• 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 #include <algorithm>
18 
19 namespace panda::compiler {
20 
SetMask(const LocationMask & reg_mask,size_t priority_reg)21 void RegisterMap::SetMask(const LocationMask &reg_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 &reg_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