blob: 10aced02c3f40aebcd43ad392955fd80f9fedf25 [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_arm64.h"
Andreas Gampe895f9222017-07-05 09:53:32 -070018
Aart Bikf8f5a162017-02-06 15:35:29 -080019#include "mirror/array-inl.h"
Andreas Gampe895f9222017-07-05 09:53:32 -070020#include "mirror/string.h"
Aart Bikf8f5a162017-02-06 15:35:29 -080021
22using namespace vixl::aarch64; // NOLINT(build/namespaces)
23
24namespace art {
25namespace arm64 {
26
Artem Serov8dfe7462017-06-01 14:28:48 +010027using helpers::ARM64EncodableConstantOrRegister;
28using helpers::Arm64CanEncodeConstantAsImmediate;
Aart Bik472821b2017-04-27 17:23:51 -070029using helpers::DRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080030using helpers::HeapOperand;
31using helpers::InputRegisterAt;
32using helpers::Int64ConstantFrom;
Aart Bik0148de42017-09-05 09:25:01 -070033using helpers::OutputRegister;
34using helpers::VRegisterFrom;
Nicolas Geoffray982334c2017-09-02 12:54:16 +000035using helpers::WRegisterFrom;
Aart Bik0148de42017-09-05 09:25:01 -070036using helpers::XRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080037
38#define __ GetVIXLAssembler()->
39
40void LocationsBuilderARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010041 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Artem Serov8dfe7462017-06-01 14:28:48 +010042 HInstruction* input = instruction->InputAt(0);
Aart Bikf8f5a162017-02-06 15:35:29 -080043 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010044 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010045 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010046 case DataType::Type::kInt8:
47 case DataType::Type::kUint16:
48 case DataType::Type::kInt16:
49 case DataType::Type::kInt32:
50 case DataType::Type::kInt64:
Artem Serov8dfe7462017-06-01 14:28:48 +010051 locations->SetInAt(0, ARM64EncodableConstantOrRegister(input, instruction));
Aart Bikf8f5a162017-02-06 15:35:29 -080052 locations->SetOut(Location::RequiresFpuRegister());
53 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010054 case DataType::Type::kFloat32:
55 case DataType::Type::kFloat64:
Artem Serov8dfe7462017-06-01 14:28:48 +010056 if (input->IsConstant() &&
57 Arm64CanEncodeConstantAsImmediate(input->AsConstant(), instruction)) {
58 locations->SetInAt(0, Location::ConstantLocation(input->AsConstant()));
59 locations->SetOut(Location::RequiresFpuRegister());
60 } else {
61 locations->SetInAt(0, Location::RequiresFpuRegister());
62 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
63 }
Aart Bikf8f5a162017-02-06 15:35:29 -080064 break;
65 default:
66 LOG(FATAL) << "Unsupported SIMD type";
67 UNREACHABLE();
68 }
69}
70
71void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
72 LocationSummary* locations = instruction->GetLocations();
Artem Serov8dfe7462017-06-01 14:28:48 +010073 Location src_loc = locations->InAt(0);
Artem Serovb31f91f2017-04-05 11:31:19 +010074 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -080075 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010076 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010077 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010078 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +010079 DCHECK_EQ(16u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010080 if (src_loc.IsConstant()) {
81 __ Movi(dst.V16B(), Int64ConstantFrom(src_loc));
82 } else {
83 __ Dup(dst.V16B(), InputRegisterAt(instruction, 0));
84 }
Aart Bikf8f5a162017-02-06 15:35:29 -080085 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010086 case DataType::Type::kUint16:
87 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +010088 DCHECK_EQ(8u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010089 if (src_loc.IsConstant()) {
90 __ Movi(dst.V8H(), Int64ConstantFrom(src_loc));
91 } else {
92 __ Dup(dst.V8H(), InputRegisterAt(instruction, 0));
93 }
Aart Bikf8f5a162017-02-06 15:35:29 -080094 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010095 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +010096 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010097 if (src_loc.IsConstant()) {
98 __ Movi(dst.V4S(), Int64ConstantFrom(src_loc));
99 } else {
100 __ Dup(dst.V4S(), InputRegisterAt(instruction, 0));
101 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800102 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100103 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100104 DCHECK_EQ(2u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100105 if (src_loc.IsConstant()) {
106 __ Movi(dst.V2D(), Int64ConstantFrom(src_loc));
107 } else {
108 __ Dup(dst.V2D(), XRegisterFrom(src_loc));
109 }
Artem Serovb31f91f2017-04-05 11:31:19 +0100110 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100111 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100112 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100113 if (src_loc.IsConstant()) {
114 __ Fmov(dst.V4S(), src_loc.GetConstant()->AsFloatConstant()->GetValue());
115 } else {
116 __ Dup(dst.V4S(), VRegisterFrom(src_loc).V4S(), 0);
117 }
Artem Serovb31f91f2017-04-05 11:31:19 +0100118 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100119 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100120 DCHECK_EQ(2u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100121 if (src_loc.IsConstant()) {
122 __ Fmov(dst.V2D(), src_loc.GetConstant()->AsDoubleConstant()->GetValue());
123 } else {
124 __ Dup(dst.V2D(), VRegisterFrom(src_loc).V2D(), 0);
125 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800126 break;
127 default:
128 LOG(FATAL) << "Unsupported SIMD type";
129 UNREACHABLE();
130 }
131}
132
Aart Bik0148de42017-09-05 09:25:01 -0700133void LocationsBuilderARM64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100134 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700135 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100136 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100137 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100138 case DataType::Type::kInt8:
139 case DataType::Type::kUint16:
140 case DataType::Type::kInt16:
141 case DataType::Type::kInt32:
142 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700143 locations->SetInAt(0, Location::RequiresFpuRegister());
144 locations->SetOut(Location::RequiresRegister());
145 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100146 case DataType::Type::kFloat32:
147 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700148 locations->SetInAt(0, Location::RequiresFpuRegister());
149 locations->SetOut(Location::SameAsFirstInput());
150 break;
151 default:
152 LOG(FATAL) << "Unsupported SIMD type";
153 UNREACHABLE();
154 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800155}
156
Aart Bik0148de42017-09-05 09:25:01 -0700157void InstructionCodeGeneratorARM64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
158 LocationSummary* locations = instruction->GetLocations();
159 VRegister src = VRegisterFrom(locations->InAt(0));
160 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100161 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700162 DCHECK_EQ(4u, instruction->GetVectorLength());
163 __ Umov(OutputRegister(instruction), src.V4S(), 0);
164 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100165 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700166 DCHECK_EQ(2u, instruction->GetVectorLength());
167 __ Umov(OutputRegister(instruction), src.V2D(), 0);
168 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100169 case DataType::Type::kFloat32:
170 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700171 DCHECK_LE(2u, instruction->GetVectorLength());
172 DCHECK_LE(instruction->GetVectorLength(), 4u);
173 DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required
174 break;
175 default:
176 LOG(FATAL) << "Unsupported SIMD type";
177 UNREACHABLE();
178 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800179}
180
181// Helper to set up locations for vector unary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100182static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
183 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800184 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100185 case DataType::Type::kBool:
Aart Bikf8f5a162017-02-06 15:35:29 -0800186 locations->SetInAt(0, Location::RequiresFpuRegister());
187 locations->SetOut(Location::RequiresFpuRegister(),
188 instruction->IsVecNot() ? Location::kOutputOverlap
189 : Location::kNoOutputOverlap);
190 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100191 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100192 case DataType::Type::kInt8:
193 case DataType::Type::kUint16:
194 case DataType::Type::kInt16:
195 case DataType::Type::kInt32:
196 case DataType::Type::kInt64:
197 case DataType::Type::kFloat32:
198 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800199 locations->SetInAt(0, Location::RequiresFpuRegister());
200 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
201 break;
202 default:
203 LOG(FATAL) << "Unsupported SIMD type";
204 UNREACHABLE();
205 }
206}
207
Aart Bik0148de42017-09-05 09:25:01 -0700208void LocationsBuilderARM64::VisitVecReduce(HVecReduce* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100209 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700210}
211
212void InstructionCodeGeneratorARM64::VisitVecReduce(HVecReduce* instruction) {
213 LocationSummary* locations = instruction->GetLocations();
214 VRegister src = VRegisterFrom(locations->InAt(0));
215 VRegister dst = DRegisterFrom(locations->Out());
216 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100217 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700218 DCHECK_EQ(4u, instruction->GetVectorLength());
219 switch (instruction->GetKind()) {
220 case HVecReduce::kSum:
221 __ Addv(dst.S(), src.V4S());
222 break;
223 case HVecReduce::kMin:
224 __ Sminv(dst.S(), src.V4S());
225 break;
226 case HVecReduce::kMax:
227 __ Smaxv(dst.S(), src.V4S());
228 break;
229 }
230 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100231 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700232 DCHECK_EQ(2u, instruction->GetVectorLength());
233 switch (instruction->GetKind()) {
234 case HVecReduce::kSum:
235 __ Addp(dst.D(), src.V2D());
236 break;
237 default:
238 LOG(FATAL) << "Unsupported SIMD min/max";
239 UNREACHABLE();
240 }
241 break;
242 default:
243 LOG(FATAL) << "Unsupported SIMD type";
244 UNREACHABLE();
245 }
246}
247
Aart Bikf8f5a162017-02-06 15:35:29 -0800248void LocationsBuilderARM64::VisitVecCnv(HVecCnv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100249 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800250}
251
252void InstructionCodeGeneratorARM64::VisitVecCnv(HVecCnv* instruction) {
253 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100254 VRegister src = VRegisterFrom(locations->InAt(0));
255 VRegister dst = VRegisterFrom(locations->Out());
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100256 DataType::Type from = instruction->GetInputType();
257 DataType::Type to = instruction->GetResultType();
258 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Artem Serovd4bccf12017-04-03 18:47:32 +0100259 DCHECK_EQ(4u, instruction->GetVectorLength());
260 __ Scvtf(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800261 } else {
262 LOG(FATAL) << "Unsupported SIMD type";
263 }
264}
265
266void LocationsBuilderARM64::VisitVecNeg(HVecNeg* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100267 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800268}
269
270void InstructionCodeGeneratorARM64::VisitVecNeg(HVecNeg* instruction) {
271 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100272 VRegister src = VRegisterFrom(locations->InAt(0));
273 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800274 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100275 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100276 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100277 DCHECK_EQ(16u, instruction->GetVectorLength());
278 __ Neg(dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800279 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100280 case DataType::Type::kUint16:
281 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100282 DCHECK_EQ(8u, instruction->GetVectorLength());
283 __ Neg(dst.V8H(), src.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800284 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100285 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100286 DCHECK_EQ(4u, instruction->GetVectorLength());
287 __ Neg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800288 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100289 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100290 DCHECK_EQ(2u, instruction->GetVectorLength());
291 __ Neg(dst.V2D(), src.V2D());
292 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100293 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100294 DCHECK_EQ(4u, instruction->GetVectorLength());
295 __ Fneg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800296 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100297 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100298 DCHECK_EQ(2u, instruction->GetVectorLength());
299 __ Fneg(dst.V2D(), src.V2D());
300 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800301 default:
302 LOG(FATAL) << "Unsupported SIMD type";
303 UNREACHABLE();
304 }
305}
306
Aart Bik6daebeb2017-04-03 14:35:41 -0700307void LocationsBuilderARM64::VisitVecAbs(HVecAbs* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100308 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik6daebeb2017-04-03 14:35:41 -0700309}
310
311void InstructionCodeGeneratorARM64::VisitVecAbs(HVecAbs* instruction) {
312 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100313 VRegister src = VRegisterFrom(locations->InAt(0));
314 VRegister dst = VRegisterFrom(locations->Out());
Aart Bik6daebeb2017-04-03 14:35:41 -0700315 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100316 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100317 DCHECK_EQ(16u, instruction->GetVectorLength());
318 __ Abs(dst.V16B(), src.V16B());
Aart Bik6daebeb2017-04-03 14:35:41 -0700319 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100320 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100321 DCHECK_EQ(8u, instruction->GetVectorLength());
322 __ Abs(dst.V8H(), src.V8H());
Aart Bik6daebeb2017-04-03 14:35:41 -0700323 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100324 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100325 DCHECK_EQ(4u, instruction->GetVectorLength());
326 __ Abs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700327 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100328 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100329 DCHECK_EQ(2u, instruction->GetVectorLength());
330 __ Abs(dst.V2D(), src.V2D());
331 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100332 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100333 DCHECK_EQ(4u, instruction->GetVectorLength());
334 __ Fabs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700335 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100336 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100337 DCHECK_EQ(2u, instruction->GetVectorLength());
338 __ Fabs(dst.V2D(), src.V2D());
339 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700340 default:
341 LOG(FATAL) << "Unsupported SIMD type";
Aart Bik0148de42017-09-05 09:25:01 -0700342 UNREACHABLE();
Aart Bik6daebeb2017-04-03 14:35:41 -0700343 }
344}
345
Aart Bikf8f5a162017-02-06 15:35:29 -0800346void LocationsBuilderARM64::VisitVecNot(HVecNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100347 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800348}
349
350void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) {
351 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100352 VRegister src = VRegisterFrom(locations->InAt(0));
353 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800354 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100355 case DataType::Type::kBool: // special case boolean-not
Artem Serovd4bccf12017-04-03 18:47:32 +0100356 DCHECK_EQ(16u, instruction->GetVectorLength());
357 __ Movi(dst.V16B(), 1);
358 __ Eor(dst.V16B(), dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800359 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100360 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100361 case DataType::Type::kInt8:
362 case DataType::Type::kUint16:
363 case DataType::Type::kInt16:
364 case DataType::Type::kInt32:
365 case DataType::Type::kInt64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100366 __ Not(dst.V16B(), src.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800367 break;
368 default:
369 LOG(FATAL) << "Unsupported SIMD type";
370 UNREACHABLE();
371 }
372}
373
374// Helper to set up locations for vector binary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100375static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
376 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800377 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100378 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100379 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100380 case DataType::Type::kInt8:
381 case DataType::Type::kUint16:
382 case DataType::Type::kInt16:
383 case DataType::Type::kInt32:
384 case DataType::Type::kInt64:
385 case DataType::Type::kFloat32:
386 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800387 locations->SetInAt(0, Location::RequiresFpuRegister());
388 locations->SetInAt(1, Location::RequiresFpuRegister());
389 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
390 break;
391 default:
392 LOG(FATAL) << "Unsupported SIMD type";
393 UNREACHABLE();
394 }
395}
396
397void LocationsBuilderARM64::VisitVecAdd(HVecAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100398 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800399}
400
401void InstructionCodeGeneratorARM64::VisitVecAdd(HVecAdd* instruction) {
402 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100403 VRegister lhs = VRegisterFrom(locations->InAt(0));
404 VRegister rhs = VRegisterFrom(locations->InAt(1));
405 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800406 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100407 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100408 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100409 DCHECK_EQ(16u, instruction->GetVectorLength());
410 __ Add(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800411 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100412 case DataType::Type::kUint16:
413 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100414 DCHECK_EQ(8u, instruction->GetVectorLength());
415 __ Add(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800416 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100417 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100418 DCHECK_EQ(4u, instruction->GetVectorLength());
419 __ Add(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800420 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100421 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100422 DCHECK_EQ(2u, instruction->GetVectorLength());
423 __ Add(dst.V2D(), lhs.V2D(), rhs.V2D());
424 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100425 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100426 DCHECK_EQ(4u, instruction->GetVectorLength());
427 __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800428 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100429 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100430 DCHECK_EQ(2u, instruction->GetVectorLength());
431 __ Fadd(dst.V2D(), lhs.V2D(), rhs.V2D());
432 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800433 default:
434 LOG(FATAL) << "Unsupported SIMD type";
435 UNREACHABLE();
436 }
437}
438
Aart Bikf3e61ee2017-04-12 17:09:20 -0700439void LocationsBuilderARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100440 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700441}
442
443void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
444 LocationSummary* locations = instruction->GetLocations();
445 VRegister lhs = VRegisterFrom(locations->InAt(0));
446 VRegister rhs = VRegisterFrom(locations->InAt(1));
447 VRegister dst = VRegisterFrom(locations->Out());
448 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100449 case DataType::Type::kUint8:
450 DCHECK_EQ(16u, instruction->GetVectorLength());
451 instruction->IsRounded()
452 ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
453 : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
454 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100455 case DataType::Type::kInt8:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700456 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100457 instruction->IsRounded()
458 ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
459 : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700460 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100461 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100462 DCHECK_EQ(8u, instruction->GetVectorLength());
463 instruction->IsRounded()
464 ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
465 : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
466 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100467 case DataType::Type::kInt16:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700468 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100469 instruction->IsRounded()
470 ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
471 : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700472 break;
473 default:
474 LOG(FATAL) << "Unsupported SIMD type";
475 UNREACHABLE();
476 }
477}
478
Aart Bikf8f5a162017-02-06 15:35:29 -0800479void LocationsBuilderARM64::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100480 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800481}
482
483void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* instruction) {
484 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100485 VRegister lhs = VRegisterFrom(locations->InAt(0));
486 VRegister rhs = VRegisterFrom(locations->InAt(1));
487 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800488 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100489 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100490 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100491 DCHECK_EQ(16u, instruction->GetVectorLength());
492 __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800493 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100494 case DataType::Type::kUint16:
495 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100496 DCHECK_EQ(8u, instruction->GetVectorLength());
497 __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800498 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100499 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100500 DCHECK_EQ(4u, instruction->GetVectorLength());
501 __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800502 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100503 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100504 DCHECK_EQ(2u, instruction->GetVectorLength());
505 __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D());
506 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100507 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100508 DCHECK_EQ(4u, instruction->GetVectorLength());
509 __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800510 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100511 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100512 DCHECK_EQ(2u, instruction->GetVectorLength());
513 __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D());
514 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800515 default:
516 LOG(FATAL) << "Unsupported SIMD type";
517 UNREACHABLE();
518 }
519}
520
521void LocationsBuilderARM64::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100522 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800523}
524
525void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) {
526 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100527 VRegister lhs = VRegisterFrom(locations->InAt(0));
528 VRegister rhs = VRegisterFrom(locations->InAt(1));
529 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800530 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100531 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100532 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100533 DCHECK_EQ(16u, instruction->GetVectorLength());
534 __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800535 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100536 case DataType::Type::kUint16:
537 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100538 DCHECK_EQ(8u, instruction->GetVectorLength());
539 __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800540 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100541 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100542 DCHECK_EQ(4u, instruction->GetVectorLength());
543 __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800544 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100545 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100546 DCHECK_EQ(4u, instruction->GetVectorLength());
547 __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800548 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100549 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100550 DCHECK_EQ(2u, instruction->GetVectorLength());
551 __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D());
552 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800553 default:
554 LOG(FATAL) << "Unsupported SIMD type";
555 UNREACHABLE();
556 }
557}
558
559void LocationsBuilderARM64::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100560 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800561}
562
563void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) {
564 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100565 VRegister lhs = VRegisterFrom(locations->InAt(0));
566 VRegister rhs = VRegisterFrom(locations->InAt(1));
567 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800568 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100569 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100570 DCHECK_EQ(4u, instruction->GetVectorLength());
571 __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800572 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100573 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100574 DCHECK_EQ(2u, instruction->GetVectorLength());
575 __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D());
576 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800577 default:
578 LOG(FATAL) << "Unsupported SIMD type";
579 UNREACHABLE();
580 }
581}
582
Aart Bikf3e61ee2017-04-12 17:09:20 -0700583void LocationsBuilderARM64::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100584 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700585}
586
587void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700588 LocationSummary* locations = instruction->GetLocations();
589 VRegister lhs = VRegisterFrom(locations->InAt(0));
590 VRegister rhs = VRegisterFrom(locations->InAt(1));
591 VRegister dst = VRegisterFrom(locations->Out());
592 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100593 case DataType::Type::kUint8:
594 DCHECK_EQ(16u, instruction->GetVectorLength());
595 __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
596 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100597 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700598 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100599 __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikc8e93c72017-05-10 10:49:22 -0700600 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100601 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100602 DCHECK_EQ(8u, instruction->GetVectorLength());
603 __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
604 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100605 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700606 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100607 __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikc8e93c72017-05-10 10:49:22 -0700608 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100609 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700610 DCHECK_EQ(4u, instruction->GetVectorLength());
611 if (instruction->IsUnsigned()) {
612 __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S());
613 } else {
614 __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S());
615 }
616 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100617 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700618 DCHECK_EQ(4u, instruction->GetVectorLength());
619 DCHECK(!instruction->IsUnsigned());
620 __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S());
621 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100622 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700623 DCHECK_EQ(2u, instruction->GetVectorLength());
624 DCHECK(!instruction->IsUnsigned());
625 __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D());
626 break;
627 default:
628 LOG(FATAL) << "Unsupported SIMD type";
629 UNREACHABLE();
630 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700631}
632
633void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100634 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700635}
636
637void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700638 LocationSummary* locations = instruction->GetLocations();
639 VRegister lhs = VRegisterFrom(locations->InAt(0));
640 VRegister rhs = VRegisterFrom(locations->InAt(1));
641 VRegister dst = VRegisterFrom(locations->Out());
642 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100643 case DataType::Type::kUint8:
644 DCHECK_EQ(16u, instruction->GetVectorLength());
645 __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
646 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100647 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700648 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100649 __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikc8e93c72017-05-10 10:49:22 -0700650 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100651 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100652 DCHECK_EQ(8u, instruction->GetVectorLength());
653 __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
654 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100655 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700656 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100657 __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikc8e93c72017-05-10 10:49:22 -0700658 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100659 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700660 DCHECK_EQ(4u, instruction->GetVectorLength());
661 if (instruction->IsUnsigned()) {
662 __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S());
663 } else {
664 __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S());
665 }
666 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100667 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700668 DCHECK_EQ(4u, instruction->GetVectorLength());
669 DCHECK(!instruction->IsUnsigned());
670 __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S());
671 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100672 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700673 DCHECK_EQ(2u, instruction->GetVectorLength());
674 DCHECK(!instruction->IsUnsigned());
675 __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D());
676 break;
677 default:
678 LOG(FATAL) << "Unsupported SIMD type";
679 UNREACHABLE();
680 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700681}
682
Aart Bikf8f5a162017-02-06 15:35:29 -0800683void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100684 // TODO: Allow constants supported by BIC (vector, immediate).
Vladimir Markoca6fff82017-10-03 14:49:14 +0100685 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800686}
687
688void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
689 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100690 VRegister lhs = VRegisterFrom(locations->InAt(0));
691 VRegister rhs = VRegisterFrom(locations->InAt(1));
692 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800693 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100694 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100695 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100696 case DataType::Type::kInt8:
697 case DataType::Type::kUint16:
698 case DataType::Type::kInt16:
699 case DataType::Type::kInt32:
700 case DataType::Type::kInt64:
701 case DataType::Type::kFloat32:
702 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100703 __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800704 break;
705 default:
706 LOG(FATAL) << "Unsupported SIMD type";
707 UNREACHABLE();
708 }
709}
710
711void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
712 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
713}
714
715void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100716 // TODO: Use BIC (vector, register).
Aart Bikf8f5a162017-02-06 15:35:29 -0800717 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
718}
719
720void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100721 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800722}
723
724void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
725 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100726 VRegister lhs = VRegisterFrom(locations->InAt(0));
727 VRegister rhs = VRegisterFrom(locations->InAt(1));
728 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800729 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100730 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100731 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100732 case DataType::Type::kInt8:
733 case DataType::Type::kUint16:
734 case DataType::Type::kInt16:
735 case DataType::Type::kInt32:
736 case DataType::Type::kInt64:
737 case DataType::Type::kFloat32:
738 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100739 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800740 break;
741 default:
742 LOG(FATAL) << "Unsupported SIMD type";
743 UNREACHABLE();
744 }
745}
746
747void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100748 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800749}
750
751void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
752 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100753 VRegister lhs = VRegisterFrom(locations->InAt(0));
754 VRegister rhs = VRegisterFrom(locations->InAt(1));
755 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800756 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100757 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100758 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100759 case DataType::Type::kInt8:
760 case DataType::Type::kUint16:
761 case DataType::Type::kInt16:
762 case DataType::Type::kInt32:
763 case DataType::Type::kInt64:
764 case DataType::Type::kFloat32:
765 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100766 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800767 break;
768 default:
769 LOG(FATAL) << "Unsupported SIMD type";
770 UNREACHABLE();
771 }
772}
773
774// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100775static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
776 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800777 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100778 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100779 case DataType::Type::kInt8:
780 case DataType::Type::kUint16:
781 case DataType::Type::kInt16:
782 case DataType::Type::kInt32:
783 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800784 locations->SetInAt(0, Location::RequiresFpuRegister());
785 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
786 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
787 break;
788 default:
789 LOG(FATAL) << "Unsupported SIMD type";
790 UNREACHABLE();
791 }
792}
793
794void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100795 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800796}
797
798void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
799 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100800 VRegister lhs = VRegisterFrom(locations->InAt(0));
801 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800802 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
803 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100804 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100805 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100806 DCHECK_EQ(16u, instruction->GetVectorLength());
807 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800808 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100809 case DataType::Type::kUint16:
810 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100811 DCHECK_EQ(8u, instruction->GetVectorLength());
812 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800813 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100814 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100815 DCHECK_EQ(4u, instruction->GetVectorLength());
816 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800817 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100818 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100819 DCHECK_EQ(2u, instruction->GetVectorLength());
820 __ Shl(dst.V2D(), lhs.V2D(), value);
821 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800822 default:
823 LOG(FATAL) << "Unsupported SIMD type";
824 UNREACHABLE();
825 }
826}
827
828void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100829 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800830}
831
832void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
833 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100834 VRegister lhs = VRegisterFrom(locations->InAt(0));
835 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800836 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
837 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100838 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100839 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100840 DCHECK_EQ(16u, instruction->GetVectorLength());
841 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800842 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100843 case DataType::Type::kUint16:
844 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100845 DCHECK_EQ(8u, instruction->GetVectorLength());
846 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800847 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100848 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100849 DCHECK_EQ(4u, instruction->GetVectorLength());
850 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800851 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100852 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100853 DCHECK_EQ(2u, instruction->GetVectorLength());
854 __ Sshr(dst.V2D(), lhs.V2D(), value);
855 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800856 default:
857 LOG(FATAL) << "Unsupported SIMD type";
858 UNREACHABLE();
859 }
860}
861
862void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100863 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800864}
865
866void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
867 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100868 VRegister lhs = VRegisterFrom(locations->InAt(0));
869 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800870 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
871 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100872 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100873 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100874 DCHECK_EQ(16u, instruction->GetVectorLength());
875 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800876 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100877 case DataType::Type::kUint16:
878 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100879 DCHECK_EQ(8u, instruction->GetVectorLength());
880 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800881 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100882 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100883 DCHECK_EQ(4u, instruction->GetVectorLength());
884 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800885 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100886 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100887 DCHECK_EQ(2u, instruction->GetVectorLength());
888 __ Ushr(dst.V2D(), lhs.V2D(), value);
889 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800890 default:
891 LOG(FATAL) << "Unsupported SIMD type";
892 UNREACHABLE();
893 }
894}
895
Aart Bik0148de42017-09-05 09:25:01 -0700896void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100897 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700898
899 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
900
901 HInstruction* input = instruction->InputAt(0);
902 bool is_zero = IsZeroBitPattern(input);
903
904 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100905 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100906 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100907 case DataType::Type::kInt8:
908 case DataType::Type::kUint16:
909 case DataType::Type::kInt16:
910 case DataType::Type::kInt32:
911 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700912 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
913 : Location::RequiresRegister());
914 locations->SetOut(Location::RequiresFpuRegister());
915 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100916 case DataType::Type::kFloat32:
917 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700918 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
919 : Location::RequiresFpuRegister());
920 locations->SetOut(Location::RequiresFpuRegister());
921 break;
922 default:
923 LOG(FATAL) << "Unsupported SIMD type";
924 UNREACHABLE();
925 }
926}
927
928void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
929 LocationSummary* locations = instruction->GetLocations();
930 VRegister dst = VRegisterFrom(locations->Out());
931
932 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
933
934 // Zero out all other elements first.
935 __ Movi(dst.V16B(), 0);
936
937 // Shorthand for any type of zero.
938 if (IsZeroBitPattern(instruction->InputAt(0))) {
939 return;
940 }
941
942 // Set required elements.
943 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100944 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100945 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100946 case DataType::Type::kInt8:
Aart Bik0148de42017-09-05 09:25:01 -0700947 DCHECK_EQ(16u, instruction->GetVectorLength());
948 __ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0));
949 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100950 case DataType::Type::kUint16:
951 case DataType::Type::kInt16:
Aart Bik0148de42017-09-05 09:25:01 -0700952 DCHECK_EQ(8u, instruction->GetVectorLength());
953 __ Mov(dst.V8H(), 0, InputRegisterAt(instruction, 0));
954 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100955 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700956 DCHECK_EQ(4u, instruction->GetVectorLength());
957 __ Mov(dst.V4S(), 0, InputRegisterAt(instruction, 0));
958 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100959 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700960 DCHECK_EQ(2u, instruction->GetVectorLength());
961 __ Mov(dst.V2D(), 0, InputRegisterAt(instruction, 0));
962 break;
963 default:
964 LOG(FATAL) << "Unsupported SIMD type";
965 UNREACHABLE();
966 }
967}
968
Aart Bikdbbac8f2017-09-01 13:06:08 -0700969// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100970static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
971 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -0700972 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100973 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100974 case DataType::Type::kInt8:
975 case DataType::Type::kUint16:
976 case DataType::Type::kInt16:
977 case DataType::Type::kInt32:
978 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700979 locations->SetInAt(0, Location::RequiresFpuRegister());
980 locations->SetInAt(1, Location::RequiresFpuRegister());
981 locations->SetInAt(2, Location::RequiresFpuRegister());
Artem Serovf34dd202017-04-10 17:41:46 +0100982 locations->SetOut(Location::SameAsFirstInput());
983 break;
984 default:
985 LOG(FATAL) << "Unsupported SIMD type";
986 UNREACHABLE();
987 }
988}
989
Aart Bikdbbac8f2017-09-01 13:06:08 -0700990void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100991 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -0700992}
993
Artem Serovf34dd202017-04-10 17:41:46 +0100994// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
995// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
996// However vector MultiplyAccumulate instruction is not affected.
Aart Bikdbbac8f2017-09-01 13:06:08 -0700997void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
998 LocationSummary* locations = instruction->GetLocations();
999 VRegister acc = VRegisterFrom(locations->InAt(0));
1000 VRegister left = VRegisterFrom(locations->InAt(1));
1001 VRegister right = VRegisterFrom(locations->InAt(2));
1002
1003 DCHECK(locations->InAt(0).Equals(locations->Out()));
1004
1005 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001006 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001007 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001008 DCHECK_EQ(16u, instruction->GetVectorLength());
1009 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001010 __ Mla(acc.V16B(), left.V16B(), right.V16B());
1011 } else {
1012 __ Mls(acc.V16B(), left.V16B(), right.V16B());
1013 }
1014 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001015 case DataType::Type::kUint16:
1016 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001017 DCHECK_EQ(8u, instruction->GetVectorLength());
1018 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001019 __ Mla(acc.V8H(), left.V8H(), right.V8H());
1020 } else {
1021 __ Mls(acc.V8H(), left.V8H(), right.V8H());
1022 }
1023 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001024 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001025 DCHECK_EQ(4u, instruction->GetVectorLength());
1026 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001027 __ Mla(acc.V4S(), left.V4S(), right.V4S());
1028 } else {
1029 __ Mls(acc.V4S(), left.V4S(), right.V4S());
1030 }
1031 break;
1032 default:
1033 LOG(FATAL) << "Unsupported SIMD type";
Aart Bikdbbac8f2017-09-01 13:06:08 -07001034 UNREACHABLE();
1035 }
1036}
1037
1038void LocationsBuilderARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001039 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001040 // Some conversions require temporary registers.
1041 LocationSummary* locations = instruction->GetLocations();
1042 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1043 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1044 DCHECK_EQ(a->GetPackedType(), b->GetPackedType());
1045 switch (a->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001046 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001047 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001048 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001049 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001050 locations->AddTemp(Location::RequiresFpuRegister());
1051 locations->AddTemp(Location::RequiresFpuRegister());
1052 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001053 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001054 locations->AddTemp(Location::RequiresFpuRegister());
1055 locations->AddTemp(Location::RequiresFpuRegister());
1056 break;
1057 default:
1058 break;
1059 }
1060 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001061 case DataType::Type::kUint16:
1062 case DataType::Type::kInt16:
1063 if (instruction->GetPackedType() == DataType::Type::kInt64) {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001064 locations->AddTemp(Location::RequiresFpuRegister());
1065 locations->AddTemp(Location::RequiresFpuRegister());
1066 }
1067 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001068 case DataType::Type::kInt32:
1069 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001070 if (instruction->GetPackedType() == a->GetPackedType()) {
1071 locations->AddTemp(Location::RequiresFpuRegister());
1072 }
1073 break;
1074 default:
1075 break;
1076 }
1077}
1078
1079void InstructionCodeGeneratorARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
1080 LocationSummary* locations = instruction->GetLocations();
1081 VRegister acc = VRegisterFrom(locations->InAt(0));
1082 VRegister left = VRegisterFrom(locations->InAt(1));
1083 VRegister right = VRegisterFrom(locations->InAt(2));
1084
1085 DCHECK(locations->InAt(0).Equals(locations->Out()));
1086
1087 // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
1088 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1089 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1090 DCHECK_EQ(a->GetPackedType(), b->GetPackedType());
1091 switch (a->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001092 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001093 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001094 DCHECK_EQ(16u, a->GetVectorLength());
1095 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001096 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001097 DCHECK_EQ(8u, instruction->GetVectorLength());
1098 __ Sabal(acc.V8H(), left.V8B(), right.V8B());
1099 __ Sabal2(acc.V8H(), left.V16B(), right.V16B());
1100 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001101 case DataType::Type::kInt32: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001102 DCHECK_EQ(4u, instruction->GetVectorLength());
1103 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1104 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1105 __ Sxtl(tmp1.V8H(), left.V8B());
1106 __ Sxtl(tmp2.V8H(), right.V8B());
1107 __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
1108 __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
1109 __ Sxtl2(tmp1.V8H(), left.V16B());
1110 __ Sxtl2(tmp2.V8H(), right.V16B());
1111 __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
1112 __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
1113 break;
1114 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001115 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001116 DCHECK_EQ(2u, instruction->GetVectorLength());
1117 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1118 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1119 VRegister tmp3 = VRegisterFrom(locations->GetTemp(2));
1120 VRegister tmp4 = VRegisterFrom(locations->GetTemp(3));
1121 __ Sxtl(tmp1.V8H(), left.V8B());
1122 __ Sxtl(tmp2.V8H(), right.V8B());
1123 __ Sxtl(tmp3.V4S(), tmp1.V4H());
1124 __ Sxtl(tmp4.V4S(), tmp2.V4H());
1125 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1126 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1127 __ Sxtl2(tmp3.V4S(), tmp1.V8H());
1128 __ Sxtl2(tmp4.V4S(), tmp2.V8H());
1129 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1130 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1131 __ Sxtl2(tmp1.V8H(), left.V16B());
1132 __ Sxtl2(tmp2.V8H(), right.V16B());
1133 __ Sxtl(tmp3.V4S(), tmp1.V4H());
1134 __ Sxtl(tmp4.V4S(), tmp2.V4H());
1135 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1136 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1137 __ Sxtl2(tmp3.V4S(), tmp1.V8H());
1138 __ Sxtl2(tmp4.V4S(), tmp2.V8H());
1139 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1140 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1141 break;
1142 }
1143 default:
1144 LOG(FATAL) << "Unsupported SIMD type";
1145 UNREACHABLE();
1146 }
1147 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001148 case DataType::Type::kUint16:
1149 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001150 DCHECK_EQ(8u, a->GetVectorLength());
1151 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001152 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001153 DCHECK_EQ(4u, instruction->GetVectorLength());
1154 __ Sabal(acc.V4S(), left.V4H(), right.V4H());
1155 __ Sabal2(acc.V4S(), left.V8H(), right.V8H());
1156 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001157 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001158 DCHECK_EQ(2u, instruction->GetVectorLength());
1159 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1160 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1161 __ Sxtl(tmp1.V4S(), left.V4H());
1162 __ Sxtl(tmp2.V4S(), right.V4H());
1163 __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
1164 __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
1165 __ Sxtl2(tmp1.V4S(), left.V8H());
1166 __ Sxtl2(tmp2.V4S(), right.V8H());
1167 __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
1168 __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
1169 break;
1170 }
1171 default:
1172 LOG(FATAL) << "Unsupported SIMD type";
1173 UNREACHABLE();
1174 }
1175 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001176 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001177 DCHECK_EQ(4u, a->GetVectorLength());
1178 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001179 case DataType::Type::kInt32: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001180 DCHECK_EQ(4u, instruction->GetVectorLength());
1181 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1182 __ Sub(tmp.V4S(), left.V4S(), right.V4S());
1183 __ Abs(tmp.V4S(), tmp.V4S());
1184 __ Add(acc.V4S(), acc.V4S(), tmp.V4S());
1185 break;
1186 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001187 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001188 DCHECK_EQ(2u, instruction->GetVectorLength());
1189 __ Sabal(acc.V2D(), left.V2S(), right.V2S());
1190 __ Sabal2(acc.V2D(), left.V4S(), right.V4S());
1191 break;
1192 default:
1193 LOG(FATAL) << "Unsupported SIMD type";
1194 UNREACHABLE();
1195 }
1196 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001197 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001198 DCHECK_EQ(2u, a->GetVectorLength());
1199 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001200 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001201 DCHECK_EQ(2u, instruction->GetVectorLength());
1202 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1203 __ Sub(tmp.V2D(), left.V2D(), right.V2D());
1204 __ Abs(tmp.V2D(), tmp.V2D());
1205 __ Add(acc.V2D(), acc.V2D(), tmp.V2D());
1206 break;
1207 }
1208 default:
1209 LOG(FATAL) << "Unsupported SIMD type";
1210 UNREACHABLE();
1211 }
1212 break;
1213 default:
1214 LOG(FATAL) << "Unsupported SIMD type";
Artem Serovf34dd202017-04-10 17:41:46 +01001215 }
1216}
1217
Aart Bikf8f5a162017-02-06 15:35:29 -08001218// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001219static void CreateVecMemLocations(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001220 HVecMemoryOperation* instruction,
1221 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001222 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001223 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001224 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001225 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001226 case DataType::Type::kInt8:
1227 case DataType::Type::kUint16:
1228 case DataType::Type::kInt16:
1229 case DataType::Type::kInt32:
1230 case DataType::Type::kInt64:
1231 case DataType::Type::kFloat32:
1232 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001233 locations->SetInAt(0, Location::RequiresRegister());
1234 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1235 if (is_load) {
1236 locations->SetOut(Location::RequiresFpuRegister());
1237 } else {
1238 locations->SetInAt(2, Location::RequiresFpuRegister());
1239 }
1240 break;
1241 default:
1242 LOG(FATAL) << "Unsupported SIMD type";
1243 UNREACHABLE();
1244 }
1245}
1246
Aart Bik472821b2017-04-27 17:23:51 -07001247// Helper to set up locations for vector memory operations. Returns the memory operand and,
1248// if used, sets the output parameter scratch to a temporary register used in this operand,
1249// so that the client can release it right after the memory operand use.
1250MemOperand InstructionCodeGeneratorARM64::VecAddress(
Aart Bikf8f5a162017-02-06 15:35:29 -08001251 HVecMemoryOperation* instruction,
Aart Bik472821b2017-04-27 17:23:51 -07001252 UseScratchRegisterScope* temps_scope,
1253 size_t size,
1254 bool is_string_char_at,
1255 /*out*/ Register* scratch) {
Aart Bikf8f5a162017-02-06 15:35:29 -08001256 LocationSummary* locations = instruction->GetLocations();
1257 Register base = InputRegisterAt(instruction, 0);
Artem Serove1811ed2017-04-27 16:50:47 +01001258
1259 if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
1260 DCHECK(!is_string_char_at);
1261 return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
1262 }
1263
Aart Bikf8f5a162017-02-06 15:35:29 -08001264 Location index = locations->InAt(1);
Aart Bik472821b2017-04-27 17:23:51 -07001265 uint32_t offset = is_string_char_at
1266 ? mirror::String::ValueOffset().Uint32Value()
1267 : mirror::Array::DataOffset(size).Uint32Value();
1268 size_t shift = ComponentSizeShiftWidth(size);
Aart Bikf8f5a162017-02-06 15:35:29 -08001269
Artem Serov0225b772017-04-19 15:43:53 +01001270 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
1271 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
1272
Aart Bikf8f5a162017-02-06 15:35:29 -08001273 if (index.IsConstant()) {
1274 offset += Int64ConstantFrom(index) << shift;
Artem Serov0225b772017-04-19 15:43:53 +01001275 return HeapOperand(base, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -08001276 } else {
Aart Bik472821b2017-04-27 17:23:51 -07001277 *scratch = temps_scope->AcquireSameSizeAs(base);
1278 __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
1279 return HeapOperand(*scratch, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -08001280 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001281}
1282
1283void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001284 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bikf8f5a162017-02-06 15:35:29 -08001285}
1286
1287void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001288 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001289 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001290 VRegister reg = VRegisterFrom(locations->Out());
Artem Serov0225b772017-04-19 15:43:53 +01001291 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -07001292 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +01001293
Aart Bikf8f5a162017-02-06 15:35:29 -08001294 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001295 case DataType::Type::kUint16:
Aart Bik472821b2017-04-27 17:23:51 -07001296 DCHECK_EQ(8u, instruction->GetVectorLength());
1297 // Special handling of compressed/uncompressed string load.
1298 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1299 vixl::aarch64::Label uncompressed_load, done;
1300 // Test compression bit.
1301 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
1302 "Expecting 0=compressed, 1=uncompressed");
1303 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
1304 Register length = temps.AcquireW();
1305 __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
1306 __ Tbnz(length.W(), 0, &uncompressed_load);
1307 temps.Release(length); // no longer needed
1308 // Zero extend 8 compressed bytes into 8 chars.
1309 __ Ldr(DRegisterFrom(locations->Out()).V8B(),
1310 VecAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
1311 __ Uxtl(reg.V8H(), reg.V8B());
1312 __ B(&done);
1313 if (scratch.IsValid()) {
1314 temps.Release(scratch); // if used, no longer needed
1315 }
1316 // Load 8 direct uncompressed chars.
1317 __ Bind(&uncompressed_load);
1318 __ Ldr(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
1319 __ Bind(&done);
1320 return;
1321 }
1322 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001323 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001324 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001325 case DataType::Type::kInt8:
1326 case DataType::Type::kInt16:
1327 case DataType::Type::kInt32:
1328 case DataType::Type::kFloat32:
1329 case DataType::Type::kInt64:
1330 case DataType::Type::kFloat64:
Artem Serov0225b772017-04-19 15:43:53 +01001331 DCHECK_LE(2u, instruction->GetVectorLength());
1332 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001333 __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001334 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001335 default:
1336 LOG(FATAL) << "Unsupported SIMD type";
1337 UNREACHABLE();
1338 }
1339}
1340
1341void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001342 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001343}
1344
1345void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001346 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001347 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001348 VRegister reg = VRegisterFrom(locations->InAt(2));
Artem Serov0225b772017-04-19 15:43:53 +01001349 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -07001350 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +01001351
Aart Bikf8f5a162017-02-06 15:35:29 -08001352 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001353 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001354 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001355 case DataType::Type::kInt8:
1356 case DataType::Type::kUint16:
1357 case DataType::Type::kInt16:
1358 case DataType::Type::kInt32:
1359 case DataType::Type::kFloat32:
1360 case DataType::Type::kInt64:
1361 case DataType::Type::kFloat64:
Artem Serov0225b772017-04-19 15:43:53 +01001362 DCHECK_LE(2u, instruction->GetVectorLength());
1363 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001364 __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001365 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001366 default:
1367 LOG(FATAL) << "Unsupported SIMD type";
1368 UNREACHABLE();
1369 }
1370}
1371
1372#undef __
1373
1374} // namespace arm64
1375} // namespace art