• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &reg_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 &reg_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