1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "reg_map.h"
17 #include <algorithm>
18
19 namespace panda::compiler {
20
SetMask(const LocationMask & reg_mask,size_t priority_reg)21 void RegisterMap::SetMask(const LocationMask ®_mask, size_t priority_reg)
22 {
23 codegen_reg_map_.clear();
24
25 // Firstly map registers available for register allocator starting with the highest priority one
26 for (size_t reg = priority_reg; reg < reg_mask.GetSize(); ++reg) {
27 if (!reg_mask.IsSet(reg)) {
28 codegen_reg_map_.push_back(reg);
29 }
30 }
31 border_ = static_cast<Register>(codegen_reg_map_.size());
32
33 // Add caller registers
34 for (size_t reg = 0; reg < priority_reg; ++reg) {
35 if (!reg_mask.IsSet(reg)) {
36 codegen_reg_map_.push_back(reg);
37 }
38 }
39 available_regs_count_ = codegen_reg_map_.size();
40
41 // Now map unavailable registers, since they can be assigned to the instructions
42 for (size_t reg = 0; reg < reg_mask.GetSize(); ++reg) {
43 if (reg_mask.IsSet(reg)) {
44 codegen_reg_map_.push_back(reg);
45 }
46 }
47 }
48
SetCallerFirstMask(const LocationMask & reg_mask,size_t first_callee_reg,size_t last_callee_reg)49 void RegisterMap::SetCallerFirstMask(const LocationMask ®_mask, size_t first_callee_reg, size_t last_callee_reg)
50 {
51 codegen_reg_map_.clear();
52
53 // Add caller registers
54 for (size_t reg = 0; reg < first_callee_reg; ++reg) {
55 if (!reg_mask.IsSet(reg)) {
56 codegen_reg_map_.push_back(reg);
57 }
58 }
59
60 // Add caller registers after callees onece
61 for (size_t reg = last_callee_reg + 1; reg < reg_mask.GetSize(); ++reg) {
62 if (!reg_mask.IsSet(reg)) {
63 codegen_reg_map_.push_back(reg);
64 }
65 }
66 border_ = static_cast<Register>(codegen_reg_map_.size());
67
68 // Add callee registers
69 for (size_t reg = first_callee_reg; reg <= last_callee_reg; ++reg) {
70 if (!reg_mask.IsSet(reg)) {
71 codegen_reg_map_.push_back(reg);
72 }
73 }
74 available_regs_count_ = codegen_reg_map_.size();
75
76 // Now map unavailable registers, since they can be assigned to the instructions
77 for (size_t reg = 0; reg < reg_mask.GetSize(); ++reg) {
78 if (reg_mask.IsSet(reg)) {
79 codegen_reg_map_.push_back(reg);
80 }
81 }
82 }
83
Size() const84 size_t RegisterMap::Size() const
85 {
86 return codegen_reg_map_.size();
87 }
88
GetAvailableRegsCount() const89 size_t RegisterMap::GetAvailableRegsCount() const
90 {
91 return available_regs_count_;
92 }
93
IsRegAvailable(Register reg,Arch arch) const94 bool RegisterMap::IsRegAvailable(Register reg, Arch arch) const
95 {
96 return arch != Arch::AARCH32 || reg < available_regs_count_;
97 }
98
CodegenToRegallocReg(Register codegen_reg) const99 Register RegisterMap::CodegenToRegallocReg(Register codegen_reg) const
100 {
101 auto it = std::find(codegen_reg_map_.cbegin(), codegen_reg_map_.cend(), codegen_reg);
102 ASSERT(it != codegen_reg_map_.end());
103 return std::distance(codegen_reg_map_.cbegin(), it);
104 }
105
RegallocToCodegenReg(Register regalloc_reg) const106 Register RegisterMap::RegallocToCodegenReg(Register regalloc_reg) const
107 {
108 ASSERT(regalloc_reg < codegen_reg_map_.size());
109 return codegen_reg_map_[regalloc_reg];
110 }
111
Dump(std::ostream * out) const112 void RegisterMap::Dump(std::ostream *out) const
113 {
114 *out << "Regalloc -> Codegen" << std::endl;
115 for (size_t i = 0; i < codegen_reg_map_.size(); i++) {
116 if (i == available_regs_count_) {
117 *out << "Unavailable for RA:" << std::endl;
118 }
119 *out << "r" << std::to_string(i) << " -> r" << std::to_string(codegen_reg_map_[i]) << std::endl;
120 }
121 }
122
123 } // namespace panda::compiler
124