blob: 6b0ec253e998cc14df73c532134528d6d33b405b [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:
Aart Bik29aa0822018-03-08 11:28:00 -080066 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -080067 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800128 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800129 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800152 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700153 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800176 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700177 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800203 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800204 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800243 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700244 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 {
Aart Bik29aa0822018-03-08 11:28:00 -0800262 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800263 }
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:
Aart Bik29aa0822018-03-08 11:28:00 -0800302 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800303 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800341 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
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:
Aart Bik29aa0822018-03-08 11:28:00 -0800369 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800370 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800392 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800393 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800434 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
435 UNREACHABLE();
436 }
437}
438
439void LocationsBuilderARM64::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
440 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
441}
442
443void InstructionCodeGeneratorARM64::VisitVecSaturationAdd(HVecSaturationAdd* 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()) {
449 case DataType::Type::kUint8:
450 DCHECK_EQ(16u, instruction->GetVectorLength());
451 __ Uqadd(dst.V16B(), lhs.V16B(), rhs.V16B());
452 break;
453 case DataType::Type::kInt8:
454 DCHECK_EQ(16u, instruction->GetVectorLength());
455 __ Sqadd(dst.V16B(), lhs.V16B(), rhs.V16B());
456 break;
457 case DataType::Type::kUint16:
458 DCHECK_EQ(8u, instruction->GetVectorLength());
459 __ Uqadd(dst.V8H(), lhs.V8H(), rhs.V8H());
460 break;
461 case DataType::Type::kInt16:
462 DCHECK_EQ(8u, instruction->GetVectorLength());
463 __ Sqadd(dst.V8H(), lhs.V8H(), rhs.V8H());
464 break;
465 default:
466 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800467 UNREACHABLE();
468 }
469}
470
Aart Bikf3e61ee2017-04-12 17:09:20 -0700471void LocationsBuilderARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100472 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700473}
474
475void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
476 LocationSummary* locations = instruction->GetLocations();
477 VRegister lhs = VRegisterFrom(locations->InAt(0));
478 VRegister rhs = VRegisterFrom(locations->InAt(1));
479 VRegister dst = VRegisterFrom(locations->Out());
480 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100481 case DataType::Type::kUint8:
482 DCHECK_EQ(16u, instruction->GetVectorLength());
483 instruction->IsRounded()
484 ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
485 : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
486 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100487 case DataType::Type::kInt8:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700488 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100489 instruction->IsRounded()
490 ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
491 : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700492 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100493 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100494 DCHECK_EQ(8u, instruction->GetVectorLength());
495 instruction->IsRounded()
496 ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
497 : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
498 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100499 case DataType::Type::kInt16:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700500 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100501 instruction->IsRounded()
502 ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
503 : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700504 break;
505 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800506 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf3e61ee2017-04-12 17:09:20 -0700507 UNREACHABLE();
508 }
509}
510
Aart Bikf8f5a162017-02-06 15:35:29 -0800511void LocationsBuilderARM64::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100512 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800513}
514
515void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* instruction) {
516 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100517 VRegister lhs = VRegisterFrom(locations->InAt(0));
518 VRegister rhs = VRegisterFrom(locations->InAt(1));
519 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800520 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100521 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100522 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100523 DCHECK_EQ(16u, instruction->GetVectorLength());
524 __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800525 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100526 case DataType::Type::kUint16:
527 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100528 DCHECK_EQ(8u, instruction->GetVectorLength());
529 __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800530 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100531 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100532 DCHECK_EQ(4u, instruction->GetVectorLength());
533 __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800534 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100535 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100536 DCHECK_EQ(2u, instruction->GetVectorLength());
537 __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D());
538 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100539 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100540 DCHECK_EQ(4u, instruction->GetVectorLength());
541 __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800542 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100543 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100544 DCHECK_EQ(2u, instruction->GetVectorLength());
545 __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D());
546 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800547 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800548 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
549 UNREACHABLE();
550 }
551}
552
553void LocationsBuilderARM64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
554 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
555}
556
557void InstructionCodeGeneratorARM64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
558 LocationSummary* locations = instruction->GetLocations();
559 VRegister lhs = VRegisterFrom(locations->InAt(0));
560 VRegister rhs = VRegisterFrom(locations->InAt(1));
561 VRegister dst = VRegisterFrom(locations->Out());
562 switch (instruction->GetPackedType()) {
563 case DataType::Type::kUint8:
564 DCHECK_EQ(16u, instruction->GetVectorLength());
565 __ Uqsub(dst.V16B(), lhs.V16B(), rhs.V16B());
566 break;
567 case DataType::Type::kInt8:
568 DCHECK_EQ(16u, instruction->GetVectorLength());
569 __ Sqsub(dst.V16B(), lhs.V16B(), rhs.V16B());
570 break;
571 case DataType::Type::kUint16:
572 DCHECK_EQ(8u, instruction->GetVectorLength());
573 __ Uqsub(dst.V8H(), lhs.V8H(), rhs.V8H());
574 break;
575 case DataType::Type::kInt16:
576 DCHECK_EQ(8u, instruction->GetVectorLength());
577 __ Sqsub(dst.V8H(), lhs.V8H(), rhs.V8H());
578 break;
579 default:
580 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800581 UNREACHABLE();
582 }
583}
584
585void LocationsBuilderARM64::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100586 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800587}
588
589void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) {
590 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100591 VRegister lhs = VRegisterFrom(locations->InAt(0));
592 VRegister rhs = VRegisterFrom(locations->InAt(1));
593 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800594 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100595 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100596 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100597 DCHECK_EQ(16u, instruction->GetVectorLength());
598 __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800599 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100600 case DataType::Type::kUint16:
601 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100602 DCHECK_EQ(8u, instruction->GetVectorLength());
603 __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800604 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100605 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100606 DCHECK_EQ(4u, instruction->GetVectorLength());
607 __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800608 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100609 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100610 DCHECK_EQ(4u, instruction->GetVectorLength());
611 __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800612 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100613 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100614 DCHECK_EQ(2u, instruction->GetVectorLength());
615 __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D());
616 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800617 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800618 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800619 UNREACHABLE();
620 }
621}
622
623void LocationsBuilderARM64::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100624 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800625}
626
627void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) {
628 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100629 VRegister lhs = VRegisterFrom(locations->InAt(0));
630 VRegister rhs = VRegisterFrom(locations->InAt(1));
631 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800632 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100633 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100634 DCHECK_EQ(4u, instruction->GetVectorLength());
635 __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800636 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100637 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100638 DCHECK_EQ(2u, instruction->GetVectorLength());
639 __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D());
640 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800641 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800642 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800643 UNREACHABLE();
644 }
645}
646
Aart Bikf3e61ee2017-04-12 17:09:20 -0700647void LocationsBuilderARM64::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100648 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700649}
650
651void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700652 LocationSummary* locations = instruction->GetLocations();
653 VRegister lhs = VRegisterFrom(locations->InAt(0));
654 VRegister rhs = VRegisterFrom(locations->InAt(1));
655 VRegister dst = VRegisterFrom(locations->Out());
656 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100657 case DataType::Type::kUint8:
658 DCHECK_EQ(16u, instruction->GetVectorLength());
659 __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
660 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100661 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700662 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100663 __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikc8e93c72017-05-10 10:49:22 -0700664 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100665 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100666 DCHECK_EQ(8u, instruction->GetVectorLength());
667 __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
668 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100669 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700670 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100671 __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikc8e93c72017-05-10 10:49:22 -0700672 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800673 case DataType::Type::kUint32:
674 DCHECK_EQ(4u, instruction->GetVectorLength());
675 __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S());
676 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100677 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700678 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800679 __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikc8e93c72017-05-10 10:49:22 -0700680 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100681 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700682 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700683 __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S());
684 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100685 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700686 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700687 __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D());
688 break;
689 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800690 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700691 UNREACHABLE();
692 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700693}
694
695void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100696 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700697}
698
699void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700700 LocationSummary* locations = instruction->GetLocations();
701 VRegister lhs = VRegisterFrom(locations->InAt(0));
702 VRegister rhs = VRegisterFrom(locations->InAt(1));
703 VRegister dst = VRegisterFrom(locations->Out());
704 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100705 case DataType::Type::kUint8:
706 DCHECK_EQ(16u, instruction->GetVectorLength());
707 __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
708 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100709 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700710 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100711 __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikc8e93c72017-05-10 10:49:22 -0700712 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100713 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100714 DCHECK_EQ(8u, instruction->GetVectorLength());
715 __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
716 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100717 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700718 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100719 __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikc8e93c72017-05-10 10:49:22 -0700720 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800721 case DataType::Type::kUint32:
722 DCHECK_EQ(4u, instruction->GetVectorLength());
723 __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S());
724 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100725 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700726 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800727 __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikc8e93c72017-05-10 10:49:22 -0700728 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100729 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700730 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700731 __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S());
732 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100733 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700734 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700735 __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D());
736 break;
737 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800738 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700739 UNREACHABLE();
740 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700741}
742
Aart Bikf8f5a162017-02-06 15:35:29 -0800743void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100744 // TODO: Allow constants supported by BIC (vector, immediate).
Vladimir Markoca6fff82017-10-03 14:49:14 +0100745 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800746}
747
748void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
749 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100750 VRegister lhs = VRegisterFrom(locations->InAt(0));
751 VRegister rhs = VRegisterFrom(locations->InAt(1));
752 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800753 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100754 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100755 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100756 case DataType::Type::kInt8:
757 case DataType::Type::kUint16:
758 case DataType::Type::kInt16:
759 case DataType::Type::kInt32:
760 case DataType::Type::kInt64:
761 case DataType::Type::kFloat32:
762 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100763 __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800764 break;
765 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800766 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800767 UNREACHABLE();
768 }
769}
770
771void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
772 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
773}
774
775void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100776 // TODO: Use BIC (vector, register).
Aart Bikf8f5a162017-02-06 15:35:29 -0800777 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
778}
779
780void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100781 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800782}
783
784void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
785 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100786 VRegister lhs = VRegisterFrom(locations->InAt(0));
787 VRegister rhs = VRegisterFrom(locations->InAt(1));
788 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800789 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100790 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100791 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100792 case DataType::Type::kInt8:
793 case DataType::Type::kUint16:
794 case DataType::Type::kInt16:
795 case DataType::Type::kInt32:
796 case DataType::Type::kInt64:
797 case DataType::Type::kFloat32:
798 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100799 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800800 break;
801 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800802 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800803 UNREACHABLE();
804 }
805}
806
807void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100808 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800809}
810
811void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
812 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100813 VRegister lhs = VRegisterFrom(locations->InAt(0));
814 VRegister rhs = VRegisterFrom(locations->InAt(1));
815 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800816 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100817 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100818 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100819 case DataType::Type::kInt8:
820 case DataType::Type::kUint16:
821 case DataType::Type::kInt16:
822 case DataType::Type::kInt32:
823 case DataType::Type::kInt64:
824 case DataType::Type::kFloat32:
825 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100826 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800827 break;
828 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800829 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800830 UNREACHABLE();
831 }
832}
833
834// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100835static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
836 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800837 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:
840 case DataType::Type::kUint16:
841 case DataType::Type::kInt16:
842 case DataType::Type::kInt32:
843 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800844 locations->SetInAt(0, Location::RequiresFpuRegister());
845 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
846 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
847 break;
848 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800849 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800850 UNREACHABLE();
851 }
852}
853
854void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100855 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800856}
857
858void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
859 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100860 VRegister lhs = VRegisterFrom(locations->InAt(0));
861 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800862 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
863 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100864 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100865 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100866 DCHECK_EQ(16u, instruction->GetVectorLength());
867 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800868 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100869 case DataType::Type::kUint16:
870 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100871 DCHECK_EQ(8u, instruction->GetVectorLength());
872 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800873 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100874 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100875 DCHECK_EQ(4u, instruction->GetVectorLength());
876 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800877 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100878 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100879 DCHECK_EQ(2u, instruction->GetVectorLength());
880 __ Shl(dst.V2D(), lhs.V2D(), value);
881 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800882 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800883 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800884 UNREACHABLE();
885 }
886}
887
888void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100889 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800890}
891
892void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
893 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100894 VRegister lhs = VRegisterFrom(locations->InAt(0));
895 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800896 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
897 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100898 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100899 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100900 DCHECK_EQ(16u, instruction->GetVectorLength());
901 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800902 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100903 case DataType::Type::kUint16:
904 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100905 DCHECK_EQ(8u, instruction->GetVectorLength());
906 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800907 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100908 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100909 DCHECK_EQ(4u, instruction->GetVectorLength());
910 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800911 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100912 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100913 DCHECK_EQ(2u, instruction->GetVectorLength());
914 __ Sshr(dst.V2D(), lhs.V2D(), value);
915 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800916 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800917 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800918 UNREACHABLE();
919 }
920}
921
922void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100923 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800924}
925
926void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
927 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100928 VRegister lhs = VRegisterFrom(locations->InAt(0));
929 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800930 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
931 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100932 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100933 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100934 DCHECK_EQ(16u, instruction->GetVectorLength());
935 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800936 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100937 case DataType::Type::kUint16:
938 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100939 DCHECK_EQ(8u, instruction->GetVectorLength());
940 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800941 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100942 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100943 DCHECK_EQ(4u, instruction->GetVectorLength());
944 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800945 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100946 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100947 DCHECK_EQ(2u, instruction->GetVectorLength());
948 __ Ushr(dst.V2D(), lhs.V2D(), value);
949 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800950 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800951 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800952 UNREACHABLE();
953 }
954}
955
Aart Bik0148de42017-09-05 09:25:01 -0700956void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100957 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700958
959 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
960
961 HInstruction* input = instruction->InputAt(0);
962 bool is_zero = IsZeroBitPattern(input);
963
964 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100965 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100966 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100967 case DataType::Type::kInt8:
968 case DataType::Type::kUint16:
969 case DataType::Type::kInt16:
970 case DataType::Type::kInt32:
971 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700972 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
973 : Location::RequiresRegister());
974 locations->SetOut(Location::RequiresFpuRegister());
975 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100976 case DataType::Type::kFloat32:
977 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700978 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
979 : Location::RequiresFpuRegister());
980 locations->SetOut(Location::RequiresFpuRegister());
981 break;
982 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800983 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700984 UNREACHABLE();
985 }
986}
987
988void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
989 LocationSummary* locations = instruction->GetLocations();
990 VRegister dst = VRegisterFrom(locations->Out());
991
992 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
993
994 // Zero out all other elements first.
995 __ Movi(dst.V16B(), 0);
996
997 // Shorthand for any type of zero.
998 if (IsZeroBitPattern(instruction->InputAt(0))) {
999 return;
1000 }
1001
1002 // Set required elements.
1003 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001004 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001005 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001006 case DataType::Type::kInt8:
Aart Bik0148de42017-09-05 09:25:01 -07001007 DCHECK_EQ(16u, instruction->GetVectorLength());
1008 __ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0));
1009 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001010 case DataType::Type::kUint16:
1011 case DataType::Type::kInt16:
Aart Bik0148de42017-09-05 09:25:01 -07001012 DCHECK_EQ(8u, instruction->GetVectorLength());
1013 __ Mov(dst.V8H(), 0, InputRegisterAt(instruction, 0));
1014 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001015 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001016 DCHECK_EQ(4u, instruction->GetVectorLength());
1017 __ Mov(dst.V4S(), 0, InputRegisterAt(instruction, 0));
1018 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001019 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -07001020 DCHECK_EQ(2u, instruction->GetVectorLength());
1021 __ Mov(dst.V2D(), 0, InputRegisterAt(instruction, 0));
1022 break;
1023 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001024 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001025 UNREACHABLE();
1026 }
1027}
1028
Aart Bikdbbac8f2017-09-01 13:06:08 -07001029// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001030static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1031 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001032 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001033 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001034 case DataType::Type::kInt8:
1035 case DataType::Type::kUint16:
1036 case DataType::Type::kInt16:
1037 case DataType::Type::kInt32:
1038 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001039 locations->SetInAt(0, Location::RequiresFpuRegister());
1040 locations->SetInAt(1, Location::RequiresFpuRegister());
1041 locations->SetInAt(2, Location::RequiresFpuRegister());
Artem Serovf34dd202017-04-10 17:41:46 +01001042 locations->SetOut(Location::SameAsFirstInput());
1043 break;
1044 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001045 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serovf34dd202017-04-10 17:41:46 +01001046 UNREACHABLE();
1047 }
1048}
1049
Aart Bikdbbac8f2017-09-01 13:06:08 -07001050void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001051 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001052}
1053
Artem Serovf34dd202017-04-10 17:41:46 +01001054// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
1055// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
1056// However vector MultiplyAccumulate instruction is not affected.
Aart Bikdbbac8f2017-09-01 13:06:08 -07001057void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1058 LocationSummary* locations = instruction->GetLocations();
1059 VRegister acc = VRegisterFrom(locations->InAt(0));
1060 VRegister left = VRegisterFrom(locations->InAt(1));
1061 VRegister right = VRegisterFrom(locations->InAt(2));
1062
1063 DCHECK(locations->InAt(0).Equals(locations->Out()));
1064
1065 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001066 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001067 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001068 DCHECK_EQ(16u, instruction->GetVectorLength());
1069 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001070 __ Mla(acc.V16B(), left.V16B(), right.V16B());
1071 } else {
1072 __ Mls(acc.V16B(), left.V16B(), right.V16B());
1073 }
1074 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001075 case DataType::Type::kUint16:
1076 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001077 DCHECK_EQ(8u, instruction->GetVectorLength());
1078 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001079 __ Mla(acc.V8H(), left.V8H(), right.V8H());
1080 } else {
1081 __ Mls(acc.V8H(), left.V8H(), right.V8H());
1082 }
1083 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001084 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001085 DCHECK_EQ(4u, instruction->GetVectorLength());
1086 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001087 __ Mla(acc.V4S(), left.V4S(), right.V4S());
1088 } else {
1089 __ Mls(acc.V4S(), left.V4S(), right.V4S());
1090 }
1091 break;
1092 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001093 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001094 UNREACHABLE();
1095 }
1096}
1097
1098void LocationsBuilderARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001099 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001100 // Some conversions require temporary registers.
1101 LocationSummary* locations = instruction->GetLocations();
1102 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1103 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
Vladimir Marko61b92282017-10-11 13:23:17 +01001104 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1105 HVecOperation::ToSignedType(b->GetPackedType()));
Aart Bikdbbac8f2017-09-01 13:06:08 -07001106 switch (a->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001107 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001108 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001109 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001110 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001111 locations->AddTemp(Location::RequiresFpuRegister());
1112 locations->AddTemp(Location::RequiresFpuRegister());
1113 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001114 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001115 locations->AddTemp(Location::RequiresFpuRegister());
1116 locations->AddTemp(Location::RequiresFpuRegister());
1117 break;
1118 default:
1119 break;
1120 }
1121 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001122 case DataType::Type::kUint16:
1123 case DataType::Type::kInt16:
1124 if (instruction->GetPackedType() == DataType::Type::kInt64) {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001125 locations->AddTemp(Location::RequiresFpuRegister());
1126 locations->AddTemp(Location::RequiresFpuRegister());
1127 }
1128 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001129 case DataType::Type::kInt32:
1130 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001131 if (instruction->GetPackedType() == a->GetPackedType()) {
1132 locations->AddTemp(Location::RequiresFpuRegister());
1133 }
1134 break;
1135 default:
1136 break;
1137 }
1138}
1139
1140void InstructionCodeGeneratorARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
1141 LocationSummary* locations = instruction->GetLocations();
1142 VRegister acc = VRegisterFrom(locations->InAt(0));
1143 VRegister left = VRegisterFrom(locations->InAt(1));
1144 VRegister right = VRegisterFrom(locations->InAt(2));
1145
1146 DCHECK(locations->InAt(0).Equals(locations->Out()));
1147
1148 // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
1149 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1150 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
Vladimir Marko61b92282017-10-11 13:23:17 +01001151 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1152 HVecOperation::ToSignedType(b->GetPackedType()));
Aart Bikdbbac8f2017-09-01 13:06:08 -07001153 switch (a->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001154 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001155 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001156 DCHECK_EQ(16u, a->GetVectorLength());
1157 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001158 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001159 DCHECK_EQ(8u, instruction->GetVectorLength());
1160 __ Sabal(acc.V8H(), left.V8B(), right.V8B());
1161 __ Sabal2(acc.V8H(), left.V16B(), right.V16B());
1162 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001163 case DataType::Type::kInt32: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001164 DCHECK_EQ(4u, instruction->GetVectorLength());
1165 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1166 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1167 __ Sxtl(tmp1.V8H(), left.V8B());
1168 __ Sxtl(tmp2.V8H(), right.V8B());
1169 __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
1170 __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
1171 __ Sxtl2(tmp1.V8H(), left.V16B());
1172 __ Sxtl2(tmp2.V8H(), right.V16B());
1173 __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
1174 __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
1175 break;
1176 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001177 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001178 DCHECK_EQ(2u, instruction->GetVectorLength());
1179 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1180 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1181 VRegister tmp3 = VRegisterFrom(locations->GetTemp(2));
1182 VRegister tmp4 = VRegisterFrom(locations->GetTemp(3));
1183 __ Sxtl(tmp1.V8H(), left.V8B());
1184 __ Sxtl(tmp2.V8H(), right.V8B());
1185 __ Sxtl(tmp3.V4S(), tmp1.V4H());
1186 __ Sxtl(tmp4.V4S(), tmp2.V4H());
1187 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1188 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1189 __ Sxtl2(tmp3.V4S(), tmp1.V8H());
1190 __ Sxtl2(tmp4.V4S(), tmp2.V8H());
1191 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1192 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1193 __ Sxtl2(tmp1.V8H(), left.V16B());
1194 __ Sxtl2(tmp2.V8H(), right.V16B());
1195 __ Sxtl(tmp3.V4S(), tmp1.V4H());
1196 __ Sxtl(tmp4.V4S(), tmp2.V4H());
1197 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1198 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1199 __ Sxtl2(tmp3.V4S(), tmp1.V8H());
1200 __ Sxtl2(tmp4.V4S(), tmp2.V8H());
1201 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1202 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1203 break;
1204 }
1205 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001206 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001207 UNREACHABLE();
1208 }
1209 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001210 case DataType::Type::kUint16:
1211 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001212 DCHECK_EQ(8u, a->GetVectorLength());
1213 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001214 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001215 DCHECK_EQ(4u, instruction->GetVectorLength());
1216 __ Sabal(acc.V4S(), left.V4H(), right.V4H());
1217 __ Sabal2(acc.V4S(), left.V8H(), right.V8H());
1218 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001219 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001220 DCHECK_EQ(2u, instruction->GetVectorLength());
1221 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1222 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1223 __ Sxtl(tmp1.V4S(), left.V4H());
1224 __ Sxtl(tmp2.V4S(), right.V4H());
1225 __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
1226 __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
1227 __ Sxtl2(tmp1.V4S(), left.V8H());
1228 __ Sxtl2(tmp2.V4S(), right.V8H());
1229 __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
1230 __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
1231 break;
1232 }
1233 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001234 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001235 UNREACHABLE();
1236 }
1237 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001238 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001239 DCHECK_EQ(4u, a->GetVectorLength());
1240 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001241 case DataType::Type::kInt32: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001242 DCHECK_EQ(4u, instruction->GetVectorLength());
1243 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1244 __ Sub(tmp.V4S(), left.V4S(), right.V4S());
1245 __ Abs(tmp.V4S(), tmp.V4S());
1246 __ Add(acc.V4S(), acc.V4S(), tmp.V4S());
1247 break;
1248 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001249 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001250 DCHECK_EQ(2u, instruction->GetVectorLength());
1251 __ Sabal(acc.V2D(), left.V2S(), right.V2S());
1252 __ Sabal2(acc.V2D(), left.V4S(), right.V4S());
1253 break;
1254 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001255 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001256 UNREACHABLE();
1257 }
1258 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001259 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001260 DCHECK_EQ(2u, a->GetVectorLength());
1261 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001262 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001263 DCHECK_EQ(2u, instruction->GetVectorLength());
1264 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1265 __ Sub(tmp.V2D(), left.V2D(), right.V2D());
1266 __ Abs(tmp.V2D(), tmp.V2D());
1267 __ Add(acc.V2D(), acc.V2D(), tmp.V2D());
1268 break;
1269 }
1270 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001271 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001272 UNREACHABLE();
1273 }
1274 break;
1275 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001276 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serovf34dd202017-04-10 17:41:46 +01001277 }
1278}
1279
Aart Bikf8f5a162017-02-06 15:35:29 -08001280// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001281static void CreateVecMemLocations(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001282 HVecMemoryOperation* instruction,
1283 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001284 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001285 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001286 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001287 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001288 case DataType::Type::kInt8:
1289 case DataType::Type::kUint16:
1290 case DataType::Type::kInt16:
1291 case DataType::Type::kInt32:
1292 case DataType::Type::kInt64:
1293 case DataType::Type::kFloat32:
1294 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001295 locations->SetInAt(0, Location::RequiresRegister());
1296 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1297 if (is_load) {
1298 locations->SetOut(Location::RequiresFpuRegister());
1299 } else {
1300 locations->SetInAt(2, Location::RequiresFpuRegister());
1301 }
1302 break;
1303 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001304 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001305 UNREACHABLE();
1306 }
1307}
1308
Aart Bik472821b2017-04-27 17:23:51 -07001309// Helper to set up locations for vector memory operations. Returns the memory operand and,
1310// if used, sets the output parameter scratch to a temporary register used in this operand,
1311// so that the client can release it right after the memory operand use.
1312MemOperand InstructionCodeGeneratorARM64::VecAddress(
Aart Bikf8f5a162017-02-06 15:35:29 -08001313 HVecMemoryOperation* instruction,
Aart Bik472821b2017-04-27 17:23:51 -07001314 UseScratchRegisterScope* temps_scope,
1315 size_t size,
1316 bool is_string_char_at,
1317 /*out*/ Register* scratch) {
Aart Bikf8f5a162017-02-06 15:35:29 -08001318 LocationSummary* locations = instruction->GetLocations();
1319 Register base = InputRegisterAt(instruction, 0);
Artem Serove1811ed2017-04-27 16:50:47 +01001320
1321 if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
1322 DCHECK(!is_string_char_at);
1323 return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
1324 }
1325
Aart Bikf8f5a162017-02-06 15:35:29 -08001326 Location index = locations->InAt(1);
Aart Bik472821b2017-04-27 17:23:51 -07001327 uint32_t offset = is_string_char_at
1328 ? mirror::String::ValueOffset().Uint32Value()
1329 : mirror::Array::DataOffset(size).Uint32Value();
1330 size_t shift = ComponentSizeShiftWidth(size);
Aart Bikf8f5a162017-02-06 15:35:29 -08001331
Artem Serov0225b772017-04-19 15:43:53 +01001332 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
1333 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
1334
Aart Bikf8f5a162017-02-06 15:35:29 -08001335 if (index.IsConstant()) {
1336 offset += Int64ConstantFrom(index) << shift;
Artem Serov0225b772017-04-19 15:43:53 +01001337 return HeapOperand(base, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -08001338 } else {
Aart Bik472821b2017-04-27 17:23:51 -07001339 *scratch = temps_scope->AcquireSameSizeAs(base);
1340 __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
1341 return HeapOperand(*scratch, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -08001342 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001343}
1344
1345void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001346 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bikf8f5a162017-02-06 15:35:29 -08001347}
1348
1349void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001350 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001351 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001352 VRegister reg = VRegisterFrom(locations->Out());
Artem Serov0225b772017-04-19 15:43:53 +01001353 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -07001354 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +01001355
Aart Bikf8f5a162017-02-06 15:35:29 -08001356 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001357 case DataType::Type::kUint16:
Aart Bik472821b2017-04-27 17:23:51 -07001358 DCHECK_EQ(8u, instruction->GetVectorLength());
1359 // Special handling of compressed/uncompressed string load.
1360 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1361 vixl::aarch64::Label uncompressed_load, done;
1362 // Test compression bit.
1363 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
1364 "Expecting 0=compressed, 1=uncompressed");
1365 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
1366 Register length = temps.AcquireW();
1367 __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
1368 __ Tbnz(length.W(), 0, &uncompressed_load);
1369 temps.Release(length); // no longer needed
1370 // Zero extend 8 compressed bytes into 8 chars.
1371 __ Ldr(DRegisterFrom(locations->Out()).V8B(),
1372 VecAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
1373 __ Uxtl(reg.V8H(), reg.V8B());
1374 __ B(&done);
1375 if (scratch.IsValid()) {
1376 temps.Release(scratch); // if used, no longer needed
1377 }
1378 // Load 8 direct uncompressed chars.
1379 __ Bind(&uncompressed_load);
1380 __ Ldr(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
1381 __ Bind(&done);
1382 return;
1383 }
1384 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001385 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001386 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001387 case DataType::Type::kInt8:
1388 case DataType::Type::kInt16:
1389 case DataType::Type::kInt32:
1390 case DataType::Type::kFloat32:
1391 case DataType::Type::kInt64:
1392 case DataType::Type::kFloat64:
Artem Serov0225b772017-04-19 15:43:53 +01001393 DCHECK_LE(2u, instruction->GetVectorLength());
1394 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001395 __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001396 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001397 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001398 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001399 UNREACHABLE();
1400 }
1401}
1402
1403void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001404 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001405}
1406
1407void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001408 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001409 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001410 VRegister reg = VRegisterFrom(locations->InAt(2));
Artem Serov0225b772017-04-19 15:43:53 +01001411 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -07001412 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +01001413
Aart Bikf8f5a162017-02-06 15:35:29 -08001414 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001415 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001416 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001417 case DataType::Type::kInt8:
1418 case DataType::Type::kUint16:
1419 case DataType::Type::kInt16:
1420 case DataType::Type::kInt32:
1421 case DataType::Type::kFloat32:
1422 case DataType::Type::kInt64:
1423 case DataType::Type::kFloat64:
Artem Serov0225b772017-04-19 15:43:53 +01001424 DCHECK_LE(2u, instruction->GetVectorLength());
1425 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001426 __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001427 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001428 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001429 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001430 UNREACHABLE();
1431 }
1432}
1433
1434#undef __
1435
1436} // namespace arm64
1437} // namespace art