• 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 /*
17 Register file implementation.
18 Reserve registers.
19 */
20 
21 #include "registers_description.h"
22 #include "target/aarch64/target.h"
23 #include "regfile.h"
24 
25 namespace panda::compiler::aarch64 {
Aarch64RegisterDescription(ArenaAllocator * allocator)26 Aarch64RegisterDescription::Aarch64RegisterDescription(ArenaAllocator *allocator)
27     : RegistersDescription(allocator, Arch::AARCH64), used_regs_(allocator->Adapter())
28 {
29 }
30 
IsRegUsed(ArenaVector<Reg> vec_reg,Reg reg)31 bool Aarch64RegisterDescription::IsRegUsed(ArenaVector<Reg> vec_reg, Reg reg)
32 {
33     auto equality = [reg](Reg in) { return (reg.GetId() == in.GetId()) && (reg.GetType() == in.GetType()); };
34     return (std::find_if(vec_reg.begin(), vec_reg.end(), equality) != vec_reg.end());
35 }
36 
GetCalleeSaved()37 ArenaVector<Reg> Aarch64RegisterDescription::GetCalleeSaved()
38 {
39     ArenaVector<Reg> out(GetAllocator()->Adapter());
40     for (uint32_t i = 0; i <= MAX_NUM_REGS; ++i) {
41         if ((callee_savedv_.GetList() & (UINT64_C(1) << i)) != 0) {
42             out.emplace_back(Reg(i, FLOAT64_TYPE));
43         }
44         if (i == MAX_NUM_REGS) {
45             break;
46         }
47         if ((callee_saved_.GetList() & (UINT64_C(1) << i)) != 0) {
48             out.emplace_back(Reg(i, INT64_TYPE));
49         }
50     }
51     return out;
52 }
53 
SetCalleeSaved(const ArenaVector<Reg> & regs)54 void Aarch64RegisterDescription::SetCalleeSaved(const ArenaVector<Reg> &regs)
55 {
56     callee_saved_ = vixl::aarch64::kCalleeSaved;
57     callee_savedv_ = vixl::aarch64::kCalleeSavedV;
58 
59     for (uint32_t i = 0; i < MAX_NUM_REGS; ++i) {
60         bool vector_used = IsRegUsed(regs, Reg(i, FLOAT64_TYPE));
61         if (vector_used) {
62             callee_savedv_.Combine(i);
63         } else {
64             callee_savedv_.Remove(i);
65         }
66         bool scalar_used = IsRegUsed(regs, Reg(i, INT64_TYPE));
67         if (scalar_used) {
68             callee_saved_.Combine(i);
69         } else {
70             callee_saved_.Remove(i);
71         }
72     }
73     // Remove return-value from callee
74     callee_saved_.Remove(0);
75 
76     // We can safely skip saving THREAD_REG if it is in the regmask
77     // of the regdescr (i.e. regalloc can not use it).
78     if (GetRegMask().Test(GetThreadReg(Arch::AARCH64))) {
79         callee_saved_.Remove(GetThreadReg(Arch::AARCH64));
80     }
81 }
82 
SetUsedRegs(const ArenaVector<Reg> & regs)83 void Aarch64RegisterDescription::SetUsedRegs(const ArenaVector<Reg> &regs)
84 {
85     used_regs_ = regs;
86 
87     // Update current lists - to do not use old data
88     callee_saved_ = vixl::aarch64::kCalleeSaved;
89     caller_saved_ = vixl::aarch64::kCallerSaved;
90 
91     // Need remove return value from callee
92     callee_saved_.Remove(0);
93 
94     // We can safely skip saving THREAD_REG if it is in the regmask
95     // of the regdescr (i.e. regalloc can not use it).
96     if (GetRegMask().Test(GetThreadReg(Arch::AARCH64))) {
97         callee_saved_.Remove(GetThreadReg(Arch::AARCH64));
98     }
99 
100     callee_savedv_ = vixl::aarch64::kCalleeSavedV;
101     caller_savedv_ = vixl::aarch64::kCallerSavedV;
102 
103     for (uint32_t i = 0; i <= MAX_NUM_REGS; ++i) {
104         // IsRegUsed use used_regs_ variable
105         bool scalar_used = IsRegUsed(used_regs_, Reg(i, INT64_TYPE));
106         if (!scalar_used && ((callee_saved_.GetList() & (UINT64_C(1) << i)) != 0)) {
107             callee_saved_.Remove(i);
108         }
109         if (!scalar_used && ((caller_saved_.GetList() & (UINT64_C(1) << i)) != 0)) {
110             caller_saved_.Remove(i);
111         }
112         bool vector_used = IsRegUsed(used_regs_, Reg(i, FLOAT64_TYPE));
113         if (!vector_used && ((callee_savedv_.GetList() & (UINT64_C(1) << i)) != 0)) {
114             callee_savedv_.Remove(i);
115             allignment_vreg_callee_ = i;
116         }
117         if (!vector_used && ((caller_savedv_.GetList() & (UINT64_C(1) << i)) != 0)) {
118             caller_savedv_.Remove(i);
119             allignment_vreg_caller_ = i;
120         }
121     }
122 }
123 
124 }  // namespace panda::compiler::aarch64
125