blob: 29a135459778765128232c3b46644178c1513ed6 [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:
Aart Bik29aa0822018-03-08 11:28:00 -080057 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -070058 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800114 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700115 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800141 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik9879d0e2017-08-15 10:51:25 -0700142 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 Bik29aa0822018-03-08 11:28:00 -0800155 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700156 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800177 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik9879d0e2017-08-15 10:51:25 -0700178 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800199 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800200 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 ||
Vladimir Marko4e3734a2018-11-14 15:45:28 +0000208 instruction->GetReductionKind() == HVecReduce::kMin ||
209 instruction->GetReductionKind() == HVecReduce::kMax) {
Aart Bik0148de42017-09-05 09:25:01 -0700210 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());
Vladimir Marko4e3734a2018-11-14 15:45:28 +0000221 switch (instruction->GetReductionKind()) {
Aart Bik0148de42017-09-05 09:25:01 -0700222 case HVecReduce::kSum:
223 __ movaps(dst, src);
224 __ phaddd(dst, dst);
225 __ phaddd(dst, dst);
226 break;
Vladimir Marko8786fd92018-11-14 15:47:03 +0000227 case HVecReduce::kMin:
228 case HVecReduce::kMax:
229 // Historical note: We've had a broken implementation here. b/117863065
230 // Do not draw on the old code if we ever want to bring MIN/MAX reduction back.
231 LOG(FATAL) << "Unsupported reduction type.";
Aart Bik0148de42017-09-05 09:25:01 -0700232 }
233 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100234 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -0700235 DCHECK_EQ(2u, instruction->GetVectorLength());
236 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Vladimir Marko4e3734a2018-11-14 15:45:28 +0000237 switch (instruction->GetReductionKind()) {
Aart Bik0148de42017-09-05 09:25:01 -0700238 case HVecReduce::kSum:
239 __ movaps(tmp, src);
240 __ movaps(dst, src);
241 __ punpckhqdq(tmp, tmp);
242 __ paddq(dst, tmp);
243 break;
244 case HVecReduce::kMin:
245 case HVecReduce::kMax:
Aart Bik29aa0822018-03-08 11:28:00 -0800246 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700247 }
248 break;
249 }
250 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800251 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700252 UNREACHABLE();
253 }
254}
255
Aart Bikf8f5a162017-02-06 15:35:29 -0800256void LocationsBuilderX86::VisitVecCnv(HVecCnv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100257 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800258}
259
260void InstructionCodeGeneratorX86::VisitVecCnv(HVecCnv* instruction) {
261 LocationSummary* locations = instruction->GetLocations();
262 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
263 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100264 DataType::Type from = instruction->GetInputType();
265 DataType::Type to = instruction->GetResultType();
266 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800267 DCHECK_EQ(4u, instruction->GetVectorLength());
268 __ cvtdq2ps(dst, src);
269 } else {
Aart Bik29aa0822018-03-08 11:28:00 -0800270 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800271 }
272}
273
274void LocationsBuilderX86::VisitVecNeg(HVecNeg* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100275 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800276}
277
278void InstructionCodeGeneratorX86::VisitVecNeg(HVecNeg* instruction) {
279 LocationSummary* locations = instruction->GetLocations();
280 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
281 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
282 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100283 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100284 case DataType::Type::kInt8:
Aart Bikf8f5a162017-02-06 15:35:29 -0800285 DCHECK_EQ(16u, instruction->GetVectorLength());
286 __ pxor(dst, dst);
287 __ psubb(dst, src);
288 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100289 case DataType::Type::kUint16:
290 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800291 DCHECK_EQ(8u, instruction->GetVectorLength());
292 __ pxor(dst, dst);
293 __ psubw(dst, src);
294 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100295 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800296 DCHECK_EQ(4u, instruction->GetVectorLength());
297 __ pxor(dst, dst);
298 __ psubd(dst, src);
299 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100300 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800301 DCHECK_EQ(2u, instruction->GetVectorLength());
302 __ pxor(dst, dst);
303 __ psubq(dst, src);
304 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100305 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800306 DCHECK_EQ(4u, instruction->GetVectorLength());
307 __ xorps(dst, dst);
308 __ subps(dst, src);
309 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100310 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800311 DCHECK_EQ(2u, instruction->GetVectorLength());
312 __ xorpd(dst, dst);
313 __ subpd(dst, src);
314 break;
315 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800316 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800317 UNREACHABLE();
318 }
319}
320
Aart Bik6daebeb2017-04-03 14:35:41 -0700321void LocationsBuilderX86::VisitVecAbs(HVecAbs* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100322 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik472821b2017-04-27 17:23:51 -0700323 // Integral-abs requires a temporary for the comparison.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100324 if (instruction->GetPackedType() == DataType::Type::kInt32) {
Aart Bik6daebeb2017-04-03 14:35:41 -0700325 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
326 }
327}
328
329void InstructionCodeGeneratorX86::VisitVecAbs(HVecAbs* instruction) {
330 LocationSummary* locations = instruction->GetLocations();
331 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
332 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
333 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100334 case DataType::Type::kInt32: {
Aart Bik6daebeb2017-04-03 14:35:41 -0700335 DCHECK_EQ(4u, instruction->GetVectorLength());
336 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
337 __ movaps(dst, src);
338 __ pxor(tmp, tmp);
339 __ pcmpgtd(tmp, dst);
340 __ pxor(dst, tmp);
341 __ psubd(dst, tmp);
342 break;
343 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100344 case DataType::Type::kFloat32:
Aart Bik6daebeb2017-04-03 14:35:41 -0700345 DCHECK_EQ(4u, instruction->GetVectorLength());
346 __ pcmpeqb(dst, dst); // all ones
347 __ psrld(dst, Immediate(1));
348 __ andps(dst, src);
349 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100350 case DataType::Type::kFloat64:
Aart Bik6daebeb2017-04-03 14:35:41 -0700351 DCHECK_EQ(2u, instruction->GetVectorLength());
352 __ pcmpeqb(dst, dst); // all ones
353 __ psrlq(dst, Immediate(1));
354 __ andpd(dst, src);
355 break;
356 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800357 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik6daebeb2017-04-03 14:35:41 -0700358 UNREACHABLE();
359 }
360}
361
Aart Bikf8f5a162017-02-06 15:35:29 -0800362void LocationsBuilderX86::VisitVecNot(HVecNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100363 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800364 // Boolean-not requires a temporary to construct the 16 x one.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100365 if (instruction->GetPackedType() == DataType::Type::kBool) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800366 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
367 }
368}
369
370void InstructionCodeGeneratorX86::VisitVecNot(HVecNot* instruction) {
371 LocationSummary* locations = instruction->GetLocations();
372 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
373 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
374 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100375 case DataType::Type::kBool: { // special case boolean-not
Aart Bikf8f5a162017-02-06 15:35:29 -0800376 DCHECK_EQ(16u, instruction->GetVectorLength());
377 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
378 __ pxor(dst, dst);
379 __ pcmpeqb(tmp, tmp); // all ones
380 __ psubb(dst, tmp); // 16 x one
381 __ pxor(dst, src);
382 break;
383 }
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100384 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100385 case DataType::Type::kInt8:
386 case DataType::Type::kUint16:
387 case DataType::Type::kInt16:
388 case DataType::Type::kInt32:
389 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800390 DCHECK_LE(2u, instruction->GetVectorLength());
391 DCHECK_LE(instruction->GetVectorLength(), 16u);
392 __ pcmpeqb(dst, dst); // all ones
393 __ pxor(dst, src);
394 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100395 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800396 DCHECK_EQ(4u, instruction->GetVectorLength());
397 __ pcmpeqb(dst, dst); // all ones
398 __ xorps(dst, src);
399 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100400 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800401 DCHECK_EQ(2u, instruction->GetVectorLength());
402 __ pcmpeqb(dst, dst); // all ones
403 __ xorpd(dst, src);
404 break;
405 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800406 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800407 UNREACHABLE();
408 }
409}
410
411// Helper to set up locations for vector binary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100412static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
413 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800414 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100415 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100416 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100417 case DataType::Type::kInt8:
418 case DataType::Type::kUint16:
419 case DataType::Type::kInt16:
420 case DataType::Type::kInt32:
421 case DataType::Type::kInt64:
422 case DataType::Type::kFloat32:
423 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800424 locations->SetInAt(0, Location::RequiresFpuRegister());
425 locations->SetInAt(1, Location::RequiresFpuRegister());
426 locations->SetOut(Location::SameAsFirstInput());
427 break;
428 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800429 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800430 UNREACHABLE();
431 }
432}
433
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530434static void CreateVecTerOpLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
435 LocationSummary* locations = new (allocator) LocationSummary(instruction);
436 switch (instruction->GetPackedType()) {
437 case DataType::Type::kBool:
438 case DataType::Type::kUint8:
439 case DataType::Type::kInt8:
440 case DataType::Type::kUint16:
441 case DataType::Type::kInt16:
442 case DataType::Type::kInt32:
443 case DataType::Type::kInt64:
444 case DataType::Type::kFloat32:
445 case DataType::Type::kFloat64:
446 locations->SetInAt(0, Location::RequiresFpuRegister());
447 locations->SetInAt(1, Location::RequiresFpuRegister());
448 locations->SetOut(Location::RequiresFpuRegister());
449 break;
450 default:
451 LOG(FATAL) << "Unsupported SIMD type";
452 UNREACHABLE();
453 }
454}
455
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530456void LocationsBuilderX86::VisitVecAdd(HVecAdd* instruction) {
457 if (CpuHasAvxFeatureFlag()) {
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530458 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530459 } else {
460 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
461 }
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530462}
463
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530464void InstructionCodeGeneratorX86::VisitVecAdd(HVecAdd* instruction) {
465 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530466 LocationSummary* locations = instruction->GetLocations();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530467 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
468 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530469 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530470 DCHECK(cpu_has_avx || other_src == dst);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530471 switch (instruction->GetPackedType()) {
472 case DataType::Type::kUint8:
473 case DataType::Type::kInt8:
474 DCHECK_EQ(16u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530475 cpu_has_avx ? __ vpaddb(dst, other_src, src) : __ paddb(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530476 break;
477 case DataType::Type::kUint16:
478 case DataType::Type::kInt16:
479 DCHECK_EQ(8u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530480 cpu_has_avx ? __ vpaddw(dst, other_src, src) : __ paddw(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530481 break;
482 case DataType::Type::kInt32:
483 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530484 cpu_has_avx ? __ vpaddd(dst, other_src, src) : __ paddd(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530485 break;
486 case DataType::Type::kInt64:
487 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530488 cpu_has_avx ? __ vpaddq(dst, other_src, src) : __ paddq(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530489 break;
490 case DataType::Type::kFloat32:
491 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530492 cpu_has_avx ? __ vaddps(dst, other_src, src) : __ addps(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530493 break;
494 case DataType::Type::kFloat64:
495 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530496 cpu_has_avx ? __ vaddpd(dst, other_src, src) : __ addpd(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530497 break;
498 default:
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530499 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530500 UNREACHABLE();
501 }
502}
503
Aart Bik29aa0822018-03-08 11:28:00 -0800504void LocationsBuilderX86::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
505 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
506}
507
508void InstructionCodeGeneratorX86::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
509 LocationSummary* locations = instruction->GetLocations();
510 DCHECK(locations->InAt(0).Equals(locations->Out()));
511 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
512 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
513 switch (instruction->GetPackedType()) {
514 case DataType::Type::kUint8:
515 DCHECK_EQ(16u, instruction->GetVectorLength());
516 __ paddusb(dst, src);
517 break;
518 case DataType::Type::kInt8:
519 DCHECK_EQ(16u, instruction->GetVectorLength());
520 __ paddsb(dst, src);
521 break;
522 case DataType::Type::kUint16:
523 DCHECK_EQ(8u, instruction->GetVectorLength());
524 __ paddusw(dst, src);
525 break;
526 case DataType::Type::kInt16:
527 DCHECK_EQ(8u, instruction->GetVectorLength());
528 __ paddsw(dst, src);
529 break;
530 default:
531 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800532 UNREACHABLE();
533 }
534}
535
Aart Bikf3e61ee2017-04-12 17:09:20 -0700536void LocationsBuilderX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100537 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700538}
539
540void InstructionCodeGeneratorX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
541 LocationSummary* locations = instruction->GetLocations();
542 DCHECK(locations->InAt(0).Equals(locations->Out()));
543 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
544 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
545
546 DCHECK(instruction->IsRounded());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700547
548 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100549 case DataType::Type::kUint8:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700550 DCHECK_EQ(16u, instruction->GetVectorLength());
Aart Bik29aa0822018-03-08 11:28:00 -0800551 __ pavgb(dst, src);
552 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100553 case DataType::Type::kUint16:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700554 DCHECK_EQ(8u, instruction->GetVectorLength());
555 __ pavgw(dst, src);
Aart Bik29aa0822018-03-08 11:28:00 -0800556 break;
Aart Bikf3e61ee2017-04-12 17:09:20 -0700557 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800558 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf3e61ee2017-04-12 17:09:20 -0700559 UNREACHABLE();
560 }
561}
562
Aart Bikf8f5a162017-02-06 15:35:29 -0800563void LocationsBuilderX86::VisitVecSub(HVecSub* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530564 if (CpuHasAvxFeatureFlag()) {
565 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
566 } else {
567 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik29aa0822018-03-08 11:28:00 -0800568 }
569}
570
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530571void InstructionCodeGeneratorX86::VisitVecSub(HVecSub* instruction) {
572 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530573 LocationSummary* locations = instruction->GetLocations();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530574 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
575 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530576 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530577 DCHECK(cpu_has_avx || other_src == dst);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530578 switch (instruction->GetPackedType()) {
579 case DataType::Type::kUint8:
580 case DataType::Type::kInt8:
581 DCHECK_EQ(16u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530582 cpu_has_avx ? __ vpsubb(dst, other_src, src) : __ psubb(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530583 break;
584 case DataType::Type::kUint16:
585 case DataType::Type::kInt16:
586 DCHECK_EQ(8u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530587 cpu_has_avx ? __ vpsubw(dst, other_src, src) : __ psubw(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530588 break;
589 case DataType::Type::kInt32:
590 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530591 cpu_has_avx ? __ vpsubd(dst, other_src, src) : __ psubd(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530592 break;
593 case DataType::Type::kInt64:
594 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530595 cpu_has_avx ? __ vpsubq(dst, other_src, src) : __ psubq(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530596 break;
597 case DataType::Type::kFloat32:
598 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530599 cpu_has_avx ? __ vsubps(dst, other_src, src) : __ subps(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530600 break;
601 case DataType::Type::kFloat64:
602 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530603 cpu_has_avx ? __ vsubpd(dst, other_src, src) : __ subpd(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530604 break;
605 default:
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530606 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530607 UNREACHABLE();
608 }
609}
610
Aart Bik29aa0822018-03-08 11:28:00 -0800611void LocationsBuilderX86::VisitVecSaturationSub(HVecSaturationSub* instruction) {
612 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
613}
614
615void InstructionCodeGeneratorX86::VisitVecSaturationSub(HVecSaturationSub* instruction) {
616 LocationSummary* locations = instruction->GetLocations();
617 DCHECK(locations->InAt(0).Equals(locations->Out()));
618 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
619 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
620 switch (instruction->GetPackedType()) {
621 case DataType::Type::kUint8:
622 DCHECK_EQ(16u, instruction->GetVectorLength());
623 __ psubusb(dst, src);
624 break;
625 case DataType::Type::kInt8:
626 DCHECK_EQ(16u, instruction->GetVectorLength());
627 __ psubsb(dst, src);
628 break;
629 case DataType::Type::kUint16:
630 DCHECK_EQ(8u, instruction->GetVectorLength());
631 __ psubusw(dst, src);
632 break;
633 case DataType::Type::kInt16:
634 DCHECK_EQ(8u, instruction->GetVectorLength());
635 __ psubsw(dst, src);
636 break;
637 default:
638 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800639 UNREACHABLE();
640 }
641}
642
643void LocationsBuilderX86::VisitVecMul(HVecMul* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530644 if (CpuHasAvxFeatureFlag()) {
645 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
646 } else {
647 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
648 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800649}
650
651void InstructionCodeGeneratorX86::VisitVecMul(HVecMul* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530652 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Aart Bikf8f5a162017-02-06 15:35:29 -0800653 LocationSummary* locations = instruction->GetLocations();
Aart Bikf8f5a162017-02-06 15:35:29 -0800654 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530655 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -0800656 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530657 DCHECK(cpu_has_avx || other_src == dst);
Aart Bikf8f5a162017-02-06 15:35:29 -0800658 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100659 case DataType::Type::kUint16:
660 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800661 DCHECK_EQ(8u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530662 cpu_has_avx ? __ vpmullw(dst, other_src, src) : __ pmullw(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800663 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100664 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800665 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530666 cpu_has_avx ? __ vpmulld(dst, other_src, src) : __ pmulld(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800667 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100668 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800669 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530670 cpu_has_avx ? __ vmulps(dst, other_src, src) : __ mulps(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800671 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100672 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800673 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530674 cpu_has_avx ? __ vmulpd(dst, other_src, src) : __ mulpd(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800675 break;
676 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800677 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800678 UNREACHABLE();
679 }
680}
681
682void LocationsBuilderX86::VisitVecDiv(HVecDiv* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530683 if (CpuHasAvxFeatureFlag()) {
684 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
685 } else {
686 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
687 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800688}
689
690void InstructionCodeGeneratorX86::VisitVecDiv(HVecDiv* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530691 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Aart Bikf8f5a162017-02-06 15:35:29 -0800692 LocationSummary* locations = instruction->GetLocations();
Aart Bikf8f5a162017-02-06 15:35:29 -0800693 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530694 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -0800695 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530696 DCHECK(cpu_has_avx || other_src == dst);
Aart Bikf8f5a162017-02-06 15:35:29 -0800697 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100698 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800699 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530700 cpu_has_avx ? __ vdivps(dst, other_src, src) : __ divps(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800701 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100702 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800703 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530704 cpu_has_avx ? __ vdivpd(dst, other_src, src) : __ divpd(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800705 break;
706 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800707 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800708 UNREACHABLE();
709 }
710}
711
Aart Bikf3e61ee2017-04-12 17:09:20 -0700712void LocationsBuilderX86::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100713 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700714}
715
716void InstructionCodeGeneratorX86::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700717 LocationSummary* locations = instruction->GetLocations();
718 DCHECK(locations->InAt(0).Equals(locations->Out()));
719 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
720 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
721 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100722 case DataType::Type::kUint8:
723 DCHECK_EQ(16u, instruction->GetVectorLength());
724 __ pminub(dst, src);
725 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100726 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700727 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100728 __ pminsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700729 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100730 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100731 DCHECK_EQ(8u, instruction->GetVectorLength());
732 __ pminuw(dst, src);
733 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100734 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700735 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100736 __ pminsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700737 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800738 case DataType::Type::kUint32:
739 DCHECK_EQ(4u, instruction->GetVectorLength());
740 __ pminud(dst, src);
741 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100742 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700743 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800744 __ pminsd(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700745 break;
746 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100747 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700748 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700749 __ minps(dst, src);
750 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100751 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700752 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700753 __ minpd(dst, src);
754 break;
755 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800756 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700757 UNREACHABLE();
758 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700759}
760
761void LocationsBuilderX86::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100762 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700763}
764
765void InstructionCodeGeneratorX86::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700766 LocationSummary* locations = instruction->GetLocations();
767 DCHECK(locations->InAt(0).Equals(locations->Out()));
768 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
769 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
770 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100771 case DataType::Type::kUint8:
772 DCHECK_EQ(16u, instruction->GetVectorLength());
773 __ pmaxub(dst, src);
774 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100775 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700776 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100777 __ pmaxsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700778 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100779 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100780 DCHECK_EQ(8u, instruction->GetVectorLength());
781 __ pmaxuw(dst, src);
782 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100783 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700784 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100785 __ pmaxsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700786 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800787 case DataType::Type::kUint32:
788 DCHECK_EQ(4u, instruction->GetVectorLength());
789 __ pmaxud(dst, src);
790 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100791 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700792 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800793 __ pmaxsd(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700794 break;
795 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100796 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700797 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700798 __ maxps(dst, src);
799 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100800 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700801 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700802 __ maxpd(dst, src);
803 break;
804 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800805 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700806 UNREACHABLE();
807 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700808}
809
Aart Bikf8f5a162017-02-06 15:35:29 -0800810void LocationsBuilderX86::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100811 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800812}
813
814void InstructionCodeGeneratorX86::VisitVecAnd(HVecAnd* instruction) {
815 LocationSummary* locations = instruction->GetLocations();
816 DCHECK(locations->InAt(0).Equals(locations->Out()));
817 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
818 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
819 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100820 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100821 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100822 case DataType::Type::kInt8:
823 case DataType::Type::kUint16:
824 case DataType::Type::kInt16:
825 case DataType::Type::kInt32:
826 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800827 DCHECK_LE(2u, instruction->GetVectorLength());
828 DCHECK_LE(instruction->GetVectorLength(), 16u);
829 __ pand(dst, src);
830 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100831 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800832 DCHECK_EQ(4u, instruction->GetVectorLength());
833 __ andps(dst, src);
834 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100835 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800836 DCHECK_EQ(2u, instruction->GetVectorLength());
837 __ andpd(dst, src);
838 break;
839 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800840 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800841 UNREACHABLE();
842 }
843}
844
845void LocationsBuilderX86::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100846 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800847}
848
849void InstructionCodeGeneratorX86::VisitVecAndNot(HVecAndNot* instruction) {
850 LocationSummary* locations = instruction->GetLocations();
851 DCHECK(locations->InAt(0).Equals(locations->Out()));
852 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
853 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
854 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100855 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100856 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100857 case DataType::Type::kInt8:
858 case DataType::Type::kUint16:
859 case DataType::Type::kInt16:
860 case DataType::Type::kInt32:
861 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800862 DCHECK_LE(2u, instruction->GetVectorLength());
863 DCHECK_LE(instruction->GetVectorLength(), 16u);
864 __ pandn(dst, src);
865 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100866 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800867 DCHECK_EQ(4u, instruction->GetVectorLength());
868 __ andnps(dst, src);
869 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100870 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800871 DCHECK_EQ(2u, instruction->GetVectorLength());
872 __ andnpd(dst, src);
873 break;
874 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800875 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800876 UNREACHABLE();
877 }
878}
879
880void LocationsBuilderX86::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100881 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800882}
883
884void InstructionCodeGeneratorX86::VisitVecOr(HVecOr* instruction) {
885 LocationSummary* locations = instruction->GetLocations();
886 DCHECK(locations->InAt(0).Equals(locations->Out()));
887 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
888 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
889 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100890 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100891 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100892 case DataType::Type::kInt8:
893 case DataType::Type::kUint16:
894 case DataType::Type::kInt16:
895 case DataType::Type::kInt32:
896 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800897 DCHECK_LE(2u, instruction->GetVectorLength());
898 DCHECK_LE(instruction->GetVectorLength(), 16u);
899 __ por(dst, src);
900 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100901 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800902 DCHECK_EQ(4u, instruction->GetVectorLength());
903 __ orps(dst, src);
904 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100905 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800906 DCHECK_EQ(2u, instruction->GetVectorLength());
907 __ orpd(dst, src);
908 break;
909 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800910 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800911 UNREACHABLE();
912 }
913}
914
915void LocationsBuilderX86::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100916 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800917}
918
919void InstructionCodeGeneratorX86::VisitVecXor(HVecXor* instruction) {
920 LocationSummary* locations = instruction->GetLocations();
921 DCHECK(locations->InAt(0).Equals(locations->Out()));
922 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
923 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
924 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100925 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100926 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100927 case DataType::Type::kInt8:
928 case DataType::Type::kUint16:
929 case DataType::Type::kInt16:
930 case DataType::Type::kInt32:
931 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800932 DCHECK_LE(2u, instruction->GetVectorLength());
933 DCHECK_LE(instruction->GetVectorLength(), 16u);
934 __ pxor(dst, src);
935 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100936 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800937 DCHECK_EQ(4u, instruction->GetVectorLength());
938 __ xorps(dst, src);
939 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100940 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800941 DCHECK_EQ(2u, instruction->GetVectorLength());
942 __ xorpd(dst, src);
943 break;
944 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800945 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800946 UNREACHABLE();
947 }
948}
949
950// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100951static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
952 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800953 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100954 case DataType::Type::kUint16:
955 case DataType::Type::kInt16:
956 case DataType::Type::kInt32:
957 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800958 locations->SetInAt(0, Location::RequiresFpuRegister());
959 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
960 locations->SetOut(Location::SameAsFirstInput());
961 break;
962 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800963 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800964 UNREACHABLE();
965 }
966}
967
968void LocationsBuilderX86::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100969 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800970}
971
972void InstructionCodeGeneratorX86::VisitVecShl(HVecShl* instruction) {
973 LocationSummary* locations = instruction->GetLocations();
974 DCHECK(locations->InAt(0).Equals(locations->Out()));
975 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
976 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
977 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100978 case DataType::Type::kUint16:
979 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800980 DCHECK_EQ(8u, instruction->GetVectorLength());
981 __ psllw(dst, Immediate(static_cast<uint8_t>(value)));
982 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100983 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800984 DCHECK_EQ(4u, instruction->GetVectorLength());
985 __ pslld(dst, Immediate(static_cast<uint8_t>(value)));
986 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100987 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800988 DCHECK_EQ(2u, instruction->GetVectorLength());
989 __ psllq(dst, Immediate(static_cast<uint8_t>(value)));
990 break;
991 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800992 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800993 UNREACHABLE();
994 }
995}
996
997void LocationsBuilderX86::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100998 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800999}
1000
1001void InstructionCodeGeneratorX86::VisitVecShr(HVecShr* instruction) {
1002 LocationSummary* locations = instruction->GetLocations();
1003 DCHECK(locations->InAt(0).Equals(locations->Out()));
1004 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
1005 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
1006 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001007 case DataType::Type::kUint16:
1008 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -08001009 DCHECK_EQ(8u, instruction->GetVectorLength());
1010 __ psraw(dst, Immediate(static_cast<uint8_t>(value)));
1011 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001012 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001013 DCHECK_EQ(4u, instruction->GetVectorLength());
1014 __ psrad(dst, Immediate(static_cast<uint8_t>(value)));
1015 break;
1016 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001017 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001018 UNREACHABLE();
1019 }
1020}
1021
1022void LocationsBuilderX86::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001023 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001024}
1025
1026void InstructionCodeGeneratorX86::VisitVecUShr(HVecUShr* instruction) {
1027 LocationSummary* locations = instruction->GetLocations();
1028 DCHECK(locations->InAt(0).Equals(locations->Out()));
1029 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
1030 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
1031 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001032 case DataType::Type::kUint16:
1033 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -08001034 DCHECK_EQ(8u, instruction->GetVectorLength());
1035 __ psrlw(dst, Immediate(static_cast<uint8_t>(value)));
1036 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001037 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001038 DCHECK_EQ(4u, instruction->GetVectorLength());
1039 __ psrld(dst, Immediate(static_cast<uint8_t>(value)));
1040 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001041 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001042 DCHECK_EQ(2u, instruction->GetVectorLength());
1043 __ psrlq(dst, Immediate(static_cast<uint8_t>(value)));
1044 break;
1045 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001046 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001047 UNREACHABLE();
1048 }
1049}
1050
Aart Bik0148de42017-09-05 09:25:01 -07001051void LocationsBuilderX86::VisitVecSetScalars(HVecSetScalars* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001052 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -07001053
1054 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
1055
1056 HInstruction* input = instruction->InputAt(0);
1057 bool is_zero = IsZeroBitPattern(input);
1058
1059 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001060 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -07001061 // Long needs extra temporary to load from register pairs.
1062 if (!is_zero) {
1063 locations->AddTemp(Location::RequiresFpuRegister());
1064 }
1065 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001066 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001067 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001068 case DataType::Type::kInt8:
1069 case DataType::Type::kUint16:
1070 case DataType::Type::kInt16:
1071 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001072 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
1073 : Location::RequiresRegister());
1074 locations->SetOut(Location::RequiresFpuRegister());
1075 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001076 case DataType::Type::kFloat32:
1077 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -07001078 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
1079 : Location::RequiresFpuRegister());
1080 locations->SetOut(Location::RequiresFpuRegister());
1081 break;
1082 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001083 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001084 UNREACHABLE();
1085 }
1086}
1087
1088void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction) {
1089 LocationSummary* locations = instruction->GetLocations();
1090 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
1091
1092 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
1093
1094 // Zero out all other elements first.
1095 __ xorps(dst, dst);
1096
1097 // Shorthand for any type of zero.
1098 if (IsZeroBitPattern(instruction->InputAt(0))) {
1099 return;
1100 }
1101
1102 // Set required elements.
1103 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001104 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001105 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001106 case DataType::Type::kInt8:
1107 case DataType::Type::kUint16:
1108 case DataType::Type::kInt16: // TODO: up to here, and?
Aart Bik29aa0822018-03-08 11:28:00 -08001109 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001110 UNREACHABLE();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001111 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001112 DCHECK_EQ(4u, instruction->GetVectorLength());
1113 __ movd(dst, locations->InAt(0).AsRegister<Register>());
1114 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001115 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -07001116 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -08001117 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Aart Bik0148de42017-09-05 09:25:01 -07001118 __ xorps(tmp, tmp);
1119 __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
1120 __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
1121 __ punpckldq(dst, tmp);
1122 break;
1123 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001124 case DataType::Type::kFloat32:
Aart Bik0148de42017-09-05 09:25:01 -07001125 DCHECK_EQ(4u, instruction->GetVectorLength());
1126 __ movss(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1127 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001128 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -07001129 DCHECK_EQ(2u, instruction->GetVectorLength());
1130 __ movsd(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1131 break;
1132 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001133 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001134 UNREACHABLE();
1135 }
1136}
1137
Aart Bikdbbac8f2017-09-01 13:06:08 -07001138// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001139static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1140 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001141 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001142 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001143 case DataType::Type::kInt8:
1144 case DataType::Type::kUint16:
1145 case DataType::Type::kInt16:
1146 case DataType::Type::kInt32:
1147 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001148 locations->SetInAt(0, Location::RequiresFpuRegister());
1149 locations->SetInAt(1, Location::RequiresFpuRegister());
1150 locations->SetInAt(2, Location::RequiresFpuRegister());
1151 locations->SetOut(Location::SameAsFirstInput());
1152 break;
1153 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001154 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001155 UNREACHABLE();
1156 }
Artem Serovf34dd202017-04-10 17:41:46 +01001157}
1158
Hans Boehmf5f56c72018-07-13 00:05:27 +00001159void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1160 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001161}
1162
Hans Boehmf5f56c72018-07-13 00:05:27 +00001163void InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1164 // TODO: pmaddwd?
1165 LOG(FATAL) << "No SIMD for " << instruction->GetId();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001166}
1167
1168void LocationsBuilderX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001169 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001170}
1171
1172void InstructionCodeGeneratorX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
1173 // TODO: psadbw for unsigned?
1174 LOG(FATAL) << "No SIMD for " << instruction->GetId();
Artem Serovf34dd202017-04-10 17:41:46 +01001175}
1176
Artem Serovaaac0e32018-08-07 00:52:22 +01001177void LocationsBuilderX86::VisitVecDotProd(HVecDotProd* instruction) {
1178 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1179}
1180
1181void InstructionCodeGeneratorX86::VisitVecDotProd(HVecDotProd* instruction) {
1182 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1183}
1184
Aart Bikf8f5a162017-02-06 15:35:29 -08001185// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001186static void CreateVecMemLocations(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001187 HVecMemoryOperation* instruction,
1188 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001189 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001190 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001191 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001192 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001193 case DataType::Type::kInt8:
1194 case DataType::Type::kUint16:
1195 case DataType::Type::kInt16:
1196 case DataType::Type::kInt32:
1197 case DataType::Type::kInt64:
1198 case DataType::Type::kFloat32:
1199 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001200 locations->SetInAt(0, Location::RequiresRegister());
1201 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1202 if (is_load) {
1203 locations->SetOut(Location::RequiresFpuRegister());
1204 } else {
1205 locations->SetInAt(2, Location::RequiresFpuRegister());
1206 }
1207 break;
1208 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001209 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001210 UNREACHABLE();
1211 }
1212}
1213
Aart Bik472821b2017-04-27 17:23:51 -07001214// Helper to construct address for vector memory operations.
1215static Address VecAddress(LocationSummary* locations, size_t size, bool is_string_char_at) {
Aart Bikf8f5a162017-02-06 15:35:29 -08001216 Location base = locations->InAt(0);
1217 Location index = locations->InAt(1);
Aart Bikf8f5a162017-02-06 15:35:29 -08001218 ScaleFactor scale = TIMES_1;
1219 switch (size) {
1220 case 2: scale = TIMES_2; break;
1221 case 4: scale = TIMES_4; break;
1222 case 8: scale = TIMES_8; break;
1223 default: break;
1224 }
Aart Bik0148de42017-09-05 09:25:01 -07001225 // Incorporate the string or array offset in the address computation.
Aart Bik472821b2017-04-27 17:23:51 -07001226 uint32_t offset = is_string_char_at
1227 ? mirror::String::ValueOffset().Uint32Value()
1228 : mirror::Array::DataOffset(size).Uint32Value();
Aart Bikf8f5a162017-02-06 15:35:29 -08001229 return CodeGeneratorX86::ArrayAddress(base.AsRegister<Register>(), index, scale, offset);
1230}
1231
1232void LocationsBuilderX86::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001233 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bik472821b2017-04-27 17:23:51 -07001234 // String load requires a temporary for the compressed load.
1235 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1236 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
1237 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001238}
1239
1240void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001241 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001242 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001243 Address address = VecAddress(locations, size, instruction->IsStringCharAt());
1244 XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001245 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1246 switch (instruction->GetPackedType()) {
Vladimir Marko805b6312018-09-05 14:46:06 +01001247 case DataType::Type::kInt16: // (short) s.charAt(.) can yield HVecLoad/Int16/StringCharAt.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001248 case DataType::Type::kUint16:
Aart Bik472821b2017-04-27 17:23:51 -07001249 DCHECK_EQ(8u, instruction->GetVectorLength());
1250 // Special handling of compressed/uncompressed string load.
1251 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1252 NearLabel done, not_compressed;
1253 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1254 // Test compression bit.
1255 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
1256 "Expecting 0=compressed, 1=uncompressed");
1257 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
1258 __ testb(Address(locations->InAt(0).AsRegister<Register>(), count_offset), Immediate(1));
1259 __ j(kNotZero, &not_compressed);
1260 // Zero extend 8 compressed bytes into 8 chars.
Aart Bik0148de42017-09-05 09:25:01 -07001261 __ movsd(reg, VecAddress(locations, 1, instruction->IsStringCharAt()));
Aart Bik472821b2017-04-27 17:23:51 -07001262 __ pxor(tmp, tmp);
1263 __ punpcklbw(reg, tmp);
1264 __ jmp(&done);
1265 // Load 4 direct uncompressed chars.
1266 __ Bind(&not_compressed);
1267 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1268 __ Bind(&done);
1269 return;
1270 }
1271 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001272 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001273 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001274 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001275 case DataType::Type::kInt32:
1276 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001277 DCHECK_LE(2u, instruction->GetVectorLength());
1278 DCHECK_LE(instruction->GetVectorLength(), 16u);
1279 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1280 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001281 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001282 DCHECK_EQ(4u, instruction->GetVectorLength());
1283 is_aligned16 ? __ movaps(reg, address) : __ movups(reg, address);
1284 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001285 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001286 DCHECK_EQ(2u, instruction->GetVectorLength());
1287 is_aligned16 ? __ movapd(reg, address) : __ movupd(reg, address);
1288 break;
1289 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001290 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001291 UNREACHABLE();
1292 }
1293}
1294
1295void LocationsBuilderX86::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001296 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001297}
1298
1299void InstructionCodeGeneratorX86::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001300 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001301 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001302 Address address = VecAddress(locations, size, /*is_string_char_at*/ false);
1303 XmmRegister reg = locations->InAt(2).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001304 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1305 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001306 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001307 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001308 case DataType::Type::kInt8:
1309 case DataType::Type::kUint16:
1310 case DataType::Type::kInt16:
1311 case DataType::Type::kInt32:
1312 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001313 DCHECK_LE(2u, instruction->GetVectorLength());
1314 DCHECK_LE(instruction->GetVectorLength(), 16u);
1315 is_aligned16 ? __ movdqa(address, reg) : __ movdqu(address, reg);
1316 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001317 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001318 DCHECK_EQ(4u, instruction->GetVectorLength());
1319 is_aligned16 ? __ movaps(address, reg) : __ movups(address, reg);
1320 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001321 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001322 DCHECK_EQ(2u, instruction->GetVectorLength());
1323 is_aligned16 ? __ movapd(address, reg) : __ movupd(address, reg);
1324 break;
1325 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001326 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001327 UNREACHABLE();
1328 }
1329}
1330
1331#undef __
1332
1333} // namespace x86
1334} // namespace art