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
18 namespace panda::compiler {
19
SetMask(const LocationMask & reg_mask,size_t priority_reg)20 void RegisterMap::SetMask(const LocationMask ®_mask, size_t priority_reg)
21 {
22 codegen_reg_map_.clear();
23
24 // Firstly map registers available for register allocator starting with the highest priority one
25 for (size_t reg = priority_reg; reg < reg_mask.GetSize(); ++reg) {
26 if (!reg_mask.IsSet(reg)) {
27 codegen_reg_map_.push_back(reg);
28 }
29 }
30 border_ = static_cast<Register>(codegen_reg_map_.size());
31
32 // Add caller registers
33 for (size_t reg = 0; reg < priority_reg; ++reg) {
34 if (!reg_mask.IsSet(reg)) {
35 codegen_reg_map_.push_back(reg);
36 }
37 }
38 available_regs_count_ = codegen_reg_map_.size();
39
40 // Now map unavailable registers, since they can be assigned to the instructions
41 for (size_t reg = 0; reg < reg_mask.GetSize(); ++reg) {
42 if (reg_mask.IsSet(reg)) {
43 codegen_reg_map_.push_back(reg);
44 }
45 }
46 }
47
SetCallerFirstMask(const LocationMask & reg_mask,size_t first_callee_reg,size_t last_callee_reg)48 void RegisterMap::SetCallerFirstMask(const LocationMask ®_mask, size_t first_callee_reg, size_t last_callee_reg)
49 {
50 codegen_reg_map_.clear();
51
52 // Add caller registers
53 for (size_t reg = 0; reg < first_callee_reg; ++reg) {
54 if (!reg_mask.IsSet(reg)) {
55 codegen_reg_map_.push_back(reg);
56 }
57 }
58
59 // Add caller registers after callees onece
60 for (size_t reg = last_callee_reg + 1; reg < reg_mask.GetSize(); ++reg) {
61 if (!reg_mask.IsSet(reg)) {
62 codegen_reg_map_.push_back(reg);
63 }
64 }
65 border_ = static_cast<Register>(codegen_reg_map_.size());
66
67 // Add callee registers
68 for (size_t reg = first_callee_reg; reg <= last_callee_reg; ++reg) {
69 if (!reg_mask.IsSet(reg)) {
70 codegen_reg_map_.push_back(reg);
71 }
72 }
73 available_regs_count_ = codegen_reg_map_.size();
74
75 // Now map unavailable registers, since they can be assigned to the instructions
76 for (size_t reg = 0; reg < reg_mask.GetSize(); ++reg) {
77 if (reg_mask.IsSet(reg)) {
78 codegen_reg_map_.push_back(reg);
79 }
80 }
81 }
82
Size() const83 size_t RegisterMap::Size() const
84 {
85 return codegen_reg_map_.size();
86 }
87
GetAvailableRegsCount() const88 size_t RegisterMap::GetAvailableRegsCount() const
89 {
90 return available_regs_count_;
91 }
92
IsRegAvailable(Register reg,Arch arch) const93 bool RegisterMap::IsRegAvailable(Register reg, Arch arch) const
94 {
95 return arch != Arch::AARCH32 || reg < available_regs_count_;
96 }
97
CodegenToRegallocReg(Register codegen_reg) const98 Register RegisterMap::CodegenToRegallocReg(Register codegen_reg) const
99 {
100 auto it = std::find(codegen_reg_map_.cbegin(), codegen_reg_map_.cend(), codegen_reg);
101 ASSERT(it != codegen_reg_map_.end());
102 return std::distance(codegen_reg_map_.cbegin(), it);
103 }
104
RegallocToCodegenReg(Register regalloc_reg) const105 Register RegisterMap::RegallocToCodegenReg(Register regalloc_reg) const
106 {
107 ASSERT(regalloc_reg < codegen_reg_map_.size());
108 return codegen_reg_map_[regalloc_reg];
109 }
110
Dump(std::ostream * out) const111 void RegisterMap::Dump(std::ostream *out) const
112 {
113 *out << "Regalloc -> Codegen" << std::endl;
114 for (size_t i = 0; i < codegen_reg_map_.size(); i++) {
115 if (i == available_regs_count_) {
116 *out << "Unavailable for RA:" << std::endl;
117 }
118 *out << "r" << std::to_string(i) << " -> r" << std::to_string(codegen_reg_map_[i]) << std::endl;
119 }
120 }
121
122 } // namespace panda::compiler
123