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> ®s)
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> ®s)
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