blob: df95c88c076a1ce9e34699da0bed08569aa241f6 [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
Artem Serov85dd9e32019-01-14 16:39:51 +000019#include "arch/arm64/instruction_set_features_arm64.h"
Aart Bikf8f5a162017-02-06 15:35:29 -080020#include "mirror/array-inl.h"
Andreas Gampe895f9222017-07-05 09:53:32 -070021#include "mirror/string.h"
Aart Bikf8f5a162017-02-06 15:35:29 -080022
23using namespace vixl::aarch64; // NOLINT(build/namespaces)
24
Vladimir Marko0a516052019-10-14 13:00:44 +000025namespace art {
Aart Bikf8f5a162017-02-06 15:35:29 -080026namespace arm64 {
27
Artem Serov8dfe7462017-06-01 14:28:48 +010028using helpers::ARM64EncodableConstantOrRegister;
29using helpers::Arm64CanEncodeConstantAsImmediate;
Aart Bik472821b2017-04-27 17:23:51 -070030using helpers::DRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080031using helpers::HeapOperand;
32using helpers::InputRegisterAt;
Evgeny Astigeevichf9e90542018-06-25 13:43:53 +010033using helpers::Int64FromLocation;
Aart Bik0148de42017-09-05 09:25:01 -070034using helpers::OutputRegister;
35using helpers::VRegisterFrom;
Nicolas Geoffray982334c2017-09-02 12:54:16 +000036using helpers::WRegisterFrom;
Aart Bik0148de42017-09-05 09:25:01 -070037using helpers::XRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080038
39#define __ GetVIXLAssembler()->
40
Artem Serov85dd9e32019-01-14 16:39:51 +000041// Build-time switch for Armv8.4-a dot product instructions.
42// TODO: Enable dot product when there is a device to test it on.
43static constexpr bool kArm64EmitDotProdInstructions = false;
44
45// Returns whether dot product instructions should be emitted.
46static bool ShouldEmitDotProductInstructions(const CodeGeneratorARM64* codegen_) {
47 return kArm64EmitDotProdInstructions && codegen_->GetInstructionSetFeatures().HasDotProd();
48}
49
Aart Bikf8f5a162017-02-06 15:35:29 -080050void LocationsBuilderARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010051 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Artem Serov8dfe7462017-06-01 14:28:48 +010052 HInstruction* input = instruction->InputAt(0);
Aart Bikf8f5a162017-02-06 15:35:29 -080053 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010054 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010055 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010056 case DataType::Type::kInt8:
57 case DataType::Type::kUint16:
58 case DataType::Type::kInt16:
59 case DataType::Type::kInt32:
60 case DataType::Type::kInt64:
Artem Serov8dfe7462017-06-01 14:28:48 +010061 locations->SetInAt(0, ARM64EncodableConstantOrRegister(input, instruction));
Aart Bikf8f5a162017-02-06 15:35:29 -080062 locations->SetOut(Location::RequiresFpuRegister());
63 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010064 case DataType::Type::kFloat32:
65 case DataType::Type::kFloat64:
Artem Serov8dfe7462017-06-01 14:28:48 +010066 if (input->IsConstant() &&
67 Arm64CanEncodeConstantAsImmediate(input->AsConstant(), instruction)) {
68 locations->SetInAt(0, Location::ConstantLocation(input->AsConstant()));
69 locations->SetOut(Location::RequiresFpuRegister());
70 } else {
71 locations->SetInAt(0, Location::RequiresFpuRegister());
72 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
73 }
Aart Bikf8f5a162017-02-06 15:35:29 -080074 break;
75 default:
Aart Bik29aa0822018-03-08 11:28:00 -080076 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -080077 UNREACHABLE();
78 }
79}
80
81void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
82 LocationSummary* locations = instruction->GetLocations();
Artem Serov8dfe7462017-06-01 14:28:48 +010083 Location src_loc = locations->InAt(0);
Artem Serovb31f91f2017-04-05 11:31:19 +010084 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -080085 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010086 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010087 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010088 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +010089 DCHECK_EQ(16u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010090 if (src_loc.IsConstant()) {
Evgeny Astigeevichf9e90542018-06-25 13:43:53 +010091 __ Movi(dst.V16B(), Int64FromLocation(src_loc));
Artem Serov8dfe7462017-06-01 14:28:48 +010092 } else {
93 __ Dup(dst.V16B(), InputRegisterAt(instruction, 0));
94 }
Aart Bikf8f5a162017-02-06 15:35:29 -080095 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010096 case DataType::Type::kUint16:
97 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +010098 DCHECK_EQ(8u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010099 if (src_loc.IsConstant()) {
Evgeny Astigeevichf9e90542018-06-25 13:43:53 +0100100 __ Movi(dst.V8H(), Int64FromLocation(src_loc));
Artem Serov8dfe7462017-06-01 14:28:48 +0100101 } else {
102 __ Dup(dst.V8H(), InputRegisterAt(instruction, 0));
103 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800104 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100105 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100106 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100107 if (src_loc.IsConstant()) {
Evgeny Astigeevichf9e90542018-06-25 13:43:53 +0100108 __ Movi(dst.V4S(), Int64FromLocation(src_loc));
Artem Serov8dfe7462017-06-01 14:28:48 +0100109 } else {
110 __ Dup(dst.V4S(), InputRegisterAt(instruction, 0));
111 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800112 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100113 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100114 DCHECK_EQ(2u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100115 if (src_loc.IsConstant()) {
Evgeny Astigeevichf9e90542018-06-25 13:43:53 +0100116 __ Movi(dst.V2D(), Int64FromLocation(src_loc));
Artem Serov8dfe7462017-06-01 14:28:48 +0100117 } else {
118 __ Dup(dst.V2D(), XRegisterFrom(src_loc));
119 }
Artem Serovb31f91f2017-04-05 11:31:19 +0100120 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100121 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100122 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100123 if (src_loc.IsConstant()) {
124 __ Fmov(dst.V4S(), src_loc.GetConstant()->AsFloatConstant()->GetValue());
125 } else {
126 __ Dup(dst.V4S(), VRegisterFrom(src_loc).V4S(), 0);
127 }
Artem Serovb31f91f2017-04-05 11:31:19 +0100128 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100129 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100130 DCHECK_EQ(2u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100131 if (src_loc.IsConstant()) {
132 __ Fmov(dst.V2D(), src_loc.GetConstant()->AsDoubleConstant()->GetValue());
133 } else {
134 __ Dup(dst.V2D(), VRegisterFrom(src_loc).V2D(), 0);
135 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800136 break;
137 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800138 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800139 UNREACHABLE();
140 }
141}
142
Aart Bik0148de42017-09-05 09:25:01 -0700143void LocationsBuilderARM64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100144 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700145 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100146 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100147 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100148 case DataType::Type::kInt8:
149 case DataType::Type::kUint16:
150 case DataType::Type::kInt16:
151 case DataType::Type::kInt32:
152 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700153 locations->SetInAt(0, Location::RequiresFpuRegister());
154 locations->SetOut(Location::RequiresRegister());
155 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100156 case DataType::Type::kFloat32:
157 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700158 locations->SetInAt(0, Location::RequiresFpuRegister());
159 locations->SetOut(Location::SameAsFirstInput());
160 break;
161 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800162 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700163 UNREACHABLE();
164 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800165}
166
Aart Bik0148de42017-09-05 09:25:01 -0700167void InstructionCodeGeneratorARM64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
168 LocationSummary* locations = instruction->GetLocations();
169 VRegister src = VRegisterFrom(locations->InAt(0));
170 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100171 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700172 DCHECK_EQ(4u, instruction->GetVectorLength());
173 __ Umov(OutputRegister(instruction), src.V4S(), 0);
174 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100175 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700176 DCHECK_EQ(2u, instruction->GetVectorLength());
177 __ Umov(OutputRegister(instruction), src.V2D(), 0);
178 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100179 case DataType::Type::kFloat32:
180 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700181 DCHECK_LE(2u, instruction->GetVectorLength());
182 DCHECK_LE(instruction->GetVectorLength(), 4u);
183 DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required
184 break;
185 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800186 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700187 UNREACHABLE();
188 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800189}
190
191// Helper to set up locations for vector unary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100192static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
193 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800194 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100195 case DataType::Type::kBool:
Aart Bikf8f5a162017-02-06 15:35:29 -0800196 locations->SetInAt(0, Location::RequiresFpuRegister());
197 locations->SetOut(Location::RequiresFpuRegister(),
198 instruction->IsVecNot() ? Location::kOutputOverlap
199 : Location::kNoOutputOverlap);
200 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100201 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100202 case DataType::Type::kInt8:
203 case DataType::Type::kUint16:
204 case DataType::Type::kInt16:
205 case DataType::Type::kInt32:
206 case DataType::Type::kInt64:
207 case DataType::Type::kFloat32:
208 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800209 locations->SetInAt(0, Location::RequiresFpuRegister());
210 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
211 break;
212 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800213 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800214 UNREACHABLE();
215 }
216}
217
Aart Bik0148de42017-09-05 09:25:01 -0700218void LocationsBuilderARM64::VisitVecReduce(HVecReduce* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100219 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700220}
221
222void InstructionCodeGeneratorARM64::VisitVecReduce(HVecReduce* instruction) {
223 LocationSummary* locations = instruction->GetLocations();
224 VRegister src = VRegisterFrom(locations->InAt(0));
225 VRegister dst = DRegisterFrom(locations->Out());
226 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100227 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700228 DCHECK_EQ(4u, instruction->GetVectorLength());
Vladimir Marko4e3734a2018-11-14 15:45:28 +0000229 switch (instruction->GetReductionKind()) {
Aart Bik0148de42017-09-05 09:25:01 -0700230 case HVecReduce::kSum:
231 __ Addv(dst.S(), src.V4S());
232 break;
233 case HVecReduce::kMin:
234 __ Sminv(dst.S(), src.V4S());
235 break;
236 case HVecReduce::kMax:
237 __ Smaxv(dst.S(), src.V4S());
238 break;
239 }
240 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100241 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700242 DCHECK_EQ(2u, instruction->GetVectorLength());
Vladimir Marko4e3734a2018-11-14 15:45:28 +0000243 switch (instruction->GetReductionKind()) {
Aart Bik0148de42017-09-05 09:25:01 -0700244 case HVecReduce::kSum:
245 __ Addp(dst.D(), src.V2D());
246 break;
247 default:
248 LOG(FATAL) << "Unsupported SIMD min/max";
249 UNREACHABLE();
250 }
251 break;
252 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800253 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700254 UNREACHABLE();
255 }
256}
257
Aart Bikf8f5a162017-02-06 15:35:29 -0800258void LocationsBuilderARM64::VisitVecCnv(HVecCnv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100259 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800260}
261
262void InstructionCodeGeneratorARM64::VisitVecCnv(HVecCnv* instruction) {
263 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100264 VRegister src = VRegisterFrom(locations->InAt(0));
265 VRegister dst = VRegisterFrom(locations->Out());
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100266 DataType::Type from = instruction->GetInputType();
267 DataType::Type to = instruction->GetResultType();
268 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Artem Serovd4bccf12017-04-03 18:47:32 +0100269 DCHECK_EQ(4u, instruction->GetVectorLength());
270 __ Scvtf(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800271 } else {
Aart Bik29aa0822018-03-08 11:28:00 -0800272 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800273 }
274}
275
276void LocationsBuilderARM64::VisitVecNeg(HVecNeg* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100277 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800278}
279
280void InstructionCodeGeneratorARM64::VisitVecNeg(HVecNeg* instruction) {
281 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100282 VRegister src = VRegisterFrom(locations->InAt(0));
283 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800284 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100285 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100286 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100287 DCHECK_EQ(16u, instruction->GetVectorLength());
288 __ Neg(dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800289 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100290 case DataType::Type::kUint16:
291 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100292 DCHECK_EQ(8u, instruction->GetVectorLength());
293 __ Neg(dst.V8H(), src.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800294 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100295 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100296 DCHECK_EQ(4u, instruction->GetVectorLength());
297 __ Neg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800298 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100299 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100300 DCHECK_EQ(2u, instruction->GetVectorLength());
301 __ Neg(dst.V2D(), src.V2D());
302 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100303 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100304 DCHECK_EQ(4u, instruction->GetVectorLength());
305 __ Fneg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800306 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100307 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100308 DCHECK_EQ(2u, instruction->GetVectorLength());
309 __ Fneg(dst.V2D(), src.V2D());
310 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800311 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800312 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800313 UNREACHABLE();
314 }
315}
316
Aart Bik6daebeb2017-04-03 14:35:41 -0700317void LocationsBuilderARM64::VisitVecAbs(HVecAbs* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100318 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik6daebeb2017-04-03 14:35:41 -0700319}
320
321void InstructionCodeGeneratorARM64::VisitVecAbs(HVecAbs* instruction) {
322 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100323 VRegister src = VRegisterFrom(locations->InAt(0));
324 VRegister dst = VRegisterFrom(locations->Out());
Aart Bik6daebeb2017-04-03 14:35:41 -0700325 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100326 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100327 DCHECK_EQ(16u, instruction->GetVectorLength());
328 __ Abs(dst.V16B(), src.V16B());
Aart Bik6daebeb2017-04-03 14:35:41 -0700329 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100330 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100331 DCHECK_EQ(8u, instruction->GetVectorLength());
332 __ Abs(dst.V8H(), src.V8H());
Aart Bik6daebeb2017-04-03 14:35:41 -0700333 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100334 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100335 DCHECK_EQ(4u, instruction->GetVectorLength());
336 __ Abs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700337 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100338 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100339 DCHECK_EQ(2u, instruction->GetVectorLength());
340 __ Abs(dst.V2D(), src.V2D());
341 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100342 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100343 DCHECK_EQ(4u, instruction->GetVectorLength());
344 __ Fabs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700345 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100346 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100347 DCHECK_EQ(2u, instruction->GetVectorLength());
348 __ Fabs(dst.V2D(), src.V2D());
349 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700350 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800351 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700352 UNREACHABLE();
Aart Bik6daebeb2017-04-03 14:35:41 -0700353 }
354}
355
Aart Bikf8f5a162017-02-06 15:35:29 -0800356void LocationsBuilderARM64::VisitVecNot(HVecNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100357 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800358}
359
360void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) {
361 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100362 VRegister src = VRegisterFrom(locations->InAt(0));
363 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800364 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100365 case DataType::Type::kBool: // special case boolean-not
Artem Serovd4bccf12017-04-03 18:47:32 +0100366 DCHECK_EQ(16u, instruction->GetVectorLength());
367 __ Movi(dst.V16B(), 1);
368 __ Eor(dst.V16B(), dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800369 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100370 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100371 case DataType::Type::kInt8:
372 case DataType::Type::kUint16:
373 case DataType::Type::kInt16:
374 case DataType::Type::kInt32:
375 case DataType::Type::kInt64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100376 __ Not(dst.V16B(), src.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800377 break;
378 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800379 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800380 UNREACHABLE();
381 }
382}
383
384// Helper to set up locations for vector binary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100385static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
386 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800387 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100388 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100389 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100390 case DataType::Type::kInt8:
391 case DataType::Type::kUint16:
392 case DataType::Type::kInt16:
393 case DataType::Type::kInt32:
394 case DataType::Type::kInt64:
395 case DataType::Type::kFloat32:
396 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800397 locations->SetInAt(0, Location::RequiresFpuRegister());
398 locations->SetInAt(1, Location::RequiresFpuRegister());
399 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
400 break;
401 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800402 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800403 UNREACHABLE();
404 }
405}
406
407void LocationsBuilderARM64::VisitVecAdd(HVecAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100408 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800409}
410
411void InstructionCodeGeneratorARM64::VisitVecAdd(HVecAdd* instruction) {
412 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100413 VRegister lhs = VRegisterFrom(locations->InAt(0));
414 VRegister rhs = VRegisterFrom(locations->InAt(1));
415 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800416 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100417 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100418 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100419 DCHECK_EQ(16u, instruction->GetVectorLength());
420 __ Add(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800421 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100422 case DataType::Type::kUint16:
423 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100424 DCHECK_EQ(8u, instruction->GetVectorLength());
425 __ Add(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800426 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100427 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100428 DCHECK_EQ(4u, instruction->GetVectorLength());
429 __ Add(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800430 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100431 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100432 DCHECK_EQ(2u, instruction->GetVectorLength());
433 __ Add(dst.V2D(), lhs.V2D(), rhs.V2D());
434 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100435 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100436 DCHECK_EQ(4u, instruction->GetVectorLength());
437 __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800438 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100439 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100440 DCHECK_EQ(2u, instruction->GetVectorLength());
441 __ Fadd(dst.V2D(), lhs.V2D(), rhs.V2D());
442 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800443 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800444 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
445 UNREACHABLE();
446 }
447}
448
449void LocationsBuilderARM64::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
450 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
451}
452
453void InstructionCodeGeneratorARM64::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
454 LocationSummary* locations = instruction->GetLocations();
455 VRegister lhs = VRegisterFrom(locations->InAt(0));
456 VRegister rhs = VRegisterFrom(locations->InAt(1));
457 VRegister dst = VRegisterFrom(locations->Out());
458 switch (instruction->GetPackedType()) {
459 case DataType::Type::kUint8:
460 DCHECK_EQ(16u, instruction->GetVectorLength());
461 __ Uqadd(dst.V16B(), lhs.V16B(), rhs.V16B());
462 break;
463 case DataType::Type::kInt8:
464 DCHECK_EQ(16u, instruction->GetVectorLength());
465 __ Sqadd(dst.V16B(), lhs.V16B(), rhs.V16B());
466 break;
467 case DataType::Type::kUint16:
468 DCHECK_EQ(8u, instruction->GetVectorLength());
469 __ Uqadd(dst.V8H(), lhs.V8H(), rhs.V8H());
470 break;
471 case DataType::Type::kInt16:
472 DCHECK_EQ(8u, instruction->GetVectorLength());
473 __ Sqadd(dst.V8H(), lhs.V8H(), rhs.V8H());
474 break;
475 default:
476 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800477 UNREACHABLE();
478 }
479}
480
Aart Bikf3e61ee2017-04-12 17:09:20 -0700481void LocationsBuilderARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100482 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700483}
484
485void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
486 LocationSummary* locations = instruction->GetLocations();
487 VRegister lhs = VRegisterFrom(locations->InAt(0));
488 VRegister rhs = VRegisterFrom(locations->InAt(1));
489 VRegister dst = VRegisterFrom(locations->Out());
490 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100491 case DataType::Type::kUint8:
492 DCHECK_EQ(16u, instruction->GetVectorLength());
493 instruction->IsRounded()
494 ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
495 : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
496 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100497 case DataType::Type::kInt8:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700498 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100499 instruction->IsRounded()
500 ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
501 : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700502 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100503 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100504 DCHECK_EQ(8u, instruction->GetVectorLength());
505 instruction->IsRounded()
506 ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
507 : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
508 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100509 case DataType::Type::kInt16:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700510 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100511 instruction->IsRounded()
512 ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
513 : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700514 break;
515 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800516 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf3e61ee2017-04-12 17:09:20 -0700517 UNREACHABLE();
518 }
519}
520
Aart Bikf8f5a162017-02-06 15:35:29 -0800521void LocationsBuilderARM64::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100522 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800523}
524
525void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* 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 __ Sub(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 __ Sub(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 __ Sub(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::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100546 DCHECK_EQ(2u, instruction->GetVectorLength());
547 __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D());
548 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100549 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100550 DCHECK_EQ(4u, instruction->GetVectorLength());
551 __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800552 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100553 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100554 DCHECK_EQ(2u, instruction->GetVectorLength());
555 __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D());
556 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800557 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800558 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
559 UNREACHABLE();
560 }
561}
562
563void LocationsBuilderARM64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
564 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
565}
566
567void InstructionCodeGeneratorARM64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
568 LocationSummary* locations = instruction->GetLocations();
569 VRegister lhs = VRegisterFrom(locations->InAt(0));
570 VRegister rhs = VRegisterFrom(locations->InAt(1));
571 VRegister dst = VRegisterFrom(locations->Out());
572 switch (instruction->GetPackedType()) {
573 case DataType::Type::kUint8:
574 DCHECK_EQ(16u, instruction->GetVectorLength());
575 __ Uqsub(dst.V16B(), lhs.V16B(), rhs.V16B());
576 break;
577 case DataType::Type::kInt8:
578 DCHECK_EQ(16u, instruction->GetVectorLength());
579 __ Sqsub(dst.V16B(), lhs.V16B(), rhs.V16B());
580 break;
581 case DataType::Type::kUint16:
582 DCHECK_EQ(8u, instruction->GetVectorLength());
583 __ Uqsub(dst.V8H(), lhs.V8H(), rhs.V8H());
584 break;
585 case DataType::Type::kInt16:
586 DCHECK_EQ(8u, instruction->GetVectorLength());
587 __ Sqsub(dst.V8H(), lhs.V8H(), rhs.V8H());
588 break;
589 default:
590 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800591 UNREACHABLE();
592 }
593}
594
595void LocationsBuilderARM64::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100596 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800597}
598
599void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) {
600 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100601 VRegister lhs = VRegisterFrom(locations->InAt(0));
602 VRegister rhs = VRegisterFrom(locations->InAt(1));
603 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800604 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100605 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100606 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100607 DCHECK_EQ(16u, instruction->GetVectorLength());
608 __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800609 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100610 case DataType::Type::kUint16:
611 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100612 DCHECK_EQ(8u, instruction->GetVectorLength());
613 __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800614 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100615 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100616 DCHECK_EQ(4u, instruction->GetVectorLength());
617 __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800618 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100619 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100620 DCHECK_EQ(4u, instruction->GetVectorLength());
621 __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800622 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100623 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100624 DCHECK_EQ(2u, instruction->GetVectorLength());
625 __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D());
626 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800627 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800628 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800629 UNREACHABLE();
630 }
631}
632
633void LocationsBuilderARM64::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100634 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800635}
636
637void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) {
638 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100639 VRegister lhs = VRegisterFrom(locations->InAt(0));
640 VRegister rhs = VRegisterFrom(locations->InAt(1));
641 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800642 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100643 case DataType::Type::kFloat32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100644 DCHECK_EQ(4u, instruction->GetVectorLength());
645 __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800646 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100647 case DataType::Type::kFloat64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100648 DCHECK_EQ(2u, instruction->GetVectorLength());
649 __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D());
650 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800651 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800652 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800653 UNREACHABLE();
654 }
655}
656
Aart Bikf3e61ee2017-04-12 17:09:20 -0700657void LocationsBuilderARM64::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100658 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700659}
660
661void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700662 LocationSummary* locations = instruction->GetLocations();
663 VRegister lhs = VRegisterFrom(locations->InAt(0));
664 VRegister rhs = VRegisterFrom(locations->InAt(1));
665 VRegister dst = VRegisterFrom(locations->Out());
666 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100667 case DataType::Type::kUint8:
668 DCHECK_EQ(16u, instruction->GetVectorLength());
669 __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
670 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100671 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700672 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100673 __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikc8e93c72017-05-10 10:49:22 -0700674 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100675 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100676 DCHECK_EQ(8u, instruction->GetVectorLength());
677 __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
678 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100679 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700680 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100681 __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikc8e93c72017-05-10 10:49:22 -0700682 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800683 case DataType::Type::kUint32:
684 DCHECK_EQ(4u, instruction->GetVectorLength());
685 __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S());
686 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100687 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700688 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800689 __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikc8e93c72017-05-10 10:49:22 -0700690 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100691 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700692 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700693 __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S());
694 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100695 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700696 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700697 __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D());
698 break;
699 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800700 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700701 UNREACHABLE();
702 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700703}
704
705void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100706 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700707}
708
709void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700710 LocationSummary* locations = instruction->GetLocations();
711 VRegister lhs = VRegisterFrom(locations->InAt(0));
712 VRegister rhs = VRegisterFrom(locations->InAt(1));
713 VRegister dst = VRegisterFrom(locations->Out());
714 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100715 case DataType::Type::kUint8:
716 DCHECK_EQ(16u, instruction->GetVectorLength());
717 __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
718 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100719 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700720 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100721 __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikc8e93c72017-05-10 10:49:22 -0700722 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100723 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100724 DCHECK_EQ(8u, instruction->GetVectorLength());
725 __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
726 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100727 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700728 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100729 __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikc8e93c72017-05-10 10:49:22 -0700730 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800731 case DataType::Type::kUint32:
732 DCHECK_EQ(4u, instruction->GetVectorLength());
733 __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S());
734 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100735 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700736 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800737 __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikc8e93c72017-05-10 10:49:22 -0700738 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100739 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700740 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700741 __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S());
742 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100743 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700744 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700745 __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D());
746 break;
747 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800748 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700749 UNREACHABLE();
750 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700751}
752
Aart Bikf8f5a162017-02-06 15:35:29 -0800753void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100754 // TODO: Allow constants supported by BIC (vector, immediate).
Vladimir Markoca6fff82017-10-03 14:49:14 +0100755 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800756}
757
758void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
759 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100760 VRegister lhs = VRegisterFrom(locations->InAt(0));
761 VRegister rhs = VRegisterFrom(locations->InAt(1));
762 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800763 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100764 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100765 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100766 case DataType::Type::kInt8:
767 case DataType::Type::kUint16:
768 case DataType::Type::kInt16:
769 case DataType::Type::kInt32:
770 case DataType::Type::kInt64:
771 case DataType::Type::kFloat32:
772 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100773 __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800774 break;
775 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800776 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800777 UNREACHABLE();
778 }
779}
780
781void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
782 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
783}
784
785void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100786 // TODO: Use BIC (vector, register).
Aart Bikf8f5a162017-02-06 15:35:29 -0800787 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
788}
789
790void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100791 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800792}
793
794void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
795 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100796 VRegister lhs = VRegisterFrom(locations->InAt(0));
797 VRegister rhs = VRegisterFrom(locations->InAt(1));
798 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800799 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100800 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100801 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100802 case DataType::Type::kInt8:
803 case DataType::Type::kUint16:
804 case DataType::Type::kInt16:
805 case DataType::Type::kInt32:
806 case DataType::Type::kInt64:
807 case DataType::Type::kFloat32:
808 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100809 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800810 break;
811 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800812 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800813 UNREACHABLE();
814 }
815}
816
817void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100818 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800819}
820
821void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
822 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100823 VRegister lhs = VRegisterFrom(locations->InAt(0));
824 VRegister rhs = VRegisterFrom(locations->InAt(1));
825 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800826 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100827 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100828 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100829 case DataType::Type::kInt8:
830 case DataType::Type::kUint16:
831 case DataType::Type::kInt16:
832 case DataType::Type::kInt32:
833 case DataType::Type::kInt64:
834 case DataType::Type::kFloat32:
835 case DataType::Type::kFloat64:
Artem Serovd4bccf12017-04-03 18:47:32 +0100836 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800837 break;
838 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800839 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800840 UNREACHABLE();
841 }
842}
843
844// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100845static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
846 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800847 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100848 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100849 case DataType::Type::kInt8:
850 case DataType::Type::kUint16:
851 case DataType::Type::kInt16:
852 case DataType::Type::kInt32:
853 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800854 locations->SetInAt(0, Location::RequiresFpuRegister());
855 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
856 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
857 break;
858 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800859 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800860 UNREACHABLE();
861 }
862}
863
864void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100865 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800866}
867
868void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
869 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100870 VRegister lhs = VRegisterFrom(locations->InAt(0));
871 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800872 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
873 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100874 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100875 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100876 DCHECK_EQ(16u, instruction->GetVectorLength());
877 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800878 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100879 case DataType::Type::kUint16:
880 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100881 DCHECK_EQ(8u, instruction->GetVectorLength());
882 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800883 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100884 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100885 DCHECK_EQ(4u, instruction->GetVectorLength());
886 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800887 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100888 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100889 DCHECK_EQ(2u, instruction->GetVectorLength());
890 __ Shl(dst.V2D(), lhs.V2D(), value);
891 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800892 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800893 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800894 UNREACHABLE();
895 }
896}
897
898void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100899 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800900}
901
902void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
903 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100904 VRegister lhs = VRegisterFrom(locations->InAt(0));
905 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800906 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
907 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100908 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100909 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100910 DCHECK_EQ(16u, instruction->GetVectorLength());
911 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800912 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100913 case DataType::Type::kUint16:
914 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100915 DCHECK_EQ(8u, instruction->GetVectorLength());
916 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800917 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100918 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100919 DCHECK_EQ(4u, instruction->GetVectorLength());
920 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800921 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100922 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100923 DCHECK_EQ(2u, instruction->GetVectorLength());
924 __ Sshr(dst.V2D(), lhs.V2D(), value);
925 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800926 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800927 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800928 UNREACHABLE();
929 }
930}
931
932void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100933 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800934}
935
936void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
937 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100938 VRegister lhs = VRegisterFrom(locations->InAt(0));
939 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800940 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
941 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100942 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100943 case DataType::Type::kInt8:
Artem Serovd4bccf12017-04-03 18:47:32 +0100944 DCHECK_EQ(16u, instruction->GetVectorLength());
945 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800946 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100947 case DataType::Type::kUint16:
948 case DataType::Type::kInt16:
Artem Serovd4bccf12017-04-03 18:47:32 +0100949 DCHECK_EQ(8u, instruction->GetVectorLength());
950 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800951 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100952 case DataType::Type::kInt32:
Artem Serovd4bccf12017-04-03 18:47:32 +0100953 DCHECK_EQ(4u, instruction->GetVectorLength());
954 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800955 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100956 case DataType::Type::kInt64:
Artem Serovb31f91f2017-04-05 11:31:19 +0100957 DCHECK_EQ(2u, instruction->GetVectorLength());
958 __ Ushr(dst.V2D(), lhs.V2D(), value);
959 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800960 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800961 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800962 UNREACHABLE();
963 }
964}
965
Aart Bik0148de42017-09-05 09:25:01 -0700966void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100967 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700968
969 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
970
971 HInstruction* input = instruction->InputAt(0);
972 bool is_zero = IsZeroBitPattern(input);
973
974 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100975 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100976 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100977 case DataType::Type::kInt8:
978 case DataType::Type::kUint16:
979 case DataType::Type::kInt16:
980 case DataType::Type::kInt32:
981 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700982 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
983 : Location::RequiresRegister());
984 locations->SetOut(Location::RequiresFpuRegister());
985 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100986 case DataType::Type::kFloat32:
987 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700988 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
989 : Location::RequiresFpuRegister());
990 locations->SetOut(Location::RequiresFpuRegister());
991 break;
992 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800993 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700994 UNREACHABLE();
995 }
996}
997
998void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
999 LocationSummary* locations = instruction->GetLocations();
1000 VRegister dst = VRegisterFrom(locations->Out());
1001
1002 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
1003
1004 // Zero out all other elements first.
1005 __ Movi(dst.V16B(), 0);
1006
1007 // Shorthand for any type of zero.
1008 if (IsZeroBitPattern(instruction->InputAt(0))) {
1009 return;
1010 }
1011
1012 // Set required elements.
1013 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001014 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001015 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001016 case DataType::Type::kInt8:
Aart Bik0148de42017-09-05 09:25:01 -07001017 DCHECK_EQ(16u, instruction->GetVectorLength());
1018 __ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0));
1019 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001020 case DataType::Type::kUint16:
1021 case DataType::Type::kInt16:
Aart Bik0148de42017-09-05 09:25:01 -07001022 DCHECK_EQ(8u, instruction->GetVectorLength());
1023 __ Mov(dst.V8H(), 0, InputRegisterAt(instruction, 0));
1024 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001025 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001026 DCHECK_EQ(4u, instruction->GetVectorLength());
1027 __ Mov(dst.V4S(), 0, InputRegisterAt(instruction, 0));
1028 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001029 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -07001030 DCHECK_EQ(2u, instruction->GetVectorLength());
1031 __ Mov(dst.V2D(), 0, InputRegisterAt(instruction, 0));
1032 break;
1033 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001034 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001035 UNREACHABLE();
1036 }
1037}
1038
Aart Bikdbbac8f2017-09-01 13:06:08 -07001039// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001040static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1041 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001042 switch (instruction->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:
1045 case DataType::Type::kUint16:
1046 case DataType::Type::kInt16:
1047 case DataType::Type::kInt32:
1048 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001049 locations->SetInAt(0, Location::RequiresFpuRegister());
1050 locations->SetInAt(1, Location::RequiresFpuRegister());
1051 locations->SetInAt(2, Location::RequiresFpuRegister());
Artem Serovf34dd202017-04-10 17:41:46 +01001052 locations->SetOut(Location::SameAsFirstInput());
1053 break;
1054 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001055 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serovf34dd202017-04-10 17:41:46 +01001056 UNREACHABLE();
1057 }
1058}
1059
Aart Bikdbbac8f2017-09-01 13:06:08 -07001060void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001061 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001062}
1063
Artem Serovf34dd202017-04-10 17:41:46 +01001064// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
1065// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
1066// However vector MultiplyAccumulate instruction is not affected.
Aart Bikdbbac8f2017-09-01 13:06:08 -07001067void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1068 LocationSummary* locations = instruction->GetLocations();
1069 VRegister acc = VRegisterFrom(locations->InAt(0));
1070 VRegister left = VRegisterFrom(locations->InAt(1));
1071 VRegister right = VRegisterFrom(locations->InAt(2));
1072
1073 DCHECK(locations->InAt(0).Equals(locations->Out()));
1074
1075 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001076 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001077 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001078 DCHECK_EQ(16u, instruction->GetVectorLength());
1079 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001080 __ Mla(acc.V16B(), left.V16B(), right.V16B());
1081 } else {
1082 __ Mls(acc.V16B(), left.V16B(), right.V16B());
1083 }
1084 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001085 case DataType::Type::kUint16:
1086 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001087 DCHECK_EQ(8u, instruction->GetVectorLength());
1088 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001089 __ Mla(acc.V8H(), left.V8H(), right.V8H());
1090 } else {
1091 __ Mls(acc.V8H(), left.V8H(), right.V8H());
1092 }
1093 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001094 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001095 DCHECK_EQ(4u, instruction->GetVectorLength());
1096 if (instruction->GetOpKind() == HInstruction::kAdd) {
Artem Serovf34dd202017-04-10 17:41:46 +01001097 __ Mla(acc.V4S(), left.V4S(), right.V4S());
1098 } else {
1099 __ Mls(acc.V4S(), left.V4S(), right.V4S());
1100 }
1101 break;
1102 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001103 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001104 UNREACHABLE();
1105 }
1106}
1107
1108void LocationsBuilderARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001109 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001110 // Some conversions require temporary registers.
1111 LocationSummary* locations = instruction->GetLocations();
1112 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1113 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
Vladimir Marko61b92282017-10-11 13:23:17 +01001114 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1115 HVecOperation::ToSignedType(b->GetPackedType()));
Aart Bikdbbac8f2017-09-01 13:06:08 -07001116 switch (a->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001117 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001118 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001119 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001120 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001121 locations->AddTemp(Location::RequiresFpuRegister());
1122 locations->AddTemp(Location::RequiresFpuRegister());
1123 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001124 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001125 locations->AddTemp(Location::RequiresFpuRegister());
1126 locations->AddTemp(Location::RequiresFpuRegister());
1127 break;
1128 default:
1129 break;
1130 }
1131 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001132 case DataType::Type::kUint16:
1133 case DataType::Type::kInt16:
1134 if (instruction->GetPackedType() == DataType::Type::kInt64) {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001135 locations->AddTemp(Location::RequiresFpuRegister());
1136 locations->AddTemp(Location::RequiresFpuRegister());
1137 }
1138 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001139 case DataType::Type::kInt32:
1140 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001141 if (instruction->GetPackedType() == a->GetPackedType()) {
1142 locations->AddTemp(Location::RequiresFpuRegister());
1143 }
1144 break;
1145 default:
1146 break;
1147 }
1148}
1149
1150void InstructionCodeGeneratorARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
1151 LocationSummary* locations = instruction->GetLocations();
1152 VRegister acc = VRegisterFrom(locations->InAt(0));
1153 VRegister left = VRegisterFrom(locations->InAt(1));
1154 VRegister right = VRegisterFrom(locations->InAt(2));
1155
1156 DCHECK(locations->InAt(0).Equals(locations->Out()));
1157
1158 // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
1159 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1160 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
Vladimir Marko61b92282017-10-11 13:23:17 +01001161 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1162 HVecOperation::ToSignedType(b->GetPackedType()));
Aart Bikdbbac8f2017-09-01 13:06:08 -07001163 switch (a->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001164 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001165 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001166 DCHECK_EQ(16u, a->GetVectorLength());
1167 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001168 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001169 DCHECK_EQ(8u, instruction->GetVectorLength());
1170 __ Sabal(acc.V8H(), left.V8B(), right.V8B());
1171 __ Sabal2(acc.V8H(), left.V16B(), right.V16B());
1172 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001173 case DataType::Type::kInt32: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001174 DCHECK_EQ(4u, instruction->GetVectorLength());
1175 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1176 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1177 __ Sxtl(tmp1.V8H(), left.V8B());
1178 __ Sxtl(tmp2.V8H(), right.V8B());
1179 __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
1180 __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
1181 __ Sxtl2(tmp1.V8H(), left.V16B());
1182 __ Sxtl2(tmp2.V8H(), right.V16B());
1183 __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
1184 __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
1185 break;
1186 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001187 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001188 DCHECK_EQ(2u, instruction->GetVectorLength());
1189 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1190 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1191 VRegister tmp3 = VRegisterFrom(locations->GetTemp(2));
1192 VRegister tmp4 = VRegisterFrom(locations->GetTemp(3));
1193 __ Sxtl(tmp1.V8H(), left.V8B());
1194 __ Sxtl(tmp2.V8H(), right.V8B());
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 __ Sxtl2(tmp1.V8H(), left.V16B());
1204 __ Sxtl2(tmp2.V8H(), right.V16B());
1205 __ Sxtl(tmp3.V4S(), tmp1.V4H());
1206 __ Sxtl(tmp4.V4S(), tmp2.V4H());
1207 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1208 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1209 __ Sxtl2(tmp3.V4S(), tmp1.V8H());
1210 __ Sxtl2(tmp4.V4S(), tmp2.V8H());
1211 __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
1212 __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
1213 break;
1214 }
1215 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001216 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001217 UNREACHABLE();
1218 }
1219 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001220 case DataType::Type::kUint16:
1221 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001222 DCHECK_EQ(8u, a->GetVectorLength());
1223 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001224 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001225 DCHECK_EQ(4u, instruction->GetVectorLength());
1226 __ Sabal(acc.V4S(), left.V4H(), right.V4H());
1227 __ Sabal2(acc.V4S(), left.V8H(), right.V8H());
1228 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001229 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001230 DCHECK_EQ(2u, instruction->GetVectorLength());
1231 VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
1232 VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
1233 __ Sxtl(tmp1.V4S(), left.V4H());
1234 __ Sxtl(tmp2.V4S(), right.V4H());
1235 __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
1236 __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
1237 __ Sxtl2(tmp1.V4S(), left.V8H());
1238 __ Sxtl2(tmp2.V4S(), right.V8H());
1239 __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
1240 __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
1241 break;
1242 }
1243 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001244 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001245 UNREACHABLE();
1246 }
1247 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001248 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001249 DCHECK_EQ(4u, a->GetVectorLength());
1250 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001251 case DataType::Type::kInt32: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001252 DCHECK_EQ(4u, instruction->GetVectorLength());
1253 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1254 __ Sub(tmp.V4S(), left.V4S(), right.V4S());
1255 __ Abs(tmp.V4S(), tmp.V4S());
1256 __ Add(acc.V4S(), acc.V4S(), tmp.V4S());
1257 break;
1258 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001259 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001260 DCHECK_EQ(2u, instruction->GetVectorLength());
1261 __ Sabal(acc.V2D(), left.V2S(), right.V2S());
1262 __ Sabal2(acc.V2D(), left.V4S(), right.V4S());
1263 break;
1264 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001265 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001266 UNREACHABLE();
1267 }
1268 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001269 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001270 DCHECK_EQ(2u, a->GetVectorLength());
1271 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001272 case DataType::Type::kInt64: {
Aart Bikdbbac8f2017-09-01 13:06:08 -07001273 DCHECK_EQ(2u, instruction->GetVectorLength());
1274 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1275 __ Sub(tmp.V2D(), left.V2D(), right.V2D());
1276 __ Abs(tmp.V2D(), tmp.V2D());
1277 __ Add(acc.V2D(), acc.V2D(), tmp.V2D());
1278 break;
1279 }
1280 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001281 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001282 UNREACHABLE();
1283 }
1284 break;
1285 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001286 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Artem Serovf34dd202017-04-10 17:41:46 +01001287 }
1288}
1289
Artem Serovaaac0e32018-08-07 00:52:22 +01001290void LocationsBuilderARM64::VisitVecDotProd(HVecDotProd* instruction) {
1291 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
1292 DCHECK(instruction->GetPackedType() == DataType::Type::kInt32);
1293 locations->SetInAt(0, Location::RequiresFpuRegister());
1294 locations->SetInAt(1, Location::RequiresFpuRegister());
1295 locations->SetInAt(2, Location::RequiresFpuRegister());
1296 locations->SetOut(Location::SameAsFirstInput());
1297
Artem Serov85dd9e32019-01-14 16:39:51 +00001298 // For Int8 and Uint8 general case we need a temp register.
1299 if ((DataType::Size(instruction->InputAt(1)->AsVecOperation()->GetPackedType()) == 1) &&
1300 !ShouldEmitDotProductInstructions(codegen_)) {
Artem Serovaaac0e32018-08-07 00:52:22 +01001301 locations->AddTemp(Location::RequiresFpuRegister());
1302 }
1303}
1304
1305void InstructionCodeGeneratorARM64::VisitVecDotProd(HVecDotProd* instruction) {
1306 LocationSummary* locations = instruction->GetLocations();
1307 DCHECK(locations->InAt(0).Equals(locations->Out()));
1308 VRegister acc = VRegisterFrom(locations->InAt(0));
1309 VRegister left = VRegisterFrom(locations->InAt(1));
1310 VRegister right = VRegisterFrom(locations->InAt(2));
1311 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1312 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1313 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1314 HVecOperation::ToSignedType(b->GetPackedType()));
1315 DCHECK_EQ(instruction->GetPackedType(), DataType::Type::kInt32);
1316 DCHECK_EQ(4u, instruction->GetVectorLength());
1317
1318 size_t inputs_data_size = DataType::Size(a->GetPackedType());
1319 switch (inputs_data_size) {
1320 case 1u: {
1321 DCHECK_EQ(16u, a->GetVectorLength());
Artem Serovaaac0e32018-08-07 00:52:22 +01001322 if (instruction->IsZeroExtending()) {
Artem Serov85dd9e32019-01-14 16:39:51 +00001323 if (ShouldEmitDotProductInstructions(codegen_)) {
1324 __ Udot(acc.V4S(), left.V16B(), right.V16B());
1325 } else {
1326 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1327 __ Umull(tmp.V8H(), left.V8B(), right.V8B());
1328 __ Uaddw(acc.V4S(), acc.V4S(), tmp.V4H());
1329 __ Uaddw2(acc.V4S(), acc.V4S(), tmp.V8H());
Artem Serovaaac0e32018-08-07 00:52:22 +01001330
Artem Serov85dd9e32019-01-14 16:39:51 +00001331 __ Umull2(tmp.V8H(), left.V16B(), right.V16B());
1332 __ Uaddw(acc.V4S(), acc.V4S(), tmp.V4H());
1333 __ Uaddw2(acc.V4S(), acc.V4S(), tmp.V8H());
1334 }
Artem Serovaaac0e32018-08-07 00:52:22 +01001335 } else {
Artem Serov85dd9e32019-01-14 16:39:51 +00001336 if (ShouldEmitDotProductInstructions(codegen_)) {
1337 __ Sdot(acc.V4S(), left.V16B(), right.V16B());
1338 } else {
1339 VRegister tmp = VRegisterFrom(locations->GetTemp(0));
1340 __ Smull(tmp.V8H(), left.V8B(), right.V8B());
1341 __ Saddw(acc.V4S(), acc.V4S(), tmp.V4H());
1342 __ Saddw2(acc.V4S(), acc.V4S(), tmp.V8H());
Artem Serovaaac0e32018-08-07 00:52:22 +01001343
Artem Serov85dd9e32019-01-14 16:39:51 +00001344 __ Smull2(tmp.V8H(), left.V16B(), right.V16B());
1345 __ Saddw(acc.V4S(), acc.V4S(), tmp.V4H());
1346 __ Saddw2(acc.V4S(), acc.V4S(), tmp.V8H());
1347 }
Artem Serovaaac0e32018-08-07 00:52:22 +01001348 }
1349 break;
1350 }
1351 case 2u:
1352 DCHECK_EQ(8u, a->GetVectorLength());
1353 if (instruction->IsZeroExtending()) {
1354 __ Umlal(acc.V4S(), left.V4H(), right.V4H());
1355 __ Umlal2(acc.V4S(), left.V8H(), right.V8H());
1356 } else {
1357 __ Smlal(acc.V4S(), left.V4H(), right.V4H());
1358 __ Smlal2(acc.V4S(), left.V8H(), right.V8H());
1359 }
1360 break;
1361 default:
1362 LOG(FATAL) << "Unsupported SIMD type size: " << inputs_data_size;
1363 }
1364}
1365
Aart Bikf8f5a162017-02-06 15:35:29 -08001366// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001367static void CreateVecMemLocations(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001368 HVecMemoryOperation* instruction,
1369 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001370 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001371 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001372 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001373 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001374 case DataType::Type::kInt8:
1375 case DataType::Type::kUint16:
1376 case DataType::Type::kInt16:
1377 case DataType::Type::kInt32:
1378 case DataType::Type::kInt64:
1379 case DataType::Type::kFloat32:
1380 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001381 locations->SetInAt(0, Location::RequiresRegister());
1382 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1383 if (is_load) {
1384 locations->SetOut(Location::RequiresFpuRegister());
1385 } else {
1386 locations->SetInAt(2, Location::RequiresFpuRegister());
1387 }
1388 break;
1389 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001390 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001391 UNREACHABLE();
1392 }
1393}
1394
Aart Bik472821b2017-04-27 17:23:51 -07001395// Helper to set up locations for vector memory operations. Returns the memory operand and,
1396// if used, sets the output parameter scratch to a temporary register used in this operand,
1397// so that the client can release it right after the memory operand use.
1398MemOperand InstructionCodeGeneratorARM64::VecAddress(
Aart Bikf8f5a162017-02-06 15:35:29 -08001399 HVecMemoryOperation* instruction,
Aart Bik472821b2017-04-27 17:23:51 -07001400 UseScratchRegisterScope* temps_scope,
1401 size_t size,
1402 bool is_string_char_at,
1403 /*out*/ Register* scratch) {
Aart Bikf8f5a162017-02-06 15:35:29 -08001404 LocationSummary* locations = instruction->GetLocations();
1405 Register base = InputRegisterAt(instruction, 0);
Artem Serove1811ed2017-04-27 16:50:47 +01001406
1407 if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
1408 DCHECK(!is_string_char_at);
1409 return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
1410 }
1411
Aart Bikf8f5a162017-02-06 15:35:29 -08001412 Location index = locations->InAt(1);
Aart Bik472821b2017-04-27 17:23:51 -07001413 uint32_t offset = is_string_char_at
1414 ? mirror::String::ValueOffset().Uint32Value()
1415 : mirror::Array::DataOffset(size).Uint32Value();
1416 size_t shift = ComponentSizeShiftWidth(size);
Aart Bikf8f5a162017-02-06 15:35:29 -08001417
Artem Serov0225b772017-04-19 15:43:53 +01001418 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
1419 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
1420
Aart Bikf8f5a162017-02-06 15:35:29 -08001421 if (index.IsConstant()) {
Evgeny Astigeevichf9e90542018-06-25 13:43:53 +01001422 offset += Int64FromLocation(index) << shift;
Artem Serov0225b772017-04-19 15:43:53 +01001423 return HeapOperand(base, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -08001424 } else {
Aart Bik472821b2017-04-27 17:23:51 -07001425 *scratch = temps_scope->AcquireSameSizeAs(base);
1426 __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
1427 return HeapOperand(*scratch, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -08001428 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001429}
1430
1431void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001432 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bikf8f5a162017-02-06 15:35:29 -08001433}
1434
1435void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001436 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001437 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001438 VRegister reg = VRegisterFrom(locations->Out());
Artem Serov0225b772017-04-19 15:43:53 +01001439 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -07001440 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +01001441
Aart Bikf8f5a162017-02-06 15:35:29 -08001442 switch (instruction->GetPackedType()) {
Vladimir Marko805b6312018-09-05 14:46:06 +01001443 case DataType::Type::kInt16: // (short) s.charAt(.) can yield HVecLoad/Int16/StringCharAt.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001444 case DataType::Type::kUint16:
Aart Bik472821b2017-04-27 17:23:51 -07001445 DCHECK_EQ(8u, instruction->GetVectorLength());
1446 // Special handling of compressed/uncompressed string load.
1447 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1448 vixl::aarch64::Label uncompressed_load, done;
1449 // Test compression bit.
1450 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
1451 "Expecting 0=compressed, 1=uncompressed");
1452 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
1453 Register length = temps.AcquireW();
1454 __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
1455 __ Tbnz(length.W(), 0, &uncompressed_load);
1456 temps.Release(length); // no longer needed
1457 // Zero extend 8 compressed bytes into 8 chars.
1458 __ Ldr(DRegisterFrom(locations->Out()).V8B(),
1459 VecAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
1460 __ Uxtl(reg.V8H(), reg.V8B());
1461 __ B(&done);
1462 if (scratch.IsValid()) {
1463 temps.Release(scratch); // if used, no longer needed
1464 }
1465 // Load 8 direct uncompressed chars.
1466 __ Bind(&uncompressed_load);
1467 __ Ldr(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
1468 __ Bind(&done);
1469 return;
1470 }
1471 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001472 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001473 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001474 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001475 case DataType::Type::kInt32:
1476 case DataType::Type::kFloat32:
1477 case DataType::Type::kInt64:
1478 case DataType::Type::kFloat64:
Artem Serov0225b772017-04-19 15:43:53 +01001479 DCHECK_LE(2u, instruction->GetVectorLength());
1480 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001481 __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001482 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001483 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001484 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001485 UNREACHABLE();
1486 }
1487}
1488
1489void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001490 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001491}
1492
1493void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001494 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001495 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001496 VRegister reg = VRegisterFrom(locations->InAt(2));
Artem Serov0225b772017-04-19 15:43:53 +01001497 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -07001498 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +01001499
Aart Bikf8f5a162017-02-06 15:35:29 -08001500 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001501 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001502 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001503 case DataType::Type::kInt8:
1504 case DataType::Type::kUint16:
1505 case DataType::Type::kInt16:
1506 case DataType::Type::kInt32:
1507 case DataType::Type::kFloat32:
1508 case DataType::Type::kInt64:
1509 case DataType::Type::kFloat64:
Artem Serov0225b772017-04-19 15:43:53 +01001510 DCHECK_LE(2u, instruction->GetVectorLength());
1511 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001512 __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001513 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001514 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001515 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001516 UNREACHABLE();
1517 }
1518}
1519
1520#undef __
1521
1522} // namespace arm64
1523} // namespace art