blob: f2ffccc8879b5f46c33161fe27c6dc0f87dd38d0 [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_x86.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
22namespace art {
23namespace x86 {
24
25// NOLINT on __ macro to suppress wrong warning/fix (misc-macro-parentheses) from clang-tidy.
26#define __ down_cast<X86Assembler*>(GetAssembler())-> // NOLINT
27
28void LocationsBuilderX86::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010029 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -070030 HInstruction* input = instruction->InputAt(0);
31 bool is_zero = IsZeroBitPattern(input);
Aart Bikf8f5a162017-02-06 15:35:29 -080032 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010033 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -070034 // Long needs extra temporary to load from the register pair.
35 if (!is_zero) {
36 locations->AddTemp(Location::RequiresFpuRegister());
37 }
38 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010039 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010040 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010041 case DataType::Type::kInt8:
42 case DataType::Type::kUint16:
43 case DataType::Type::kInt16:
44 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -070045 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
46 : Location::RequiresRegister());
47 locations->SetOut(Location::RequiresFpuRegister());
48 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010049 case DataType::Type::kFloat32:
50 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -070051 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
52 : Location::RequiresFpuRegister());
53 locations->SetOut(is_zero ? Location::RequiresFpuRegister()
54 : Location::SameAsFirstInput());
Aart Bik0148de42017-09-05 09:25:01 -070055 break;
56 default:
57 LOG(FATAL) << "Unsupported SIMD type";
58 UNREACHABLE();
59 }
60}
61
62void InstructionCodeGeneratorX86::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
63 LocationSummary* locations = instruction->GetLocations();
64 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
65
66 // Shorthand for any type of zero.
67 if (IsZeroBitPattern(instruction->InputAt(0))) {
68 __ xorps(dst, dst);
69 return;
70 }
71
72 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010073 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010074 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010075 case DataType::Type::kInt8:
Aart Bik0148de42017-09-05 09:25:01 -070076 DCHECK_EQ(16u, instruction->GetVectorLength());
77 __ movd(dst, locations->InAt(0).AsRegister<Register>());
78 __ punpcklbw(dst, dst);
79 __ punpcklwd(dst, dst);
80 __ pshufd(dst, dst, Immediate(0));
81 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010082 case DataType::Type::kUint16:
83 case DataType::Type::kInt16:
Aart Bik0148de42017-09-05 09:25:01 -070084 DCHECK_EQ(8u, instruction->GetVectorLength());
85 __ movd(dst, locations->InAt(0).AsRegister<Register>());
86 __ punpcklwd(dst, dst);
87 __ pshufd(dst, dst, Immediate(0));
88 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010089 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -070090 DCHECK_EQ(4u, instruction->GetVectorLength());
91 __ movd(dst, locations->InAt(0).AsRegister<Register>());
92 __ pshufd(dst, dst, Immediate(0));
93 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010094 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -070095 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -080096 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Aart Bik0148de42017-09-05 09:25:01 -070097 __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
98 __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
99 __ punpckldq(dst, tmp);
100 __ punpcklqdq(dst, dst);
101 break;
102 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100103 case DataType::Type::kFloat32:
Aart Bik0148de42017-09-05 09:25:01 -0700104 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -0800105 DCHECK(locations->InAt(0).Equals(locations->Out()));
Aart Bik0148de42017-09-05 09:25:01 -0700106 __ shufps(dst, dst, Immediate(0));
107 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100108 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700109 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -0800110 DCHECK(locations->InAt(0).Equals(locations->Out()));
Aart Bik0148de42017-09-05 09:25:01 -0700111 __ shufpd(dst, dst, Immediate(0));
112 break;
113 default:
114 LOG(FATAL) << "Unsupported SIMD type";
115 UNREACHABLE();
116 }
117}
118
119void LocationsBuilderX86::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100120 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700121 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100122 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700123 // Long needs extra temporary to store into the register pair.
Aart Bika57b4ee2017-08-30 21:21:41 +0000124 locations->AddTemp(Location::RequiresFpuRegister());
Aart Bik9879d0e2017-08-15 10:51:25 -0700125 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100126 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100127 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100128 case DataType::Type::kInt8:
129 case DataType::Type::kUint16:
130 case DataType::Type::kInt16:
131 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700132 locations->SetInAt(0, Location::RequiresFpuRegister());
133 locations->SetOut(Location::RequiresRegister());
Aart Bik9879d0e2017-08-15 10:51:25 -0700134 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100135 case DataType::Type::kFloat32:
136 case DataType::Type::kFloat64:
Aart Bika57b4ee2017-08-30 21:21:41 +0000137 locations->SetInAt(0, Location::RequiresFpuRegister());
Aart Bik9879d0e2017-08-15 10:51:25 -0700138 locations->SetOut(Location::SameAsFirstInput());
139 break;
140 default:
141 LOG(FATAL) << "Unsupported SIMD type";
142 UNREACHABLE();
143 }
144}
145
Aart Bik0148de42017-09-05 09:25:01 -0700146void InstructionCodeGeneratorX86::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Aart Bik9879d0e2017-08-15 10:51:25 -0700147 LocationSummary* locations = instruction->GetLocations();
Aart Bik0148de42017-09-05 09:25:01 -0700148 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bik9879d0e2017-08-15 10:51:25 -0700149 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100150 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100151 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100152 case DataType::Type::kInt8:
153 case DataType::Type::kUint16:
154 case DataType::Type::kInt16: // TODO: up to here, and?
Aart Bik0148de42017-09-05 09:25:01 -0700155 LOG(FATAL) << "Unsupported SIMD type";
156 UNREACHABLE();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100157 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700158 DCHECK_LE(4u, instruction->GetVectorLength());
159 DCHECK_LE(instruction->GetVectorLength(), 16u);
160 __ movd(locations->Out().AsRegister<Register>(), src);
Aart Bik9879d0e2017-08-15 10:51:25 -0700161 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100162 case DataType::Type::kInt64: {
Aart Bik9879d0e2017-08-15 10:51:25 -0700163 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -0800164 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Aart Bik0148de42017-09-05 09:25:01 -0700165 __ movd(locations->Out().AsRegisterPairLow<Register>(), src);
166 __ pshufd(tmp, src, Immediate(1));
167 __ movd(locations->Out().AsRegisterPairHigh<Register>(), tmp);
Aart Bik9879d0e2017-08-15 10:51:25 -0700168 break;
169 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100170 case DataType::Type::kFloat32:
171 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700172 DCHECK_LE(2u, instruction->GetVectorLength());
173 DCHECK_LE(instruction->GetVectorLength(), 4u);
174 DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required
Aart Bik9879d0e2017-08-15 10:51:25 -0700175 break;
176 default:
177 LOG(FATAL) << "Unsupported SIMD type";
178 UNREACHABLE();
179 }
180}
181
Aart Bikf8f5a162017-02-06 15:35:29 -0800182// Helper to set up locations for vector unary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100183static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
184 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800185 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100186 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100187 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100188 case DataType::Type::kInt8:
189 case DataType::Type::kUint16:
190 case DataType::Type::kInt16:
191 case DataType::Type::kInt32:
192 case DataType::Type::kInt64:
193 case DataType::Type::kFloat32:
194 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800195 locations->SetInAt(0, Location::RequiresFpuRegister());
196 locations->SetOut(Location::RequiresFpuRegister());
197 break;
198 default:
199 LOG(FATAL) << "Unsupported SIMD type";
200 UNREACHABLE();
201 }
202}
203
Aart Bik0148de42017-09-05 09:25:01 -0700204void LocationsBuilderX86::VisitVecReduce(HVecReduce* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100205 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700206 // Long reduction or min/max require a temporary.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100207 if (instruction->GetPackedType() == DataType::Type::kInt64 ||
Aart Bik0148de42017-09-05 09:25:01 -0700208 instruction->GetKind() == HVecReduce::kMin ||
209 instruction->GetKind() == HVecReduce::kMax) {
210 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
211 }
212}
213
214void InstructionCodeGeneratorX86::VisitVecReduce(HVecReduce* instruction) {
215 LocationSummary* locations = instruction->GetLocations();
216 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
217 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
218 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100219 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700220 DCHECK_EQ(4u, instruction->GetVectorLength());
221 switch (instruction->GetKind()) {
222 case HVecReduce::kSum:
223 __ movaps(dst, src);
224 __ phaddd(dst, dst);
225 __ phaddd(dst, dst);
226 break;
227 case HVecReduce::kMin: {
228 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
229 __ movaps(tmp, src);
230 __ movaps(dst, src);
231 __ psrldq(tmp, Immediate(8));
232 __ pminsd(dst, tmp);
233 __ psrldq(tmp, Immediate(4));
234 __ pminsd(dst, tmp);
235 break;
236 }
237 case HVecReduce::kMax: {
238 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
239 __ movaps(tmp, src);
240 __ movaps(dst, src);
241 __ psrldq(tmp, Immediate(8));
242 __ pmaxsd(dst, tmp);
243 __ psrldq(tmp, Immediate(4));
244 __ pmaxsd(dst, tmp);
245 break;
246 }
247 }
248 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100249 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -0700250 DCHECK_EQ(2u, instruction->GetVectorLength());
251 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
252 switch (instruction->GetKind()) {
253 case HVecReduce::kSum:
254 __ movaps(tmp, src);
255 __ movaps(dst, src);
256 __ punpckhqdq(tmp, tmp);
257 __ paddq(dst, tmp);
258 break;
259 case HVecReduce::kMin:
260 case HVecReduce::kMax:
261 LOG(FATAL) << "Unsupported SIMD type";
262 }
263 break;
264 }
265 default:
266 LOG(FATAL) << "Unsupported SIMD type";
267 UNREACHABLE();
268 }
269}
270
Aart Bikf8f5a162017-02-06 15:35:29 -0800271void LocationsBuilderX86::VisitVecCnv(HVecCnv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100272 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800273}
274
275void InstructionCodeGeneratorX86::VisitVecCnv(HVecCnv* instruction) {
276 LocationSummary* locations = instruction->GetLocations();
277 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
278 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100279 DataType::Type from = instruction->GetInputType();
280 DataType::Type to = instruction->GetResultType();
281 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800282 DCHECK_EQ(4u, instruction->GetVectorLength());
283 __ cvtdq2ps(dst, src);
284 } else {
285 LOG(FATAL) << "Unsupported SIMD type";
286 }
287}
288
289void LocationsBuilderX86::VisitVecNeg(HVecNeg* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100290 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800291}
292
293void InstructionCodeGeneratorX86::VisitVecNeg(HVecNeg* instruction) {
294 LocationSummary* locations = instruction->GetLocations();
295 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
296 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
297 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100298 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100299 case DataType::Type::kInt8:
Aart Bikf8f5a162017-02-06 15:35:29 -0800300 DCHECK_EQ(16u, instruction->GetVectorLength());
301 __ pxor(dst, dst);
302 __ psubb(dst, src);
303 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100304 case DataType::Type::kUint16:
305 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800306 DCHECK_EQ(8u, instruction->GetVectorLength());
307 __ pxor(dst, dst);
308 __ psubw(dst, src);
309 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100310 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800311 DCHECK_EQ(4u, instruction->GetVectorLength());
312 __ pxor(dst, dst);
313 __ psubd(dst, src);
314 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100315 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800316 DCHECK_EQ(2u, instruction->GetVectorLength());
317 __ pxor(dst, dst);
318 __ psubq(dst, src);
319 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100320 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800321 DCHECK_EQ(4u, instruction->GetVectorLength());
322 __ xorps(dst, dst);
323 __ subps(dst, src);
324 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100325 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800326 DCHECK_EQ(2u, instruction->GetVectorLength());
327 __ xorpd(dst, dst);
328 __ subpd(dst, src);
329 break;
330 default:
331 LOG(FATAL) << "Unsupported SIMD type";
332 UNREACHABLE();
333 }
334}
335
Aart Bik6daebeb2017-04-03 14:35:41 -0700336void LocationsBuilderX86::VisitVecAbs(HVecAbs* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100337 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik472821b2017-04-27 17:23:51 -0700338 // Integral-abs requires a temporary for the comparison.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100339 if (instruction->GetPackedType() == DataType::Type::kInt32) {
Aart Bik6daebeb2017-04-03 14:35:41 -0700340 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
341 }
342}
343
344void InstructionCodeGeneratorX86::VisitVecAbs(HVecAbs* instruction) {
345 LocationSummary* locations = instruction->GetLocations();
346 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
347 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
348 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100349 case DataType::Type::kInt32: {
Aart Bik6daebeb2017-04-03 14:35:41 -0700350 DCHECK_EQ(4u, instruction->GetVectorLength());
351 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
352 __ movaps(dst, src);
353 __ pxor(tmp, tmp);
354 __ pcmpgtd(tmp, dst);
355 __ pxor(dst, tmp);
356 __ psubd(dst, tmp);
357 break;
358 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100359 case DataType::Type::kFloat32:
Aart Bik6daebeb2017-04-03 14:35:41 -0700360 DCHECK_EQ(4u, instruction->GetVectorLength());
361 __ pcmpeqb(dst, dst); // all ones
362 __ psrld(dst, Immediate(1));
363 __ andps(dst, src);
364 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100365 case DataType::Type::kFloat64:
Aart Bik6daebeb2017-04-03 14:35:41 -0700366 DCHECK_EQ(2u, instruction->GetVectorLength());
367 __ pcmpeqb(dst, dst); // all ones
368 __ psrlq(dst, Immediate(1));
369 __ andpd(dst, src);
370 break;
371 default:
372 LOG(FATAL) << "Unsupported SIMD type";
373 UNREACHABLE();
374 }
375}
376
Aart Bikf8f5a162017-02-06 15:35:29 -0800377void LocationsBuilderX86::VisitVecNot(HVecNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100378 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800379 // Boolean-not requires a temporary to construct the 16 x one.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100380 if (instruction->GetPackedType() == DataType::Type::kBool) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800381 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
382 }
383}
384
385void InstructionCodeGeneratorX86::VisitVecNot(HVecNot* instruction) {
386 LocationSummary* locations = instruction->GetLocations();
387 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
388 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
389 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100390 case DataType::Type::kBool: { // special case boolean-not
Aart Bikf8f5a162017-02-06 15:35:29 -0800391 DCHECK_EQ(16u, instruction->GetVectorLength());
392 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
393 __ pxor(dst, dst);
394 __ pcmpeqb(tmp, tmp); // all ones
395 __ psubb(dst, tmp); // 16 x one
396 __ pxor(dst, src);
397 break;
398 }
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100399 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100400 case DataType::Type::kInt8:
401 case DataType::Type::kUint16:
402 case DataType::Type::kInt16:
403 case DataType::Type::kInt32:
404 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800405 DCHECK_LE(2u, instruction->GetVectorLength());
406 DCHECK_LE(instruction->GetVectorLength(), 16u);
407 __ pcmpeqb(dst, dst); // all ones
408 __ pxor(dst, src);
409 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100410 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800411 DCHECK_EQ(4u, instruction->GetVectorLength());
412 __ pcmpeqb(dst, dst); // all ones
413 __ xorps(dst, src);
414 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100415 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800416 DCHECK_EQ(2u, instruction->GetVectorLength());
417 __ pcmpeqb(dst, dst); // all ones
418 __ xorpd(dst, src);
419 break;
420 default:
421 LOG(FATAL) << "Unsupported SIMD type";
422 UNREACHABLE();
423 }
424}
425
426// Helper to set up locations for vector binary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100427static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
428 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800429 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100430 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100431 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100432 case DataType::Type::kInt8:
433 case DataType::Type::kUint16:
434 case DataType::Type::kInt16:
435 case DataType::Type::kInt32:
436 case DataType::Type::kInt64:
437 case DataType::Type::kFloat32:
438 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800439 locations->SetInAt(0, Location::RequiresFpuRegister());
440 locations->SetInAt(1, Location::RequiresFpuRegister());
441 locations->SetOut(Location::SameAsFirstInput());
442 break;
443 default:
444 LOG(FATAL) << "Unsupported SIMD type";
445 UNREACHABLE();
446 }
447}
448
449void LocationsBuilderX86::VisitVecAdd(HVecAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100450 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800451}
452
453void InstructionCodeGeneratorX86::VisitVecAdd(HVecAdd* instruction) {
454 LocationSummary* locations = instruction->GetLocations();
455 DCHECK(locations->InAt(0).Equals(locations->Out()));
456 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
457 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
458 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100459 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100460 case DataType::Type::kInt8:
Aart Bikf8f5a162017-02-06 15:35:29 -0800461 DCHECK_EQ(16u, instruction->GetVectorLength());
462 __ paddb(dst, src);
463 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100464 case DataType::Type::kUint16:
465 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800466 DCHECK_EQ(8u, instruction->GetVectorLength());
467 __ paddw(dst, src);
468 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100469 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800470 DCHECK_EQ(4u, instruction->GetVectorLength());
471 __ paddd(dst, src);
472 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100473 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800474 DCHECK_EQ(2u, instruction->GetVectorLength());
475 __ paddq(dst, src);
476 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100477 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800478 DCHECK_EQ(4u, instruction->GetVectorLength());
479 __ addps(dst, src);
480 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100481 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800482 DCHECK_EQ(2u, instruction->GetVectorLength());
483 __ addpd(dst, src);
484 break;
485 default:
486 LOG(FATAL) << "Unsupported SIMD type";
487 UNREACHABLE();
488 }
489}
490
Aart Bikf3e61ee2017-04-12 17:09:20 -0700491void LocationsBuilderX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100492 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700493}
494
495void InstructionCodeGeneratorX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
496 LocationSummary* locations = instruction->GetLocations();
497 DCHECK(locations->InAt(0).Equals(locations->Out()));
498 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
499 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
500
501 DCHECK(instruction->IsRounded());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700502
503 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100504 case DataType::Type::kUint8:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700505 DCHECK_EQ(16u, instruction->GetVectorLength());
506 __ pavgb(dst, src);
507 return;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100508 case DataType::Type::kUint16:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700509 DCHECK_EQ(8u, instruction->GetVectorLength());
510 __ pavgw(dst, src);
511 return;
512 default:
513 LOG(FATAL) << "Unsupported SIMD type";
514 UNREACHABLE();
515 }
516}
517
Aart Bikf8f5a162017-02-06 15:35:29 -0800518void LocationsBuilderX86::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100519 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800520}
521
522void InstructionCodeGeneratorX86::VisitVecSub(HVecSub* instruction) {
523 LocationSummary* locations = instruction->GetLocations();
524 DCHECK(locations->InAt(0).Equals(locations->Out()));
525 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
526 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
527 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100528 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100529 case DataType::Type::kInt8:
Aart Bikf8f5a162017-02-06 15:35:29 -0800530 DCHECK_EQ(16u, instruction->GetVectorLength());
531 __ psubb(dst, src);
532 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100533 case DataType::Type::kUint16:
534 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800535 DCHECK_EQ(8u, instruction->GetVectorLength());
536 __ psubw(dst, src);
537 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100538 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800539 DCHECK_EQ(4u, instruction->GetVectorLength());
540 __ psubd(dst, src);
541 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100542 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800543 DCHECK_EQ(2u, instruction->GetVectorLength());
544 __ psubq(dst, src);
545 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100546 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800547 DCHECK_EQ(4u, instruction->GetVectorLength());
548 __ subps(dst, src);
549 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100550 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800551 DCHECK_EQ(2u, instruction->GetVectorLength());
552 __ subpd(dst, src);
553 break;
554 default:
555 LOG(FATAL) << "Unsupported SIMD type";
556 UNREACHABLE();
557 }
558}
559
560void LocationsBuilderX86::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100561 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800562}
563
564void InstructionCodeGeneratorX86::VisitVecMul(HVecMul* instruction) {
565 LocationSummary* locations = instruction->GetLocations();
566 DCHECK(locations->InAt(0).Equals(locations->Out()));
567 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
568 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
569 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100570 case DataType::Type::kUint16:
571 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800572 DCHECK_EQ(8u, instruction->GetVectorLength());
573 __ pmullw(dst, src);
574 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100575 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800576 DCHECK_EQ(4u, instruction->GetVectorLength());
577 __ pmulld(dst, src);
578 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100579 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800580 DCHECK_EQ(4u, instruction->GetVectorLength());
581 __ mulps(dst, src);
582 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100583 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800584 DCHECK_EQ(2u, instruction->GetVectorLength());
585 __ mulpd(dst, src);
586 break;
587 default:
588 LOG(FATAL) << "Unsupported SIMD type";
589 UNREACHABLE();
590 }
591}
592
593void LocationsBuilderX86::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100594 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800595}
596
597void InstructionCodeGeneratorX86::VisitVecDiv(HVecDiv* instruction) {
598 LocationSummary* locations = instruction->GetLocations();
599 DCHECK(locations->InAt(0).Equals(locations->Out()));
600 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
601 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
602 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100603 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800604 DCHECK_EQ(4u, instruction->GetVectorLength());
605 __ divps(dst, src);
606 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100607 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800608 DCHECK_EQ(2u, instruction->GetVectorLength());
609 __ divpd(dst, src);
610 break;
611 default:
612 LOG(FATAL) << "Unsupported SIMD type";
613 UNREACHABLE();
614 }
615}
616
Aart Bikf3e61ee2017-04-12 17:09:20 -0700617void LocationsBuilderX86::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100618 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700619}
620
621void InstructionCodeGeneratorX86::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700622 LocationSummary* locations = instruction->GetLocations();
623 DCHECK(locations->InAt(0).Equals(locations->Out()));
624 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
625 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
626 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100627 case DataType::Type::kUint8:
628 DCHECK_EQ(16u, instruction->GetVectorLength());
629 __ pminub(dst, src);
630 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100631 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700632 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100633 __ pminsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700634 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100635 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100636 DCHECK_EQ(8u, instruction->GetVectorLength());
637 __ pminuw(dst, src);
638 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100639 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700640 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100641 __ pminsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700642 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800643 case DataType::Type::kUint32:
644 DCHECK_EQ(4u, instruction->GetVectorLength());
645 __ pminud(dst, src);
646 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100647 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700648 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800649 __ pminsd(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700650 break;
651 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100652 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700653 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700654 __ minps(dst, src);
655 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100656 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700657 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700658 __ minpd(dst, src);
659 break;
660 default:
661 LOG(FATAL) << "Unsupported SIMD type";
662 UNREACHABLE();
663 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700664}
665
666void LocationsBuilderX86::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100667 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700668}
669
670void InstructionCodeGeneratorX86::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700671 LocationSummary* locations = instruction->GetLocations();
672 DCHECK(locations->InAt(0).Equals(locations->Out()));
673 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
674 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
675 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100676 case DataType::Type::kUint8:
677 DCHECK_EQ(16u, instruction->GetVectorLength());
678 __ pmaxub(dst, src);
679 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100680 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700681 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100682 __ pmaxsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700683 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100684 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100685 DCHECK_EQ(8u, instruction->GetVectorLength());
686 __ pmaxuw(dst, src);
687 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100688 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700689 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100690 __ pmaxsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700691 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800692 case DataType::Type::kUint32:
693 DCHECK_EQ(4u, instruction->GetVectorLength());
694 __ pmaxud(dst, src);
695 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100696 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700697 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800698 __ pmaxsd(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700699 break;
700 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100701 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700702 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700703 __ maxps(dst, src);
704 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100705 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700706 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700707 __ maxpd(dst, src);
708 break;
709 default:
710 LOG(FATAL) << "Unsupported SIMD type";
711 UNREACHABLE();
712 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700713}
714
Aart Bikf8f5a162017-02-06 15:35:29 -0800715void LocationsBuilderX86::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100716 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800717}
718
719void InstructionCodeGeneratorX86::VisitVecAnd(HVecAnd* instruction) {
720 LocationSummary* locations = instruction->GetLocations();
721 DCHECK(locations->InAt(0).Equals(locations->Out()));
722 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
723 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
724 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100725 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100726 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100727 case DataType::Type::kInt8:
728 case DataType::Type::kUint16:
729 case DataType::Type::kInt16:
730 case DataType::Type::kInt32:
731 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800732 DCHECK_LE(2u, instruction->GetVectorLength());
733 DCHECK_LE(instruction->GetVectorLength(), 16u);
734 __ pand(dst, src);
735 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100736 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800737 DCHECK_EQ(4u, instruction->GetVectorLength());
738 __ andps(dst, src);
739 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100740 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800741 DCHECK_EQ(2u, instruction->GetVectorLength());
742 __ andpd(dst, src);
743 break;
744 default:
745 LOG(FATAL) << "Unsupported SIMD type";
746 UNREACHABLE();
747 }
748}
749
750void LocationsBuilderX86::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100751 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800752}
753
754void InstructionCodeGeneratorX86::VisitVecAndNot(HVecAndNot* instruction) {
755 LocationSummary* locations = instruction->GetLocations();
756 DCHECK(locations->InAt(0).Equals(locations->Out()));
757 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
758 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
759 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100760 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100761 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100762 case DataType::Type::kInt8:
763 case DataType::Type::kUint16:
764 case DataType::Type::kInt16:
765 case DataType::Type::kInt32:
766 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800767 DCHECK_LE(2u, instruction->GetVectorLength());
768 DCHECK_LE(instruction->GetVectorLength(), 16u);
769 __ pandn(dst, src);
770 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100771 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800772 DCHECK_EQ(4u, instruction->GetVectorLength());
773 __ andnps(dst, src);
774 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100775 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800776 DCHECK_EQ(2u, instruction->GetVectorLength());
777 __ andnpd(dst, src);
778 break;
779 default:
780 LOG(FATAL) << "Unsupported SIMD type";
781 UNREACHABLE();
782 }
783}
784
785void LocationsBuilderX86::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100786 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800787}
788
789void InstructionCodeGeneratorX86::VisitVecOr(HVecOr* instruction) {
790 LocationSummary* locations = instruction->GetLocations();
791 DCHECK(locations->InAt(0).Equals(locations->Out()));
792 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
793 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
794 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100795 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100796 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100797 case DataType::Type::kInt8:
798 case DataType::Type::kUint16:
799 case DataType::Type::kInt16:
800 case DataType::Type::kInt32:
801 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800802 DCHECK_LE(2u, instruction->GetVectorLength());
803 DCHECK_LE(instruction->GetVectorLength(), 16u);
804 __ por(dst, src);
805 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100806 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800807 DCHECK_EQ(4u, instruction->GetVectorLength());
808 __ orps(dst, src);
809 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100810 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800811 DCHECK_EQ(2u, instruction->GetVectorLength());
812 __ orpd(dst, src);
813 break;
814 default:
815 LOG(FATAL) << "Unsupported SIMD type";
816 UNREACHABLE();
817 }
818}
819
820void LocationsBuilderX86::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100821 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800822}
823
824void InstructionCodeGeneratorX86::VisitVecXor(HVecXor* instruction) {
825 LocationSummary* locations = instruction->GetLocations();
826 DCHECK(locations->InAt(0).Equals(locations->Out()));
827 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
828 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
829 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100830 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100831 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100832 case DataType::Type::kInt8:
833 case DataType::Type::kUint16:
834 case DataType::Type::kInt16:
835 case DataType::Type::kInt32:
836 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800837 DCHECK_LE(2u, instruction->GetVectorLength());
838 DCHECK_LE(instruction->GetVectorLength(), 16u);
839 __ pxor(dst, src);
840 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100841 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800842 DCHECK_EQ(4u, instruction->GetVectorLength());
843 __ xorps(dst, src);
844 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100845 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800846 DCHECK_EQ(2u, instruction->GetVectorLength());
847 __ xorpd(dst, src);
848 break;
849 default:
850 LOG(FATAL) << "Unsupported SIMD type";
851 UNREACHABLE();
852 }
853}
854
855// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100856static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
857 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800858 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100859 case DataType::Type::kUint16:
860 case DataType::Type::kInt16:
861 case DataType::Type::kInt32:
862 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800863 locations->SetInAt(0, Location::RequiresFpuRegister());
864 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
865 locations->SetOut(Location::SameAsFirstInput());
866 break;
867 default:
868 LOG(FATAL) << "Unsupported SIMD type";
869 UNREACHABLE();
870 }
871}
872
873void LocationsBuilderX86::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100874 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800875}
876
877void InstructionCodeGeneratorX86::VisitVecShl(HVecShl* instruction) {
878 LocationSummary* locations = instruction->GetLocations();
879 DCHECK(locations->InAt(0).Equals(locations->Out()));
880 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
881 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
882 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100883 case DataType::Type::kUint16:
884 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800885 DCHECK_EQ(8u, instruction->GetVectorLength());
886 __ psllw(dst, Immediate(static_cast<uint8_t>(value)));
887 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100888 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800889 DCHECK_EQ(4u, instruction->GetVectorLength());
890 __ pslld(dst, Immediate(static_cast<uint8_t>(value)));
891 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100892 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800893 DCHECK_EQ(2u, instruction->GetVectorLength());
894 __ psllq(dst, Immediate(static_cast<uint8_t>(value)));
895 break;
896 default:
897 LOG(FATAL) << "Unsupported SIMD type";
898 UNREACHABLE();
899 }
900}
901
902void LocationsBuilderX86::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100903 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800904}
905
906void InstructionCodeGeneratorX86::VisitVecShr(HVecShr* instruction) {
907 LocationSummary* locations = instruction->GetLocations();
908 DCHECK(locations->InAt(0).Equals(locations->Out()));
909 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
910 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
911 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100912 case DataType::Type::kUint16:
913 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800914 DCHECK_EQ(8u, instruction->GetVectorLength());
915 __ psraw(dst, Immediate(static_cast<uint8_t>(value)));
916 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100917 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800918 DCHECK_EQ(4u, instruction->GetVectorLength());
919 __ psrad(dst, Immediate(static_cast<uint8_t>(value)));
920 break;
921 default:
922 LOG(FATAL) << "Unsupported SIMD type";
923 UNREACHABLE();
924 }
925}
926
927void LocationsBuilderX86::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100928 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800929}
930
931void InstructionCodeGeneratorX86::VisitVecUShr(HVecUShr* instruction) {
932 LocationSummary* locations = instruction->GetLocations();
933 DCHECK(locations->InAt(0).Equals(locations->Out()));
934 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
935 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
936 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100937 case DataType::Type::kUint16:
938 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800939 DCHECK_EQ(8u, instruction->GetVectorLength());
940 __ psrlw(dst, Immediate(static_cast<uint8_t>(value)));
941 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100942 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800943 DCHECK_EQ(4u, instruction->GetVectorLength());
944 __ psrld(dst, Immediate(static_cast<uint8_t>(value)));
945 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100946 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800947 DCHECK_EQ(2u, instruction->GetVectorLength());
948 __ psrlq(dst, Immediate(static_cast<uint8_t>(value)));
949 break;
950 default:
951 LOG(FATAL) << "Unsupported SIMD type";
952 UNREACHABLE();
953 }
954}
955
Aart Bik0148de42017-09-05 09:25:01 -0700956void LocationsBuilderX86::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::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700966 // Long needs extra temporary to load from register pairs.
967 if (!is_zero) {
968 locations->AddTemp(Location::RequiresFpuRegister());
969 }
970 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100971 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100972 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100973 case DataType::Type::kInt8:
974 case DataType::Type::kUint16:
975 case DataType::Type::kInt16:
976 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700977 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
978 : Location::RequiresRegister());
979 locations->SetOut(Location::RequiresFpuRegister());
980 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100981 case DataType::Type::kFloat32:
982 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700983 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
984 : Location::RequiresFpuRegister());
985 locations->SetOut(Location::RequiresFpuRegister());
986 break;
987 default:
988 LOG(FATAL) << "Unsupported SIMD type";
989 UNREACHABLE();
990 }
991}
992
993void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction) {
994 LocationSummary* locations = instruction->GetLocations();
995 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
996
997 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
998
999 // Zero out all other elements first.
1000 __ xorps(dst, dst);
1001
1002 // Shorthand for any type of zero.
1003 if (IsZeroBitPattern(instruction->InputAt(0))) {
1004 return;
1005 }
1006
1007 // Set required elements.
1008 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001009 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001010 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001011 case DataType::Type::kInt8:
1012 case DataType::Type::kUint16:
1013 case DataType::Type::kInt16: // TODO: up to here, and?
Aart Bik0148de42017-09-05 09:25:01 -07001014 LOG(FATAL) << "Unsupported SIMD type";
1015 UNREACHABLE();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001016 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001017 DCHECK_EQ(4u, instruction->GetVectorLength());
1018 __ movd(dst, locations->InAt(0).AsRegister<Register>());
1019 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001020 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -07001021 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -08001022 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Aart Bik0148de42017-09-05 09:25:01 -07001023 __ xorps(tmp, tmp);
1024 __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
1025 __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
1026 __ punpckldq(dst, tmp);
1027 break;
1028 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001029 case DataType::Type::kFloat32:
Aart Bik0148de42017-09-05 09:25:01 -07001030 DCHECK_EQ(4u, instruction->GetVectorLength());
1031 __ movss(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1032 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001033 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -07001034 DCHECK_EQ(2u, instruction->GetVectorLength());
1035 __ movsd(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1036 break;
1037 default:
1038 LOG(FATAL) << "Unsupported SIMD type";
1039 UNREACHABLE();
1040 }
1041}
1042
Aart Bikdbbac8f2017-09-01 13:06:08 -07001043// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001044static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1045 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001046 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001047 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001048 case DataType::Type::kInt8:
1049 case DataType::Type::kUint16:
1050 case DataType::Type::kInt16:
1051 case DataType::Type::kInt32:
1052 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001053 locations->SetInAt(0, Location::RequiresFpuRegister());
1054 locations->SetInAt(1, Location::RequiresFpuRegister());
1055 locations->SetInAt(2, Location::RequiresFpuRegister());
1056 locations->SetOut(Location::SameAsFirstInput());
1057 break;
1058 default:
1059 LOG(FATAL) << "Unsupported SIMD type";
1060 UNREACHABLE();
1061 }
Artem Serovf34dd202017-04-10 17:41:46 +01001062}
1063
Aart Bikdbbac8f2017-09-01 13:06:08 -07001064void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001065 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001066}
1067
1068void InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1069 // TODO: pmaddwd?
1070 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1071}
1072
1073void LocationsBuilderX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001074 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001075}
1076
1077void InstructionCodeGeneratorX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
1078 // TODO: psadbw for unsigned?
1079 LOG(FATAL) << "No SIMD for " << instruction->GetId();
Artem Serovf34dd202017-04-10 17:41:46 +01001080}
1081
Aart Bikf8f5a162017-02-06 15:35:29 -08001082// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001083static void CreateVecMemLocations(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001084 HVecMemoryOperation* instruction,
1085 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001086 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001087 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001088 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001089 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001090 case DataType::Type::kInt8:
1091 case DataType::Type::kUint16:
1092 case DataType::Type::kInt16:
1093 case DataType::Type::kInt32:
1094 case DataType::Type::kInt64:
1095 case DataType::Type::kFloat32:
1096 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001097 locations->SetInAt(0, Location::RequiresRegister());
1098 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1099 if (is_load) {
1100 locations->SetOut(Location::RequiresFpuRegister());
1101 } else {
1102 locations->SetInAt(2, Location::RequiresFpuRegister());
1103 }
1104 break;
1105 default:
1106 LOG(FATAL) << "Unsupported SIMD type";
1107 UNREACHABLE();
1108 }
1109}
1110
Aart Bik472821b2017-04-27 17:23:51 -07001111// Helper to construct address for vector memory operations.
1112static Address VecAddress(LocationSummary* locations, size_t size, bool is_string_char_at) {
Aart Bikf8f5a162017-02-06 15:35:29 -08001113 Location base = locations->InAt(0);
1114 Location index = locations->InAt(1);
Aart Bikf8f5a162017-02-06 15:35:29 -08001115 ScaleFactor scale = TIMES_1;
1116 switch (size) {
1117 case 2: scale = TIMES_2; break;
1118 case 4: scale = TIMES_4; break;
1119 case 8: scale = TIMES_8; break;
1120 default: break;
1121 }
Aart Bik0148de42017-09-05 09:25:01 -07001122 // Incorporate the string or array offset in the address computation.
Aart Bik472821b2017-04-27 17:23:51 -07001123 uint32_t offset = is_string_char_at
1124 ? mirror::String::ValueOffset().Uint32Value()
1125 : mirror::Array::DataOffset(size).Uint32Value();
Aart Bikf8f5a162017-02-06 15:35:29 -08001126 return CodeGeneratorX86::ArrayAddress(base.AsRegister<Register>(), index, scale, offset);
1127}
1128
1129void LocationsBuilderX86::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001130 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bik472821b2017-04-27 17:23:51 -07001131 // String load requires a temporary for the compressed load.
1132 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1133 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
1134 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001135}
1136
1137void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001138 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001139 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001140 Address address = VecAddress(locations, size, instruction->IsStringCharAt());
1141 XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001142 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1143 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001144 case DataType::Type::kUint16:
Aart Bik472821b2017-04-27 17:23:51 -07001145 DCHECK_EQ(8u, instruction->GetVectorLength());
1146 // Special handling of compressed/uncompressed string load.
1147 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1148 NearLabel done, not_compressed;
1149 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1150 // Test compression bit.
1151 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
1152 "Expecting 0=compressed, 1=uncompressed");
1153 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
1154 __ testb(Address(locations->InAt(0).AsRegister<Register>(), count_offset), Immediate(1));
1155 __ j(kNotZero, &not_compressed);
1156 // Zero extend 8 compressed bytes into 8 chars.
Aart Bik0148de42017-09-05 09:25:01 -07001157 __ movsd(reg, VecAddress(locations, 1, instruction->IsStringCharAt()));
Aart Bik472821b2017-04-27 17:23:51 -07001158 __ pxor(tmp, tmp);
1159 __ punpcklbw(reg, tmp);
1160 __ jmp(&done);
1161 // Load 4 direct uncompressed chars.
1162 __ Bind(&not_compressed);
1163 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1164 __ Bind(&done);
1165 return;
1166 }
1167 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001168 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001169 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001170 case DataType::Type::kInt8:
1171 case DataType::Type::kInt16:
1172 case DataType::Type::kInt32:
1173 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001174 DCHECK_LE(2u, instruction->GetVectorLength());
1175 DCHECK_LE(instruction->GetVectorLength(), 16u);
1176 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1177 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001178 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001179 DCHECK_EQ(4u, instruction->GetVectorLength());
1180 is_aligned16 ? __ movaps(reg, address) : __ movups(reg, address);
1181 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001182 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001183 DCHECK_EQ(2u, instruction->GetVectorLength());
1184 is_aligned16 ? __ movapd(reg, address) : __ movupd(reg, address);
1185 break;
1186 default:
1187 LOG(FATAL) << "Unsupported SIMD type";
1188 UNREACHABLE();
1189 }
1190}
1191
1192void LocationsBuilderX86::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001193 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001194}
1195
1196void InstructionCodeGeneratorX86::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001197 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001198 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001199 Address address = VecAddress(locations, size, /*is_string_char_at*/ false);
1200 XmmRegister reg = locations->InAt(2).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001201 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1202 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001203 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001204 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001205 case DataType::Type::kInt8:
1206 case DataType::Type::kUint16:
1207 case DataType::Type::kInt16:
1208 case DataType::Type::kInt32:
1209 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001210 DCHECK_LE(2u, instruction->GetVectorLength());
1211 DCHECK_LE(instruction->GetVectorLength(), 16u);
1212 is_aligned16 ? __ movdqa(address, reg) : __ movdqu(address, reg);
1213 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001214 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001215 DCHECK_EQ(4u, instruction->GetVectorLength());
1216 is_aligned16 ? __ movaps(address, reg) : __ movups(address, reg);
1217 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001218 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001219 DCHECK_EQ(2u, instruction->GetVectorLength());
1220 is_aligned16 ? __ movapd(address, reg) : __ movupd(address, reg);
1221 break;
1222 default:
1223 LOG(FATAL) << "Unsupported SIMD type";
1224 UNREACHABLE();
1225 }
1226}
1227
1228#undef __
1229
1230} // namespace x86
1231} // namespace art