1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ART_COMPILER_OPTIMIZING_COMMON_ARM_H_
18 #define ART_COMPILER_OPTIMIZING_COMMON_ARM_H_
19
20 #include "base/macros.h"
21 #include "instruction_simplifier_shared.h"
22 #include "locations.h"
23 #include "nodes.h"
24 #include "utils/arm/constants_arm.h"
25
26 // TODO(VIXL): Make VIXL compile with -Wshadow.
27 #pragma GCC diagnostic push
28 #pragma GCC diagnostic ignored "-Wshadow"
29 #include "aarch32/macro-assembler-aarch32.h"
30 #pragma GCC diagnostic pop
31
32 namespace art HIDDEN {
33
34 using helpers::HasShifterOperand;
35
36 namespace arm {
37 namespace helpers {
38
39 static_assert(vixl::aarch32::kSpCode == SP, "vixl::aarch32::kSpCode must equal ART's SP");
40
HighRegisterFrom(Location location)41 inline vixl::aarch32::Register HighRegisterFrom(Location location) {
42 DCHECK(location.IsRegisterPair()) << location;
43 return vixl::aarch32::Register(location.AsRegisterPairHigh<vixl::aarch32::Register>());
44 }
45
HighDRegisterFrom(Location location)46 inline vixl::aarch32::DRegister HighDRegisterFrom(Location location) {
47 DCHECK(location.IsFpuRegisterPair()) << location;
48 return vixl::aarch32::DRegister(location.AsFpuRegisterPairHigh<vixl::aarch32::DRegister>());
49 }
50
LowRegisterFrom(Location location)51 inline vixl::aarch32::Register LowRegisterFrom(Location location) {
52 DCHECK(location.IsRegisterPair()) << location;
53 return vixl::aarch32::Register(location.AsRegisterPairLow<vixl::aarch32::Register>());
54 }
55
LowSRegisterFrom(Location location)56 inline vixl::aarch32::SRegister LowSRegisterFrom(Location location) {
57 DCHECK(location.IsFpuRegisterPair()) << location;
58 return vixl::aarch32::SRegister(location.AsFpuRegisterPairLow<vixl::aarch32::SRegister>());
59 }
60
HighSRegisterFrom(Location location)61 inline vixl::aarch32::SRegister HighSRegisterFrom(Location location) {
62 DCHECK(location.IsFpuRegisterPair()) << location;
63 return vixl::aarch32::SRegister(location.AsFpuRegisterPairHigh<vixl::aarch32::SRegister>());
64 }
65
RegisterFrom(Location location)66 inline vixl::aarch32::Register RegisterFrom(Location location) {
67 DCHECK(location.IsRegister()) << location;
68 return vixl::aarch32::Register(location.reg());
69 }
70
RegisterFrom(Location location,DataType::Type type)71 inline vixl::aarch32::Register RegisterFrom(Location location, DataType::Type type) {
72 DCHECK(type != DataType::Type::kVoid && !DataType::IsFloatingPointType(type)) << type;
73 return RegisterFrom(location);
74 }
75
DRegisterFrom(Location location)76 inline vixl::aarch32::DRegister DRegisterFrom(Location location) {
77 DCHECK(location.IsFpuRegisterPair()) << location;
78 int reg_code = location.low();
79 DCHECK_EQ(reg_code % 2, 0) << reg_code;
80 return vixl::aarch32::DRegister(reg_code / 2);
81 }
82
SRegisterFrom(Location location)83 inline vixl::aarch32::SRegister SRegisterFrom(Location location) {
84 DCHECK(location.IsFpuRegister()) << location;
85 return vixl::aarch32::SRegister(location.reg());
86 }
87
OutputSRegister(HInstruction * instr)88 inline vixl::aarch32::SRegister OutputSRegister(HInstruction* instr) {
89 DataType::Type type = instr->GetType();
90 DCHECK_EQ(type, DataType::Type::kFloat32) << type;
91 return SRegisterFrom(instr->GetLocations()->Out());
92 }
93
OutputDRegister(HInstruction * instr)94 inline vixl::aarch32::DRegister OutputDRegister(HInstruction* instr) {
95 DataType::Type type = instr->GetType();
96 DCHECK_EQ(type, DataType::Type::kFloat64) << type;
97 return DRegisterFrom(instr->GetLocations()->Out());
98 }
99
OutputVRegister(HInstruction * instr)100 inline vixl::aarch32::VRegister OutputVRegister(HInstruction* instr) {
101 DataType::Type type = instr->GetType();
102 if (type == DataType::Type::kFloat32) {
103 return OutputSRegister(instr);
104 } else {
105 return OutputDRegister(instr);
106 }
107 }
108
InputSRegisterAt(HInstruction * instr,int input_index)109 inline vixl::aarch32::SRegister InputSRegisterAt(HInstruction* instr, int input_index) {
110 DataType::Type type = instr->InputAt(input_index)->GetType();
111 DCHECK_EQ(type, DataType::Type::kFloat32) << type;
112 return SRegisterFrom(instr->GetLocations()->InAt(input_index));
113 }
114
InputDRegisterAt(HInstruction * instr,int input_index)115 inline vixl::aarch32::DRegister InputDRegisterAt(HInstruction* instr, int input_index) {
116 DataType::Type type = instr->InputAt(input_index)->GetType();
117 DCHECK_EQ(type, DataType::Type::kFloat64) << type;
118 return DRegisterFrom(instr->GetLocations()->InAt(input_index));
119 }
120
InputVRegisterAt(HInstruction * instr,int input_index)121 inline vixl::aarch32::VRegister InputVRegisterAt(HInstruction* instr, int input_index) {
122 DataType::Type type = instr->InputAt(input_index)->GetType();
123 if (type == DataType::Type::kFloat32) {
124 return InputSRegisterAt(instr, input_index);
125 } else {
126 DCHECK_EQ(type, DataType::Type::kFloat64);
127 return InputDRegisterAt(instr, input_index);
128 }
129 }
130
InputVRegister(HInstruction * instr)131 inline vixl::aarch32::VRegister InputVRegister(HInstruction* instr) {
132 DCHECK_EQ(instr->InputCount(), 1u);
133 return InputVRegisterAt(instr, 0);
134 }
135
OutputRegister(HInstruction * instr)136 inline vixl::aarch32::Register OutputRegister(HInstruction* instr) {
137 return RegisterFrom(instr->GetLocations()->Out(), instr->GetType());
138 }
139
InputRegisterAt(HInstruction * instr,int input_index)140 inline vixl::aarch32::Register InputRegisterAt(HInstruction* instr, int input_index) {
141 return RegisterFrom(instr->GetLocations()->InAt(input_index),
142 instr->InputAt(input_index)->GetType());
143 }
144
InputRegister(HInstruction * instr)145 inline vixl::aarch32::Register InputRegister(HInstruction* instr) {
146 DCHECK_EQ(instr->InputCount(), 1u);
147 return InputRegisterAt(instr, 0);
148 }
149
DRegisterFromS(vixl::aarch32::SRegister s)150 inline vixl::aarch32::DRegister DRegisterFromS(vixl::aarch32::SRegister s) {
151 vixl::aarch32::DRegister d = vixl::aarch32::DRegister(s.GetCode() / 2);
152 DCHECK(s.Is(d.GetLane(0)) || s.Is(d.GetLane(1)));
153 return d;
154 }
155
Int32ConstantFrom(HInstruction * instr)156 inline int32_t Int32ConstantFrom(HInstruction* instr) {
157 if (instr->IsIntConstant()) {
158 return instr->AsIntConstant()->GetValue();
159 } else if (instr->IsNullConstant()) {
160 return 0;
161 } else {
162 DCHECK(instr->IsLongConstant()) << instr->DebugName();
163 const int64_t ret = instr->AsLongConstant()->GetValue();
164 DCHECK_GE(ret, std::numeric_limits<int32_t>::min());
165 DCHECK_LE(ret, std::numeric_limits<int32_t>::max());
166 return ret;
167 }
168 }
169
Int32ConstantFrom(Location location)170 inline int32_t Int32ConstantFrom(Location location) {
171 return Int32ConstantFrom(location.GetConstant());
172 }
173
Int64ConstantFrom(Location location)174 inline int64_t Int64ConstantFrom(Location location) {
175 HConstant* instr = location.GetConstant();
176 if (instr->IsIntConstant()) {
177 return instr->AsIntConstant()->GetValue();
178 } else if (instr->IsNullConstant()) {
179 return 0;
180 } else {
181 DCHECK(instr->IsLongConstant()) << instr->DebugName();
182 return instr->AsLongConstant()->GetValue();
183 }
184 }
185
Uint64ConstantFrom(HInstruction * instr)186 inline uint64_t Uint64ConstantFrom(HInstruction* instr) {
187 DCHECK(instr->IsConstant()) << instr->DebugName();
188 return instr->AsConstant()->GetValueAsUint64();
189 }
190
OperandFrom(Location location,DataType::Type type)191 inline vixl::aarch32::Operand OperandFrom(Location location, DataType::Type type) {
192 if (location.IsRegister()) {
193 return vixl::aarch32::Operand(RegisterFrom(location, type));
194 } else {
195 return vixl::aarch32::Operand(Int32ConstantFrom(location));
196 }
197 }
198
InputOperandAt(HInstruction * instr,int input_index)199 inline vixl::aarch32::Operand InputOperandAt(HInstruction* instr, int input_index) {
200 return OperandFrom(instr->GetLocations()->InAt(input_index),
201 instr->InputAt(input_index)->GetType());
202 }
203
LocationFrom(const vixl::aarch32::Register & reg)204 inline Location LocationFrom(const vixl::aarch32::Register& reg) {
205 return Location::RegisterLocation(reg.GetCode());
206 }
207
LocationFrom(const vixl::aarch32::SRegister & reg)208 inline Location LocationFrom(const vixl::aarch32::SRegister& reg) {
209 return Location::FpuRegisterLocation(reg.GetCode());
210 }
211
LocationFrom(const vixl::aarch32::Register & low,const vixl::aarch32::Register & high)212 inline Location LocationFrom(const vixl::aarch32::Register& low,
213 const vixl::aarch32::Register& high) {
214 return Location::RegisterPairLocation(low.GetCode(), high.GetCode());
215 }
216
LocationFrom(const vixl::aarch32::SRegister & low,const vixl::aarch32::SRegister & high)217 inline Location LocationFrom(const vixl::aarch32::SRegister& low,
218 const vixl::aarch32::SRegister& high) {
219 return Location::FpuRegisterPairLocation(low.GetCode(), high.GetCode());
220 }
221
222 } // namespace helpers
223 } // namespace arm
224 } // namespace art
225
226 #endif // ART_COMPILER_OPTIMIZING_COMMON_ARM_H_
227