blob: 174efdf115536faece4b494ca141334f38803cda [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;
Aart Bik66c158e2018-01-31 12:55:04 -0800609 case DataType::Type::kUint32:
610 DCHECK_EQ(4u, instruction->GetVectorLength());
611 __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S());
612 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100613 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700614 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800615 __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikc8e93c72017-05-10 10:49:22 -0700616 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());
Aart Bikc8e93c72017-05-10 10:49:22 -0700619 __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S());
620 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100621 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700622 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700623 __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D());
624 break;
625 default:
626 LOG(FATAL) << "Unsupported SIMD type";
627 UNREACHABLE();
628 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700629}
630
631void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100632 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700633}
634
635void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700636 LocationSummary* locations = instruction->GetLocations();
637 VRegister lhs = VRegisterFrom(locations->InAt(0));
638 VRegister rhs = VRegisterFrom(locations->InAt(1));
639 VRegister dst = VRegisterFrom(locations->Out());
640 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100641 case DataType::Type::kUint8:
642 DCHECK_EQ(16u, instruction->GetVectorLength());
643 __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
644 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100645 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700646 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100647 __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikc8e93c72017-05-10 10:49:22 -0700648 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100649 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100650 DCHECK_EQ(8u, instruction->GetVectorLength());
651 __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
652 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100653 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700654 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100655 __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikc8e93c72017-05-10 10:49:22 -0700656 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800657 case DataType::Type::kUint32:
658 DCHECK_EQ(4u, instruction->GetVectorLength());
659 __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S());
660 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100661 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700662 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800663 __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikc8e93c72017-05-10 10:49:22 -0700664 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100665 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700666 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700667 __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S());
668 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100669 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700670 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700671 __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D());
672 break;
673 default:
674 LOG(FATAL) << "Unsupported SIMD type";
675 UNREACHABLE();
676 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700677}
678
Aart Bikf8f5a162017-02-06 15:35:29 -0800679void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100680 // TODO: Allow constants supported by BIC (vector, immediate).
Vladimir Markoca6fff82017-10-03 14:49:14 +0100681 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800682}
683
684void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
685 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100686 VRegister lhs = VRegisterFrom(locations->InAt(0));
687 VRegister rhs = VRegisterFrom(locations->InAt(1));
688 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800689 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100690 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100691 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100692 case DataType::Type::kInt8:
693 case DataType::Type::kUint16:
694 case DataType::Type::kInt16:
695 case DataType::Type::kInt32:
696 case DataType::Type::kInt64:
697 case DataType::Type::kFloat32:
698 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100699 __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800700 break;
701 default:
702 LOG(FATAL) << "Unsupported SIMD type";
703 UNREACHABLE();
704 }
705}
706
707void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
708 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
709}
710
711void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100712 // TODO: Use BIC (vector, register).
Aart Bikf8f5a162017-02-06 15:35:29 -0800713 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
714}
715
716void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100717 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800718}
719
720void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
721 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100722 VRegister lhs = VRegisterFrom(locations->InAt(0));
723 VRegister rhs = VRegisterFrom(locations->InAt(1));
724 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800725 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100726 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100727 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100728 case DataType::Type::kInt8:
729 case DataType::Type::kUint16:
730 case DataType::Type::kInt16:
731 case DataType::Type::kInt32:
732 case DataType::Type::kInt64:
733 case DataType::Type::kFloat32:
734 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100735 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800736 break;
737 default:
738 LOG(FATAL) << "Unsupported SIMD type";
739 UNREACHABLE();
740 }
741}
742
743void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100744 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800745}
746
747void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
748 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100749 VRegister lhs = VRegisterFrom(locations->InAt(0));
750 VRegister rhs = VRegisterFrom(locations->InAt(1));
751 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800752 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100753 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100754 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100755 case DataType::Type::kInt8:
756 case DataType::Type::kUint16:
757 case DataType::Type::kInt16:
758 case DataType::Type::kInt32:
759 case DataType::Type::kInt64:
760 case DataType::Type::kFloat32:
761 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100762 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800763 break;
764 default:
765 LOG(FATAL) << "Unsupported SIMD type";
766 UNREACHABLE();
767 }
768}
769
770// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100771static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
772 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800773 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100774 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100775 case DataType::Type::kInt8:
776 case DataType::Type::kUint16:
777 case DataType::Type::kInt16:
778 case DataType::Type::kInt32:
779 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800780 locations->SetInAt(0, Location::RequiresFpuRegister());
781 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
782 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
783 break;
784 default:
785 LOG(FATAL) << "Unsupported SIMD type";
786 UNREACHABLE();
787 }
788}
789
790void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100791 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800792}
793
794void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
795 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100796 VRegister lhs = VRegisterFrom(locations->InAt(0));
797 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800798 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
799 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100800 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100801 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100802 DCHECK_EQ(16u, instruction->GetVectorLength());
803 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800804 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100805 case DataType::Type::kUint16:
806 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100807 DCHECK_EQ(8u, instruction->GetVectorLength());
808 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800809 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100810 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100811 DCHECK_EQ(4u, instruction->GetVectorLength());
812 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800813 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100814 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100815 DCHECK_EQ(2u, instruction->GetVectorLength());
816 __ Shl(dst.V2D(), lhs.V2D(), value);
817 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800818 default:
819 LOG(FATAL) << "Unsupported SIMD type";
820 UNREACHABLE();
821 }
822}
823
824void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100825 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800826}
827
828void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
829 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100830 VRegister lhs = VRegisterFrom(locations->InAt(0));
831 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800832 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
833 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100834 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100835 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100836 DCHECK_EQ(16u, instruction->GetVectorLength());
837 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800838 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100839 case DataType::Type::kUint16:
840 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100841 DCHECK_EQ(8u, instruction->GetVectorLength());
842 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800843 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100844 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100845 DCHECK_EQ(4u, instruction->GetVectorLength());
846 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800847 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100848 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100849 DCHECK_EQ(2u, instruction->GetVectorLength());
850 __ Sshr(dst.V2D(), lhs.V2D(), value);
851 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800852 default:
853 LOG(FATAL) << "Unsupported SIMD type";
854 UNREACHABLE();
855 }
856}
857
858void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100859 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800860}
861
862void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
863 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100864 VRegister lhs = VRegisterFrom(locations->InAt(0));
865 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800866 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
867 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100868 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100869 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100870 DCHECK_EQ(16u, instruction->GetVectorLength());
871 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800872 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100873 case DataType::Type::kUint16:
874 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100875 DCHECK_EQ(8u, instruction->GetVectorLength());
876 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800877 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100878 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100879 DCHECK_EQ(4u, instruction->GetVectorLength());
880 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800881 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100882 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100883 DCHECK_EQ(2u, instruction->GetVectorLength());
884 __ Ushr(dst.V2D(), lhs.V2D(), value);
885 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800886 default:
887 LOG(FATAL) << "Unsupported SIMD type";
888 UNREACHABLE();
889 }
890}
891
Aart Bik0148de42017-09-05 09:25:01 -0700892void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100893 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700894
895 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
896
897 HInstruction* input = instruction->InputAt(0);
898 bool is_zero = IsZeroBitPattern(input);
899
900 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100901 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100902 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100903 case DataType::Type::kInt8:
904 case DataType::Type::kUint16:
905 case DataType::Type::kInt16:
906 case DataType::Type::kInt32:
907 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700908 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
909 : Location::RequiresRegister());
910 locations->SetOut(Location::RequiresFpuRegister());
911 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100912 case DataType::Type::kFloat32:
913 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700914 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
915 : Location::RequiresFpuRegister());
916 locations->SetOut(Location::RequiresFpuRegister());
917 break;
918 default:
919 LOG(FATAL) << "Unsupported SIMD type";
920 UNREACHABLE();
921 }
922}
923
924void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
925 LocationSummary* locations = instruction->GetLocations();
926 VRegister dst = VRegisterFrom(locations->Out());
927
928 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
929
930 // Zero out all other elements first.
931 __ Movi(dst.V16B(), 0);
932
933 // Shorthand for any type of zero.
934 if (IsZeroBitPattern(instruction->InputAt(0))) {
935 return;
936 }
937
938 // Set required elements.
939 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100940 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100941 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100942 case DataType::Type::kInt8:
Aart Bik0148de42017-09-05 09:25:01 -0700943 DCHECK_EQ(16u, instruction->GetVectorLength());
944 __ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0));
945 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100946 case DataType::Type::kUint16:
947 case DataType::Type::kInt16:
Aart Bik0148de42017-09-05 09:25:01 -0700948 DCHECK_EQ(8u, instruction->GetVectorLength());
949 __ Mov(dst.V8H(), 0, InputRegisterAt(instruction, 0));
950 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100951 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700952 DCHECK_EQ(4u, instruction->GetVectorLength());
953 __ Mov(dst.V4S(), 0, InputRegisterAt(instruction, 0));
954 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100955 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700956 DCHECK_EQ(2u, instruction->GetVectorLength());
957 __ Mov(dst.V2D(), 0, InputRegisterAt(instruction, 0));
958 break;
959 default:
960 LOG(FATAL) << "Unsupported SIMD type";
961 UNREACHABLE();
962 }
963}
964
Aart Bikdbbac8f2017-09-01 13:06:08 -0700965// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100966static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
967 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -0700968 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100969 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100970 case DataType::Type::kInt8:
971 case DataType::Type::kUint16:
972 case DataType::Type::kInt16:
973 case DataType::Type::kInt32:
974 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700975 locations->SetInAt(0, Location::RequiresFpuRegister());
976 locations->SetInAt(1, Location::RequiresFpuRegister());
977 locations->SetInAt(2, Location::RequiresFpuRegister());
Artem Serovf34dd202017-04-10 17:41:46 +0100978 locations->SetOut(Location::SameAsFirstInput());
979 break;
980 default:
981 LOG(FATAL) << "Unsupported SIMD type";
982 UNREACHABLE();
983 }
984}
985
Aart Bikdbbac8f2017-09-01 13:06:08 -0700986void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100987 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -0700988}
989
Artem Serovf34dd202017-04-10 17:41:46 +0100990// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
991// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
992// However vector MultiplyAccumulate instruction is not affected.
Aart Bikdbbac8f2017-09-01 13:06:08 -0700993void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
994 LocationSummary* locations = instruction->GetLocations();
995 VRegister acc = VRegisterFrom(locations->InAt(0));
996 VRegister left = VRegisterFrom(locations->InAt(1));
997 VRegister right = VRegisterFrom(locations->InAt(2));
998
999 DCHECK(locations->InAt(0).Equals(locations->Out()));
1000
1001 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001002 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001003 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001004 DCHECK_EQ(16u, instruction->GetVectorLength());
1005 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001006 __ Mla(acc.V16B(), left.V16B(), right.V16B());
1007 } else {
1008 __ Mls(acc.V16B(), left.V16B(), right.V16B());
1009 }
1010 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001011 case DataType::Type::kUint16:
1012 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001013 DCHECK_EQ(8u, instruction->GetVectorLength());
1014 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001015 __ Mla(acc.V8H(), left.V8H(), right.V8H());
1016 } else {
1017 __ Mls(acc.V8H(), left.V8H(), right.V8H());
1018 }
1019 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001020 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001021 DCHECK_EQ(4u, instruction->GetVectorLength());
1022 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001023 __ Mla(acc.V4S(), left.V4S(), right.V4S());
1024 } else {
1025 __ Mls(acc.V4S(), left.V4S(), right.V4S());
1026 }
1027 break;
1028 default:
1029 LOG(FATAL) << "Unsupported SIMD type";
Aart Bikdbbac8f2017-09-01 13:06:08 -07001030 UNREACHABLE();
1031 }
1032}
1033
1034void LocationsBuilderARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001035 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001036 // Some conversions require temporary registers.
1037 LocationSummary* locations = instruction->GetLocations();
1038 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1039 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
Vladimir Marko61b92282017-10-11 13:23:17 +01001040 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1041 HVecOperation::ToSignedType(b->GetPackedType()));
Aart Bikdbbac8f2017-09-01 13:06:08 -07001042 switch (a->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001043 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001044 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001045 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001046 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001047 locations->AddTemp(Location::RequiresFpuRegister());
1048 locations->AddTemp(Location::RequiresFpuRegister());
1049 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001050 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001051 locations->AddTemp(Location::RequiresFpuRegister());
1052 locations->AddTemp(Location::RequiresFpuRegister());
1053 break;
1054 default:
1055 break;
1056 }
1057 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001058 case DataType::Type::kUint16:
1059 case DataType::Type::kInt16:
1060 if (instruction->GetPackedType() == DataType::Type::kInt64) {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001061 locations->AddTemp(Location::RequiresFpuRegister());
1062 locations->AddTemp(Location::RequiresFpuRegister());
1063 }
1064 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001065 case DataType::Type::kInt32:
1066 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001067 if (instruction->GetPackedType() == a->GetPackedType()) {
1068 locations->AddTemp(Location::RequiresFpuRegister());
1069 }
1070 break;
1071 default:
1072 break;
1073 }
1074}
1075
1076void InstructionCodeGeneratorARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
1077 LocationSummary* locations = instruction->GetLocations();
1078 VRegister acc = VRegisterFrom(locations->InAt(0));
1079 VRegister left = VRegisterFrom(locations->InAt(1));
1080 VRegister right = VRegisterFrom(locations->InAt(2));
1081
1082 DCHECK(locations->InAt(0).Equals(locations->Out()));
1083
1084 // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
1085 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1086 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
Vladimir Marko61b92282017-10-11 13:23:17 +01001087 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1088 HVecOperation::ToSignedType(b->GetPackedType()));
Aart Bikdbbac8f2017-09-01 13:06:08 -07001089 switch (a->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001090 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001091 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001092 DCHECK_EQ(16u, a->GetVectorLength());
1093 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001094 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001095 DCHECK_EQ(8u, instruction->GetVectorLength());
1096 __ Sabal(acc.V8H(), left.V8B(), right.V8B());
1097 __ Sabal2(acc.V8H(), left.V16B(), right.V16B());
1098 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001099 case DataType::Type::kInt32: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001100 DCHECK_EQ(4u, instruction->GetVectorLength());
1101 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1102 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1103 __ Sxtl(tmp1.V8H(), left.V8B());
1104 __ Sxtl(tmp2.V8H(), right.V8B());
1105 __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
1106 __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
1107 __ Sxtl2(tmp1.V8H(), left.V16B());
1108 __ Sxtl2(tmp2.V8H(), right.V16B());
1109 __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
1110 __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
1111 break;
1112 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001113 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001114 DCHECK_EQ(2u, instruction->GetVectorLength());
1115 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1116 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1117 VRegister tmp3 = VRegisterFrom(locations->GetTemp(2));
1118 VRegister tmp4 = VRegisterFrom(locations->GetTemp(3));
1119 __ Sxtl(tmp1.V8H(), left.V8B());
1120 __ Sxtl(tmp2.V8H(), right.V8B());
1121 __ Sxtl(tmp3.V4S(), tmp1.V4H());
1122 __ Sxtl(tmp4.V4S(), tmp2.V4H());
1123 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1124 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1125 __ Sxtl2(tmp3.V4S(), tmp1.V8H());
1126 __ Sxtl2(tmp4.V4S(), tmp2.V8H());
1127 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1128 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1129 __ Sxtl2(tmp1.V8H(), left.V16B());
1130 __ Sxtl2(tmp2.V8H(), right.V16B());
1131 __ Sxtl(tmp3.V4S(), tmp1.V4H());
1132 __ Sxtl(tmp4.V4S(), tmp2.V4H());
1133 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1134 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1135 __ Sxtl2(tmp3.V4S(), tmp1.V8H());
1136 __ Sxtl2(tmp4.V4S(), tmp2.V8H());
1137 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1138 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1139 break;
1140 }
1141 default:
1142 LOG(FATAL) << "Unsupported SIMD type";
1143 UNREACHABLE();
1144 }
1145 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001146 case DataType::Type::kUint16:
1147 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001148 DCHECK_EQ(8u, a->GetVectorLength());
1149 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001150 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001151 DCHECK_EQ(4u, instruction->GetVectorLength());
1152 __ Sabal(acc.V4S(), left.V4H(), right.V4H());
1153 __ Sabal2(acc.V4S(), left.V8H(), right.V8H());
1154 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001155 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001156 DCHECK_EQ(2u, instruction->GetVectorLength());
1157 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1158 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1159 __ Sxtl(tmp1.V4S(), left.V4H());
1160 __ Sxtl(tmp2.V4S(), right.V4H());
1161 __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
1162 __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
1163 __ Sxtl2(tmp1.V4S(), left.V8H());
1164 __ Sxtl2(tmp2.V4S(), right.V8H());
1165 __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
1166 __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
1167 break;
1168 }
1169 default:
1170 LOG(FATAL) << "Unsupported SIMD type";
1171 UNREACHABLE();
1172 }
1173 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001174 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001175 DCHECK_EQ(4u, a->GetVectorLength());
1176 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001177 case DataType::Type::kInt32: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001178 DCHECK_EQ(4u, instruction->GetVectorLength());
1179 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1180 __ Sub(tmp.V4S(), left.V4S(), right.V4S());
1181 __ Abs(tmp.V4S(), tmp.V4S());
1182 __ Add(acc.V4S(), acc.V4S(), tmp.V4S());
1183 break;
1184 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001185 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001186 DCHECK_EQ(2u, instruction->GetVectorLength());
1187 __ Sabal(acc.V2D(), left.V2S(), right.V2S());
1188 __ Sabal2(acc.V2D(), left.V4S(), right.V4S());
1189 break;
1190 default:
1191 LOG(FATAL) << "Unsupported SIMD type";
1192 UNREACHABLE();
1193 }
1194 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001195 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001196 DCHECK_EQ(2u, a->GetVectorLength());
1197 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001198 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001199 DCHECK_EQ(2u, instruction->GetVectorLength());
1200 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1201 __ Sub(tmp.V2D(), left.V2D(), right.V2D());
1202 __ Abs(tmp.V2D(), tmp.V2D());
1203 __ Add(acc.V2D(), acc.V2D(), tmp.V2D());
1204 break;
1205 }
1206 default:
1207 LOG(FATAL) << "Unsupported SIMD type";
1208 UNREACHABLE();
1209 }
1210 break;
1211 default:
1212 LOG(FATAL) << "Unsupported SIMD type";
Artem Serovf34dd202017-04-10 17:41:46 +01001213 }
1214}
1215
Aart Bikf8f5a162017-02-06 15:35:29 -08001216// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001217static void CreateVecMemLocations(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001218 HVecMemoryOperation* instruction,
1219 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001220 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001221 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001222 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001223 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001224 case DataType::Type::kInt8:
1225 case DataType::Type::kUint16:
1226 case DataType::Type::kInt16:
1227 case DataType::Type::kInt32:
1228 case DataType::Type::kInt64:
1229 case DataType::Type::kFloat32:
1230 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001231 locations->SetInAt(0, Location::RequiresRegister());
1232 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1233 if (is_load) {
1234 locations->SetOut(Location::RequiresFpuRegister());
1235 } else {
1236 locations->SetInAt(2, Location::RequiresFpuRegister());
1237 }
1238 break;
1239 default:
1240 LOG(FATAL) << "Unsupported SIMD type";
1241 UNREACHABLE();
1242 }
1243}
1244
Aart Bik472821b2017-04-27 17:23:51 -07001245// Helper to set up locations for vector memory operations. Returns the memory operand and,
1246// if used, sets the output parameter scratch to a temporary register used in this operand,
1247// so that the client can release it right after the memory operand use.
1248MemOperand InstructionCodeGeneratorARM64::VecAddress(
Aart Bikf8f5a162017-02-06 15:35:29 -08001249 HVecMemoryOperation* instruction,
Aart Bik472821b2017-04-27 17:23:51 -07001250 UseScratchRegisterScope* temps_scope,
1251 size_t size,
1252 bool is_string_char_at,
1253 /*out*/ Register* scratch) {
Aart Bikf8f5a162017-02-06 15:35:29 -08001254 LocationSummary* locations = instruction->GetLocations();
1255 Register base = InputRegisterAt(instruction, 0);
Artem Serove1811ed2017-04-27 16:50:47 +01001256
1257 if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
1258 DCHECK(!is_string_char_at);
1259 return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
1260 }
1261
Aart Bikf8f5a162017-02-06 15:35:29 -08001262 Location index = locations->InAt(1);
Aart Bik472821b2017-04-27 17:23:51 -07001263 uint32_t offset = is_string_char_at
1264 ? mirror::String::ValueOffset().Uint32Value()
1265 : mirror::Array::DataOffset(size).Uint32Value();
1266 size_t shift = ComponentSizeShiftWidth(size);
Aart Bikf8f5a162017-02-06 15:35:29 -08001267
Artem Serov0225b772017-04-19 15:43:53 +01001268 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
1269 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
1270
Aart Bikf8f5a162017-02-06 15:35:29 -08001271 if (index.IsConstant()) {
1272 offset += Int64ConstantFrom(index) << shift;
Artem Serov0225b772017-04-19 15:43:53 +01001273 return HeapOperand(base, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -08001274 } else {
Aart Bik472821b2017-04-27 17:23:51 -07001275 *scratch = temps_scope->AcquireSameSizeAs(base);
1276 __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
1277 return HeapOperand(*scratch, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -08001278 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001279}
1280
1281void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001282 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bikf8f5a162017-02-06 15:35:29 -08001283}
1284
1285void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001286 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001287 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001288 VRegister reg = VRegisterFrom(locations->Out());
Artem Serov0225b772017-04-19 15:43:53 +01001289 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -07001290 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +01001291
Aart Bikf8f5a162017-02-06 15:35:29 -08001292 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001293 case DataType::Type::kUint16:
Aart Bik472821b2017-04-27 17:23:51 -07001294 DCHECK_EQ(8u, instruction->GetVectorLength());
1295 // Special handling of compressed/uncompressed string load.
1296 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1297 vixl::aarch64::Label uncompressed_load, done;
1298 // Test compression bit.
1299 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
1300 "Expecting 0=compressed, 1=uncompressed");
1301 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
1302 Register length = temps.AcquireW();
1303 __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
1304 __ Tbnz(length.W(), 0, &uncompressed_load);
1305 temps.Release(length); // no longer needed
1306 // Zero extend 8 compressed bytes into 8 chars.
1307 __ Ldr(DRegisterFrom(locations->Out()).V8B(),
1308 VecAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
1309 __ Uxtl(reg.V8H(), reg.V8B());
1310 __ B(&done);
1311 if (scratch.IsValid()) {
1312 temps.Release(scratch); // if used, no longer needed
1313 }
1314 // Load 8 direct uncompressed chars.
1315 __ Bind(&uncompressed_load);
1316 __ Ldr(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
1317 __ Bind(&done);
1318 return;
1319 }
1320 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001321 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001322 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001323 case DataType::Type::kInt8:
1324 case DataType::Type::kInt16:
1325 case DataType::Type::kInt32:
1326 case DataType::Type::kFloat32:
1327 case DataType::Type::kInt64:
1328 case DataType::Type::kFloat64:
Artem Serov0225b772017-04-19 15:43:53 +01001329 DCHECK_LE(2u, instruction->GetVectorLength());
1330 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001331 __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001332 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001333 default:
1334 LOG(FATAL) << "Unsupported SIMD type";
1335 UNREACHABLE();
1336 }
1337}
1338
1339void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001340 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001341}
1342
1343void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001344 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001345 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001346 VRegister reg = VRegisterFrom(locations->InAt(2));
Artem Serov0225b772017-04-19 15:43:53 +01001347 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -07001348 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +01001349
Aart Bikf8f5a162017-02-06 15:35:29 -08001350 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001351 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001352 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001353 case DataType::Type::kInt8:
1354 case DataType::Type::kUint16:
1355 case DataType::Type::kInt16:
1356 case DataType::Type::kInt32:
1357 case DataType::Type::kFloat32:
1358 case DataType::Type::kInt64:
1359 case DataType::Type::kFloat64:
Artem Serov0225b772017-04-19 15:43:53 +01001360 DCHECK_LE(2u, instruction->GetVectorLength());
1361 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001362 __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001363 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001364 default:
1365 LOG(FATAL) << "Unsupported SIMD type";
1366 UNREACHABLE();
1367 }
1368}
1369
1370#undef __
1371
1372} // namespace arm64
1373} // namespace art