blob: 7b66b1798397cd5d54158b738fa5a5f5eba498ee [file] [log] [blame]
Aart Bikf8f5a162017-02-06 15:35:29 -08001/*
2 * Copyright (C) 2017 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#include "code_generator_arm_vixl.h"
Artem Serov8f7c4102017-06-21 11:21:37 +010018#include "mirror/array-inl.h"
19
20namespace vixl32 = vixl::aarch32;
21using namespace vixl32; // NOLINT(build/namespaces)
Aart Bikf8f5a162017-02-06 15:35:29 -080022
23namespace art {
24namespace arm {
25
Artem Serov8f7c4102017-06-21 11:21:37 +010026using helpers::DRegisterFrom;
27using helpers::Int64ConstantFrom;
28using helpers::InputDRegisterAt;
29using helpers::InputRegisterAt;
30using helpers::OutputDRegister;
Artem Serov6e9b1372017-10-05 16:48:30 +010031using helpers::OutputRegister;
Artem Serov8f7c4102017-06-21 11:21:37 +010032using helpers::RegisterFrom;
33
34#define __ GetVIXLAssembler()->
Aart Bikf8f5a162017-02-06 15:35:29 -080035
36void LocationsBuilderARMVIXL::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010037 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Artem Serov8f7c4102017-06-21 11:21:37 +010038 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010039 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010040 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010041 case DataType::Type::kInt8:
42 case DataType::Type::kUint16:
43 case DataType::Type::kInt16:
44 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +010045 locations->SetInAt(0, Location::RequiresRegister());
46 locations->SetOut(Location::RequiresFpuRegister());
47 break;
48 default:
Aart Bik29aa0822018-03-08 11:28:00 -080049 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +010050 UNREACHABLE();
51 }
Aart Bikf8f5a162017-02-06 15:35:29 -080052}
53
54void InstructionCodeGeneratorARMVIXL::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +010055 LocationSummary* locations = instruction->GetLocations();
56 vixl32::DRegister dst = DRegisterFrom(locations->Out());
57 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010058 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010059 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010060 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +010061 DCHECK_EQ(8u, instruction->GetVectorLength());
62 __ Vdup(Untyped8, dst, InputRegisterAt(instruction, 0));
63 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010064 case DataType::Type::kUint16:
65 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +010066 DCHECK_EQ(4u, instruction->GetVectorLength());
67 __ Vdup(Untyped16, dst, InputRegisterAt(instruction, 0));
68 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010069 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +010070 DCHECK_EQ(2u, instruction->GetVectorLength());
71 __ Vdup(Untyped32, dst, InputRegisterAt(instruction, 0));
72 break;
73 default:
Aart Bik29aa0822018-03-08 11:28:00 -080074 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +010075 UNREACHABLE();
76 }
Aart Bikf8f5a162017-02-06 15:35:29 -080077}
78
Aart Bik0148de42017-09-05 09:25:01 -070079void LocationsBuilderARMVIXL::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Artem Serov6e9b1372017-10-05 16:48:30 +010080 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
81 switch (instruction->GetPackedType()) {
82 case DataType::Type::kInt32:
83 locations->SetInAt(0, Location::RequiresFpuRegister());
84 locations->SetOut(Location::RequiresRegister());
85 break;
86 default:
Aart Bik29aa0822018-03-08 11:28:00 -080087 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov6e9b1372017-10-05 16:48:30 +010088 UNREACHABLE();
89 }
Aart Bikf8f5a162017-02-06 15:35:29 -080090}
91
Aart Bik0148de42017-09-05 09:25:01 -070092void InstructionCodeGeneratorARMVIXL::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Artem Serov6e9b1372017-10-05 16:48:30 +010093 LocationSummary* locations = instruction->GetLocations();
94 vixl32::DRegister src = DRegisterFrom(locations->InAt(0));
95 switch (instruction->GetPackedType()) {
96 case DataType::Type::kInt32:
97 DCHECK_EQ(2u, instruction->GetVectorLength());
98 __ Vmov(OutputRegister(instruction), DRegisterLane(src, 0));
99 break;
100 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800101 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov6e9b1372017-10-05 16:48:30 +0100102 UNREACHABLE();
103 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800104}
105
106// Helper to set up locations for vector unary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100107static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
108 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800109 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100110 case DataType::Type::kBool:
Artem Serov8f7c4102017-06-21 11:21:37 +0100111 locations->SetInAt(0, Location::RequiresFpuRegister());
112 locations->SetOut(Location::RequiresFpuRegister(),
113 instruction->IsVecNot() ? Location::kOutputOverlap
114 : Location::kNoOutputOverlap);
115 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100116 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100117 case DataType::Type::kInt8:
118 case DataType::Type::kUint16:
119 case DataType::Type::kInt16:
120 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100121 locations->SetInAt(0, Location::RequiresFpuRegister());
122 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800123 break;
124 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800125 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800126 UNREACHABLE();
127 }
128}
129
Aart Bik0148de42017-09-05 09:25:01 -0700130void LocationsBuilderARMVIXL::VisitVecReduce(HVecReduce* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100131 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700132}
133
134void InstructionCodeGeneratorARMVIXL::VisitVecReduce(HVecReduce* instruction) {
Artem Serov6e9b1372017-10-05 16:48:30 +0100135 LocationSummary* locations = instruction->GetLocations();
136 vixl32::DRegister src = DRegisterFrom(locations->InAt(0));
137 vixl32::DRegister dst = DRegisterFrom(locations->Out());
138 switch (instruction->GetPackedType()) {
139 case DataType::Type::kInt32:
140 DCHECK_EQ(2u, instruction->GetVectorLength());
141 switch (instruction->GetKind()) {
142 case HVecReduce::kSum:
143 __ Vpadd(DataTypeValue::I32, dst, src, src);
144 break;
145 case HVecReduce::kMin:
146 __ Vpmin(DataTypeValue::S32, dst, src, src);
147 break;
148 case HVecReduce::kMax:
149 __ Vpmax(DataTypeValue::S32, dst, src, src);
150 break;
151 }
152 break;
153 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800154 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov6e9b1372017-10-05 16:48:30 +0100155 UNREACHABLE();
156 }
Aart Bik0148de42017-09-05 09:25:01 -0700157}
158
Aart Bikf8f5a162017-02-06 15:35:29 -0800159void LocationsBuilderARMVIXL::VisitVecCnv(HVecCnv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100160 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800161}
162
163void InstructionCodeGeneratorARMVIXL::VisitVecCnv(HVecCnv* instruction) {
164 LOG(FATAL) << "No SIMD for " << instruction->GetId();
165}
166
167void LocationsBuilderARMVIXL::VisitVecNeg(HVecNeg* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100168 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800169}
170
171void InstructionCodeGeneratorARMVIXL::VisitVecNeg(HVecNeg* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100172 LocationSummary* locations = instruction->GetLocations();
173 vixl32::DRegister src = DRegisterFrom(locations->InAt(0));
174 vixl32::DRegister dst = DRegisterFrom(locations->Out());
175 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100176 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100177 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100178 DCHECK_EQ(8u, instruction->GetVectorLength());
179 __ Vneg(DataTypeValue::S8, dst, src);
180 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100181 case DataType::Type::kUint16:
182 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100183 DCHECK_EQ(4u, instruction->GetVectorLength());
184 __ Vneg(DataTypeValue::S16, dst, src);
185 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100186 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100187 DCHECK_EQ(2u, instruction->GetVectorLength());
188 __ Vneg(DataTypeValue::S32, dst, src);
189 break;
190 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800191 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100192 UNREACHABLE();
193 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800194}
195
Aart Bik6daebeb2017-04-03 14:35:41 -0700196void LocationsBuilderARMVIXL::VisitVecAbs(HVecAbs* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100197 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik6daebeb2017-04-03 14:35:41 -0700198}
199
200void InstructionCodeGeneratorARMVIXL::VisitVecAbs(HVecAbs* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100201 LocationSummary* locations = instruction->GetLocations();
202 vixl32::DRegister src = DRegisterFrom(locations->InAt(0));
203 vixl32::DRegister dst = DRegisterFrom(locations->Out());
204 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100205 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100206 DCHECK_EQ(8u, instruction->GetVectorLength());
207 __ Vabs(DataTypeValue::S8, dst, src);
208 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100209 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100210 DCHECK_EQ(4u, instruction->GetVectorLength());
211 __ Vabs(DataTypeValue::S16, dst, src);
212 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100213 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100214 DCHECK_EQ(2u, instruction->GetVectorLength());
215 __ Vabs(DataTypeValue::S32, dst, src);
216 break;
217 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800218 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100219 UNREACHABLE();
220 }
Aart Bik6daebeb2017-04-03 14:35:41 -0700221}
222
Aart Bikf8f5a162017-02-06 15:35:29 -0800223void LocationsBuilderARMVIXL::VisitVecNot(HVecNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100224 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800225}
226
227void InstructionCodeGeneratorARMVIXL::VisitVecNot(HVecNot* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100228 LocationSummary* locations = instruction->GetLocations();
229 vixl32::DRegister src = DRegisterFrom(locations->InAt(0));
230 vixl32::DRegister dst = DRegisterFrom(locations->Out());
231 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100232 case DataType::Type::kBool: // special case boolean-not
Artem Serov8f7c4102017-06-21 11:21:37 +0100233 DCHECK_EQ(8u, instruction->GetVectorLength());
234 __ Vmov(I8, dst, 1);
235 __ Veor(dst, dst, src);
236 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100237 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100238 case DataType::Type::kInt8:
239 case DataType::Type::kUint16:
240 case DataType::Type::kInt16:
241 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100242 __ Vmvn(I8, dst, src); // lanes do not matter
243 break;
244 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800245 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100246 UNREACHABLE();
247 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800248}
249
250// Helper to set up locations for vector binary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100251static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
252 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800253 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100254 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100255 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100256 case DataType::Type::kInt8:
257 case DataType::Type::kUint16:
258 case DataType::Type::kInt16:
259 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100260 locations->SetInAt(0, Location::RequiresFpuRegister());
261 locations->SetInAt(1, Location::RequiresFpuRegister());
262 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800263 break;
264 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800265 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800266 UNREACHABLE();
267 }
268}
269
270void LocationsBuilderARMVIXL::VisitVecAdd(HVecAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100271 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800272}
273
274void InstructionCodeGeneratorARMVIXL::VisitVecAdd(HVecAdd* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100275 LocationSummary* locations = instruction->GetLocations();
276 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
277 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
278 vixl32::DRegister dst = DRegisterFrom(locations->Out());
279 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100280 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100281 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100282 DCHECK_EQ(8u, instruction->GetVectorLength());
283 __ Vadd(I8, dst, lhs, rhs);
284 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100285 case DataType::Type::kUint16:
286 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100287 DCHECK_EQ(4u, instruction->GetVectorLength());
288 __ Vadd(I16, dst, lhs, rhs);
289 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100290 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100291 DCHECK_EQ(2u, instruction->GetVectorLength());
292 __ Vadd(I32, dst, lhs, rhs);
293 break;
294 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800295 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
296 UNREACHABLE();
297 }
298}
299
300void LocationsBuilderARMVIXL::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
301 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
302}
303
304void InstructionCodeGeneratorARMVIXL::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
305 LocationSummary* locations = instruction->GetLocations();
306 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
307 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
308 vixl32::DRegister dst = DRegisterFrom(locations->Out());
309 switch (instruction->GetPackedType()) {
310 case DataType::Type::kUint8:
311 DCHECK_EQ(8u, instruction->GetVectorLength());
312 __ Vqadd(DataTypeValue::U8, dst, lhs, rhs);
313 break;
314 case DataType::Type::kInt8:
315 DCHECK_EQ(8u, instruction->GetVectorLength());
316 __ Vqadd(DataTypeValue::S8, dst, lhs, rhs);
317 break;
318 case DataType::Type::kUint16:
319 DCHECK_EQ(4u, instruction->GetVectorLength());
320 __ Vqadd(DataTypeValue::U16, dst, lhs, rhs);
321 break;
322 case DataType::Type::kInt16:
323 DCHECK_EQ(4u, instruction->GetVectorLength());
324 __ Vqadd(DataTypeValue::S16, dst, lhs, rhs);
325 break;
326 default:
327 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100328 UNREACHABLE();
329 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800330}
331
Aart Bikf3e61ee2017-04-12 17:09:20 -0700332void LocationsBuilderARMVIXL::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100333 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700334}
335
336void InstructionCodeGeneratorARMVIXL::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100337 LocationSummary* locations = instruction->GetLocations();
338 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
339 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
340 vixl32::DRegister dst = DRegisterFrom(locations->Out());
341 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100342 case DataType::Type::kUint8:
343 DCHECK_EQ(8u, instruction->GetVectorLength());
344 instruction->IsRounded()
345 ? __ Vrhadd(DataTypeValue::U8, dst, lhs, rhs)
346 : __ Vhadd(DataTypeValue::U8, dst, lhs, rhs);
347 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100348 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100349 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100350 instruction->IsRounded()
351 ? __ Vrhadd(DataTypeValue::S8, dst, lhs, rhs)
352 : __ Vhadd(DataTypeValue::S8, dst, lhs, rhs);
Artem Serov8f7c4102017-06-21 11:21:37 +0100353 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100354 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100355 DCHECK_EQ(4u, instruction->GetVectorLength());
356 instruction->IsRounded()
357 ? __ Vrhadd(DataTypeValue::U16, dst, lhs, rhs)
358 : __ Vhadd(DataTypeValue::U16, dst, lhs, rhs);
359 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100360 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100361 DCHECK_EQ(4u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100362 instruction->IsRounded()
363 ? __ Vrhadd(DataTypeValue::S16, dst, lhs, rhs)
364 : __ Vhadd(DataTypeValue::S16, dst, lhs, rhs);
Artem Serov8f7c4102017-06-21 11:21:37 +0100365 break;
366 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800367 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100368 UNREACHABLE();
369 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700370}
371
Aart Bikf8f5a162017-02-06 15:35:29 -0800372void LocationsBuilderARMVIXL::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100373 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800374}
375
376void InstructionCodeGeneratorARMVIXL::VisitVecSub(HVecSub* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100377 LocationSummary* locations = instruction->GetLocations();
378 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
379 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
380 vixl32::DRegister dst = DRegisterFrom(locations->Out());
381 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100382 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100383 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100384 DCHECK_EQ(8u, instruction->GetVectorLength());
385 __ Vsub(I8, dst, lhs, rhs);
386 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100387 case DataType::Type::kUint16:
388 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100389 DCHECK_EQ(4u, instruction->GetVectorLength());
390 __ Vsub(I16, dst, lhs, rhs);
391 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100392 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100393 DCHECK_EQ(2u, instruction->GetVectorLength());
394 __ Vsub(I32, dst, lhs, rhs);
395 break;
396 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800397 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
398 UNREACHABLE();
399 }
400}
401
402void LocationsBuilderARMVIXL::VisitVecSaturationSub(HVecSaturationSub* instruction) {
403 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
404}
405
406void InstructionCodeGeneratorARMVIXL::VisitVecSaturationSub(HVecSaturationSub* instruction) {
407 LocationSummary* locations = instruction->GetLocations();
408 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
409 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
410 vixl32::DRegister dst = DRegisterFrom(locations->Out());
411 switch (instruction->GetPackedType()) {
412 case DataType::Type::kUint8:
413 DCHECK_EQ(8u, instruction->GetVectorLength());
414 __ Vqsub(DataTypeValue::U8, dst, lhs, rhs);
415 break;
416 case DataType::Type::kInt8:
417 DCHECK_EQ(8u, instruction->GetVectorLength());
418 __ Vqsub(DataTypeValue::S8, dst, lhs, rhs);
419 break;
420 case DataType::Type::kUint16:
421 DCHECK_EQ(4u, instruction->GetVectorLength());
422 __ Vqsub(DataTypeValue::U16, dst, lhs, rhs);
423 break;
424 case DataType::Type::kInt16:
425 DCHECK_EQ(4u, instruction->GetVectorLength());
426 __ Vqsub(DataTypeValue::S16, dst, lhs, rhs);
427 break;
428 default:
429 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100430 UNREACHABLE();
431 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800432}
433
434void LocationsBuilderARMVIXL::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100435 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800436}
437
438void InstructionCodeGeneratorARMVIXL::VisitVecMul(HVecMul* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100439 LocationSummary* locations = instruction->GetLocations();
440 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
441 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
442 vixl32::DRegister dst = DRegisterFrom(locations->Out());
443 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100444 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100445 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100446 DCHECK_EQ(8u, instruction->GetVectorLength());
447 __ Vmul(I8, dst, lhs, rhs);
448 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100449 case DataType::Type::kUint16:
450 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100451 DCHECK_EQ(4u, instruction->GetVectorLength());
452 __ Vmul(I16, dst, lhs, rhs);
453 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100454 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100455 DCHECK_EQ(2u, instruction->GetVectorLength());
456 __ Vmul(I32, dst, lhs, rhs);
457 break;
458 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800459 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100460 UNREACHABLE();
461 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800462}
463
464void LocationsBuilderARMVIXL::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100465 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800466}
467
468void InstructionCodeGeneratorARMVIXL::VisitVecDiv(HVecDiv* instruction) {
469 LOG(FATAL) << "No SIMD for " << instruction->GetId();
470}
471
Aart Bikf3e61ee2017-04-12 17:09:20 -0700472void LocationsBuilderARMVIXL::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100473 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700474}
475
476void InstructionCodeGeneratorARMVIXL::VisitVecMin(HVecMin* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100477 LocationSummary* locations = instruction->GetLocations();
478 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
479 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
480 vixl32::DRegister dst = DRegisterFrom(locations->Out());
481 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100482 case DataType::Type::kUint8:
483 DCHECK_EQ(8u, instruction->GetVectorLength());
484 __ Vmin(DataTypeValue::U8, dst, lhs, rhs);
485 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100486 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100487 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100488 __ Vmin(DataTypeValue::S8, dst, lhs, rhs);
Artem Serov8f7c4102017-06-21 11:21:37 +0100489 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100490 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100491 DCHECK_EQ(4u, instruction->GetVectorLength());
492 __ Vmin(DataTypeValue::U16, dst, lhs, rhs);
493 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100494 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100495 DCHECK_EQ(4u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100496 __ Vmin(DataTypeValue::S16, dst, lhs, rhs);
Artem Serov8f7c4102017-06-21 11:21:37 +0100497 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800498 case DataType::Type::kUint32:
499 DCHECK_EQ(2u, instruction->GetVectorLength());
500 __ Vmin(DataTypeValue::U32, dst, lhs, rhs);
501 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100502 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100503 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800504 __ Vmin(DataTypeValue::S32, dst, lhs, rhs);
Artem Serov8f7c4102017-06-21 11:21:37 +0100505 break;
506 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800507 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100508 UNREACHABLE();
509 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700510}
511
512void LocationsBuilderARMVIXL::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100513 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700514}
515
516void InstructionCodeGeneratorARMVIXL::VisitVecMax(HVecMax* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100517 LocationSummary* locations = instruction->GetLocations();
518 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
519 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
520 vixl32::DRegister dst = DRegisterFrom(locations->Out());
521 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100522 case DataType::Type::kUint8:
523 DCHECK_EQ(8u, instruction->GetVectorLength());
524 __ Vmax(DataTypeValue::U8, dst, lhs, rhs);
525 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100526 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100527 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100528 __ Vmax(DataTypeValue::S8, dst, lhs, rhs);
Artem Serov8f7c4102017-06-21 11:21:37 +0100529 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100530 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100531 DCHECK_EQ(4u, instruction->GetVectorLength());
532 __ Vmax(DataTypeValue::U16, dst, lhs, rhs);
533 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100534 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100535 DCHECK_EQ(4u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100536 __ Vmax(DataTypeValue::S16, dst, lhs, rhs);
Artem Serov8f7c4102017-06-21 11:21:37 +0100537 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800538 case DataType::Type::kUint32:
539 DCHECK_EQ(2u, instruction->GetVectorLength());
540 __ Vmax(DataTypeValue::U32, dst, lhs, rhs);
541 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100542 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100543 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800544 __ Vmax(DataTypeValue::S32, dst, lhs, rhs);
Artem Serov8f7c4102017-06-21 11:21:37 +0100545 break;
546 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800547 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100548 UNREACHABLE();
549 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700550}
551
Aart Bikf8f5a162017-02-06 15:35:29 -0800552void LocationsBuilderARMVIXL::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100553 // TODO: Allow constants supported by VAND (immediate).
Vladimir Markoca6fff82017-10-03 14:49:14 +0100554 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800555}
556
557void InstructionCodeGeneratorARMVIXL::VisitVecAnd(HVecAnd* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100558 LocationSummary* locations = instruction->GetLocations();
559 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
560 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
561 vixl32::DRegister dst = DRegisterFrom(locations->Out());
562 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100563 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100564 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100565 case DataType::Type::kInt8:
566 case DataType::Type::kUint16:
567 case DataType::Type::kInt16:
568 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100569 __ Vand(I8, dst, lhs, rhs);
570 break;
571 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800572 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100573 UNREACHABLE();
574 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800575}
576
577void LocationsBuilderARMVIXL::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100578 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800579}
580
581void InstructionCodeGeneratorARMVIXL::VisitVecAndNot(HVecAndNot* instruction) {
582 LOG(FATAL) << "No SIMD for " << instruction->GetId();
583}
584
585void LocationsBuilderARMVIXL::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100586 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800587}
588
589void InstructionCodeGeneratorARMVIXL::VisitVecOr(HVecOr* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100590 LocationSummary* locations = instruction->GetLocations();
591 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
592 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
593 vixl32::DRegister dst = DRegisterFrom(locations->Out());
594 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100595 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100596 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100597 case DataType::Type::kInt8:
598 case DataType::Type::kUint16:
599 case DataType::Type::kInt16:
600 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100601 __ Vorr(I8, dst, lhs, rhs);
602 break;
603 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800604 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100605 UNREACHABLE();
606 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800607}
608
609void LocationsBuilderARMVIXL::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100610 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800611}
612
613void InstructionCodeGeneratorARMVIXL::VisitVecXor(HVecXor* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100614 LocationSummary* locations = instruction->GetLocations();
615 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
616 vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1));
617 vixl32::DRegister dst = DRegisterFrom(locations->Out());
618 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100619 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100620 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100621 case DataType::Type::kInt8:
622 case DataType::Type::kUint16:
623 case DataType::Type::kInt16:
624 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100625 __ Veor(I8, dst, lhs, rhs);
626 break;
627 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800628 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100629 UNREACHABLE();
630 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800631}
632
633// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100634static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
635 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800636 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100637 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100638 case DataType::Type::kInt8:
639 case DataType::Type::kUint16:
640 case DataType::Type::kInt16:
641 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100642 locations->SetInAt(0, Location::RequiresFpuRegister());
643 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
644 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800645 break;
646 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800647 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800648 UNREACHABLE();
649 }
650}
651
652void LocationsBuilderARMVIXL::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100653 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800654}
655
656void InstructionCodeGeneratorARMVIXL::VisitVecShl(HVecShl* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100657 LocationSummary* locations = instruction->GetLocations();
658 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
659 vixl32::DRegister dst = DRegisterFrom(locations->Out());
660 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
661 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100662 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100663 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100664 DCHECK_EQ(8u, instruction->GetVectorLength());
665 __ Vshl(I8, dst, lhs, value);
666 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100667 case DataType::Type::kUint16:
668 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100669 DCHECK_EQ(4u, instruction->GetVectorLength());
670 __ Vshl(I16, dst, lhs, value);
671 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100672 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100673 DCHECK_EQ(2u, instruction->GetVectorLength());
674 __ Vshl(I32, dst, lhs, value);
675 break;
676 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800677 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100678 UNREACHABLE();
679 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800680}
681
682void LocationsBuilderARMVIXL::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100683 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800684}
685
686void InstructionCodeGeneratorARMVIXL::VisitVecShr(HVecShr* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100687 LocationSummary* locations = instruction->GetLocations();
688 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
689 vixl32::DRegister dst = DRegisterFrom(locations->Out());
690 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
691 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100692 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100693 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100694 DCHECK_EQ(8u, instruction->GetVectorLength());
695 __ Vshr(DataTypeValue::S8, dst, lhs, value);
696 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100697 case DataType::Type::kUint16:
698 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100699 DCHECK_EQ(4u, instruction->GetVectorLength());
700 __ Vshr(DataTypeValue::S16, dst, lhs, value);
701 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100702 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100703 DCHECK_EQ(2u, instruction->GetVectorLength());
704 __ Vshr(DataTypeValue::S32, dst, lhs, value);
705 break;
706 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800707 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100708 UNREACHABLE();
709 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800710}
711
712void LocationsBuilderARMVIXL::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100713 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800714}
715
716void InstructionCodeGeneratorARMVIXL::VisitVecUShr(HVecUShr* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100717 LocationSummary* locations = instruction->GetLocations();
718 vixl32::DRegister lhs = DRegisterFrom(locations->InAt(0));
719 vixl32::DRegister dst = DRegisterFrom(locations->Out());
720 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
721 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100722 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100723 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100724 DCHECK_EQ(8u, instruction->GetVectorLength());
725 __ Vshr(DataTypeValue::U8, dst, lhs, value);
726 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100727 case DataType::Type::kUint16:
728 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100729 DCHECK_EQ(4u, instruction->GetVectorLength());
730 __ Vshr(DataTypeValue::U16, dst, lhs, value);
731 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100732 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100733 DCHECK_EQ(2u, instruction->GetVectorLength());
734 __ Vshr(DataTypeValue::U32, dst, lhs, value);
735 break;
736 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800737 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100738 UNREACHABLE();
739 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800740}
741
Aart Bik0148de42017-09-05 09:25:01 -0700742void LocationsBuilderARMVIXL::VisitVecSetScalars(HVecSetScalars* instruction) {
Artem Serov6e9b1372017-10-05 16:48:30 +0100743 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
744
745 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
746
747 HInstruction* input = instruction->InputAt(0);
748 bool is_zero = IsZeroBitPattern(input);
749
750 switch (instruction->GetPackedType()) {
751 case DataType::Type::kInt32:
752 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
753 : Location::RequiresRegister());
754 locations->SetOut(Location::RequiresFpuRegister());
755 break;
756 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800757 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov6e9b1372017-10-05 16:48:30 +0100758 UNREACHABLE();
759 }
Aart Bik0148de42017-09-05 09:25:01 -0700760}
761
762void InstructionCodeGeneratorARMVIXL::VisitVecSetScalars(HVecSetScalars* instruction) {
Artem Serov6e9b1372017-10-05 16:48:30 +0100763 LocationSummary* locations = instruction->GetLocations();
764 vixl32::DRegister dst = DRegisterFrom(locations->Out());
765
766 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
767
768 // Zero out all other elements first.
769 __ Vmov(I32, dst, 0);
770
771 // Shorthand for any type of zero.
772 if (IsZeroBitPattern(instruction->InputAt(0))) {
773 return;
774 }
775
776 // Set required elements.
777 switch (instruction->GetPackedType()) {
778 case DataType::Type::kInt32:
779 DCHECK_EQ(2u, instruction->GetVectorLength());
780 __ Vmov(Untyped32, DRegisterLane(dst, 0), InputRegisterAt(instruction, 0));
781 break;
782 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800783 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov6e9b1372017-10-05 16:48:30 +0100784 UNREACHABLE();
785 }
Aart Bik0148de42017-09-05 09:25:01 -0700786}
787
Aart Bikdbbac8f2017-09-01 13:06:08 -0700788// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100789static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
790 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -0700791 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100792 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100793 case DataType::Type::kInt8:
794 case DataType::Type::kUint16:
795 case DataType::Type::kInt16:
796 case DataType::Type::kInt32:
797 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700798 locations->SetInAt(0, Location::RequiresFpuRegister());
799 locations->SetInAt(1, Location::RequiresFpuRegister());
800 locations->SetInAt(2, Location::RequiresFpuRegister());
801 locations->SetOut(Location::SameAsFirstInput());
802 break;
803 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800804 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -0700805 UNREACHABLE();
806 }
Artem Serovf34dd202017-04-10 17:41:46 +0100807}
808
Aart Bikdbbac8f2017-09-01 13:06:08 -0700809void LocationsBuilderARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100810 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -0700811}
812
813void InstructionCodeGeneratorARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
814 LOG(FATAL) << "No SIMD for " << instruction->GetId();
815}
816
817void LocationsBuilderARMVIXL::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100818 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -0700819}
820
821void InstructionCodeGeneratorARMVIXL::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Artem Serov6e9b1372017-10-05 16:48:30 +0100822 LocationSummary* locations = instruction->GetLocations();
823 vixl32::DRegister acc = DRegisterFrom(locations->InAt(0));
824 vixl32::DRegister left = DRegisterFrom(locations->InAt(1));
825 vixl32::DRegister right = DRegisterFrom(locations->InAt(2));
826
827 DCHECK(locations->InAt(0).Equals(locations->Out()));
828
829 // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
830 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
831 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
832 DCHECK_EQ(a->GetPackedType(), b->GetPackedType());
833 switch (a->GetPackedType()) {
834 case DataType::Type::kInt32:
835 DCHECK_EQ(2u, a->GetVectorLength());
836 switch (instruction->GetPackedType()) {
837 case DataType::Type::kInt32: {
838 DCHECK_EQ(2u, instruction->GetVectorLength());
839 UseScratchRegisterScope temps(GetVIXLAssembler());
840 vixl32::DRegister tmp = temps.AcquireD();
841 __ Vsub(DataTypeValue::I32, tmp, left, right);
842 __ Vabs(DataTypeValue::S32, tmp, tmp);
843 __ Vadd(DataTypeValue::I32, acc, acc, tmp);
844 break;
845 }
846 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800847 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov6e9b1372017-10-05 16:48:30 +0100848 UNREACHABLE();
849 }
850 break;
851 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800852 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov6e9b1372017-10-05 16:48:30 +0100853 UNREACHABLE();
854 }
Artem Serovf34dd202017-04-10 17:41:46 +0100855}
856
Artem Serov8f7c4102017-06-21 11:21:37 +0100857// Return whether the vector memory access operation is guaranteed to be word-aligned (ARM word
858// size equals to 4).
859static bool IsWordAligned(HVecMemoryOperation* instruction) {
860 return instruction->GetAlignment().IsAlignedAt(4u);
861}
862
863// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100864static void CreateVecMemLocations(ArenaAllocator* allocator,
Artem Serov8f7c4102017-06-21 11:21:37 +0100865 HVecMemoryOperation* instruction,
866 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100867 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Artem Serov8f7c4102017-06-21 11:21:37 +0100868 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100869 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100870 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100871 case DataType::Type::kInt8:
872 case DataType::Type::kUint16:
873 case DataType::Type::kInt16:
874 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100875 locations->SetInAt(0, Location::RequiresRegister());
876 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
877 if (is_load) {
878 locations->SetOut(Location::RequiresFpuRegister());
879 } else {
880 locations->SetInAt(2, Location::RequiresFpuRegister());
881 }
882 break;
883 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800884 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100885 UNREACHABLE();
886 }
887}
888
889// Helper to set up locations for vector memory operations. Returns the memory operand and,
890// if used, sets the output parameter scratch to a temporary register used in this operand,
891// so that the client can release it right after the memory operand use.
892MemOperand InstructionCodeGeneratorARMVIXL::VecAddress(
893 HVecMemoryOperation* instruction,
894 UseScratchRegisterScope* temps_scope,
895 /*out*/ vixl32::Register* scratch) {
896 LocationSummary* locations = instruction->GetLocations();
897 vixl32::Register base = InputRegisterAt(instruction, 0);
898
899 Location index = locations->InAt(1);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100900 size_t size = DataType::Size(instruction->GetPackedType());
Artem Serov8f7c4102017-06-21 11:21:37 +0100901 uint32_t offset = mirror::Array::DataOffset(size).Uint32Value();
902 size_t shift = ComponentSizeShiftWidth(size);
903
904 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
905 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
906
907 if (index.IsConstant()) {
908 offset += Int64ConstantFrom(index) << shift;
909 return MemOperand(base, offset);
910 } else {
911 *scratch = temps_scope->Acquire();
912 __ Add(*scratch, base, Operand(RegisterFrom(index), ShiftType::LSL, shift));
913
914 return MemOperand(*scratch, offset);
915 }
916}
917
918AlignedMemOperand InstructionCodeGeneratorARMVIXL::VecAddressUnaligned(
919 HVecMemoryOperation* instruction,
920 UseScratchRegisterScope* temps_scope,
921 /*out*/ vixl32::Register* scratch) {
922 LocationSummary* locations = instruction->GetLocations();
923 vixl32::Register base = InputRegisterAt(instruction, 0);
924
925 Location index = locations->InAt(1);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100926 size_t size = DataType::Size(instruction->GetPackedType());
Artem Serov8f7c4102017-06-21 11:21:37 +0100927 uint32_t offset = mirror::Array::DataOffset(size).Uint32Value();
928 size_t shift = ComponentSizeShiftWidth(size);
929
930 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
931 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
932
933 if (index.IsConstant()) {
934 offset += Int64ConstantFrom(index) << shift;
935 __ Add(*scratch, base, offset);
936 } else {
937 *scratch = temps_scope->Acquire();
938 __ Add(*scratch, base, offset);
939 __ Add(*scratch, *scratch, Operand(RegisterFrom(index), ShiftType::LSL, shift));
940 }
941 return AlignedMemOperand(*scratch, kNoAlignment);
942}
943
Aart Bikf8f5a162017-02-06 15:35:29 -0800944void LocationsBuilderARMVIXL::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100945 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bikf8f5a162017-02-06 15:35:29 -0800946}
947
948void InstructionCodeGeneratorARMVIXL::VisitVecLoad(HVecLoad* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +0100949 vixl32::DRegister reg = OutputDRegister(instruction);
950 UseScratchRegisterScope temps(GetVIXLAssembler());
951 vixl32::Register scratch;
952
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100953 DCHECK(instruction->GetPackedType() != DataType::Type::kUint16 || !instruction->IsStringCharAt());
Artem Serov8f7c4102017-06-21 11:21:37 +0100954
955 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100956 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100957 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100958 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +0100959 DCHECK_EQ(8u, instruction->GetVectorLength());
960 if (IsWordAligned(instruction)) {
961 __ Vldr(reg, VecAddress(instruction, &temps, &scratch));
962 } else {
963 __ Vld1(Untyped8,
964 NeonRegisterList(reg, kMultipleLanes),
965 VecAddressUnaligned(instruction, &temps, &scratch));
966 }
967 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100968 case DataType::Type::kUint16:
969 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +0100970 DCHECK_EQ(4u, instruction->GetVectorLength());
971 if (IsWordAligned(instruction)) {
972 __ Vldr(reg, VecAddress(instruction, &temps, &scratch));
973 } else {
974 __ Vld1(Untyped16,
975 NeonRegisterList(reg, kMultipleLanes),
976 VecAddressUnaligned(instruction, &temps, &scratch));
977 }
978 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100979 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +0100980 DCHECK_EQ(2u, instruction->GetVectorLength());
981 if (IsWordAligned(instruction)) {
982 __ Vldr(reg, VecAddress(instruction, &temps, &scratch));
983 } else {
984 __ Vld1(Untyped32,
985 NeonRegisterList(reg, kMultipleLanes),
986 VecAddressUnaligned(instruction, &temps, &scratch));
987 }
988 break;
989 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800990 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +0100991 UNREACHABLE();
992 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800993}
994
995void LocationsBuilderARMVIXL::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100996 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -0800997}
998
999void InstructionCodeGeneratorARMVIXL::VisitVecStore(HVecStore* instruction) {
Artem Serov8f7c4102017-06-21 11:21:37 +01001000 vixl32::DRegister reg = InputDRegisterAt(instruction, 2);
1001 UseScratchRegisterScope temps(GetVIXLAssembler());
1002 vixl32::Register scratch;
1003 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001004 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001005 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001006 case DataType::Type::kInt8:
Artem Serov8f7c4102017-06-21 11:21:37 +01001007 DCHECK_EQ(8u, instruction->GetVectorLength());
1008 if (IsWordAligned(instruction)) {
1009 __ Vstr(reg, VecAddress(instruction, &temps, &scratch));
1010 } else {
1011 __ Vst1(Untyped8,
1012 NeonRegisterList(reg, kMultipleLanes),
1013 VecAddressUnaligned(instruction, &temps, &scratch));
1014 }
1015 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001016 case DataType::Type::kUint16:
1017 case DataType::Type::kInt16:
Artem Serov8f7c4102017-06-21 11:21:37 +01001018 DCHECK_EQ(4u, instruction->GetVectorLength());
1019 if (IsWordAligned(instruction)) {
1020 __ Vstr(reg, VecAddress(instruction, &temps, &scratch));
1021 } else {
1022 __ Vst1(Untyped16,
1023 NeonRegisterList(reg, kMultipleLanes),
1024 VecAddressUnaligned(instruction, &temps, &scratch));
1025 }
1026 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001027 case DataType::Type::kInt32:
Artem Serov8f7c4102017-06-21 11:21:37 +01001028 DCHECK_EQ(2u, instruction->GetVectorLength());
1029 if (IsWordAligned(instruction)) {
1030 __ Vstr(reg, VecAddress(instruction, &temps, &scratch));
1031 } else {
1032 __ Vst1(Untyped32,
1033 NeonRegisterList(reg, kMultipleLanes),
1034 VecAddressUnaligned(instruction, &temps, &scratch));
1035 }
1036 break;
1037 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001038 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serov8f7c4102017-06-21 11:21:37 +01001039 UNREACHABLE();
1040 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001041}
1042
1043#undef __
1044
1045} // namespace arm
1046} // namespace art