blob: 086ae07a0644f74c4f2d09298bd554a665e2dc39 [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 ||
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:
Aart Bik29aa0822018-03-08 11:28:00 -0800261 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700262 }
263 break;
264 }
265 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800266 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700267 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 {
Aart Bik29aa0822018-03-08 11:28:00 -0800285 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800286 }
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:
Aart Bik29aa0822018-03-08 11:28:00 -0800331 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800332 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800372 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik6daebeb2017-04-03 14:35:41 -0700373 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800421 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800422 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800444 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800445 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800486 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
487 UNREACHABLE();
488 }
489}
490
491void LocationsBuilderX86::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
492 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
493}
494
495void InstructionCodeGeneratorX86::VisitVecSaturationAdd(HVecSaturationAdd* 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 switch (instruction->GetPackedType()) {
501 case DataType::Type::kUint8:
502 DCHECK_EQ(16u, instruction->GetVectorLength());
503 __ paddusb(dst, src);
504 break;
505 case DataType::Type::kInt8:
506 DCHECK_EQ(16u, instruction->GetVectorLength());
507 __ paddsb(dst, src);
508 break;
509 case DataType::Type::kUint16:
510 DCHECK_EQ(8u, instruction->GetVectorLength());
511 __ paddusw(dst, src);
512 break;
513 case DataType::Type::kInt16:
514 DCHECK_EQ(8u, instruction->GetVectorLength());
515 __ paddsw(dst, src);
516 break;
517 default:
518 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800519 UNREACHABLE();
520 }
521}
522
Aart Bikf3e61ee2017-04-12 17:09:20 -0700523void LocationsBuilderX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100524 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700525}
526
527void InstructionCodeGeneratorX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
528 LocationSummary* locations = instruction->GetLocations();
529 DCHECK(locations->InAt(0).Equals(locations->Out()));
530 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
531 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
532
533 DCHECK(instruction->IsRounded());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700534
535 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100536 case DataType::Type::kUint8:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700537 DCHECK_EQ(16u, instruction->GetVectorLength());
Aart Bik29aa0822018-03-08 11:28:00 -0800538 __ pavgb(dst, src);
539 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100540 case DataType::Type::kUint16:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700541 DCHECK_EQ(8u, instruction->GetVectorLength());
542 __ pavgw(dst, src);
Aart Bik29aa0822018-03-08 11:28:00 -0800543 break;
Aart Bikf3e61ee2017-04-12 17:09:20 -0700544 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800545 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf3e61ee2017-04-12 17:09:20 -0700546 UNREACHABLE();
547 }
548}
549
Aart Bikf8f5a162017-02-06 15:35:29 -0800550void LocationsBuilderX86::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100551 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800552}
553
554void InstructionCodeGeneratorX86::VisitVecSub(HVecSub* instruction) {
555 LocationSummary* locations = instruction->GetLocations();
556 DCHECK(locations->InAt(0).Equals(locations->Out()));
557 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
558 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
559 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100560 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100561 case DataType::Type::kInt8:
Aart Bikf8f5a162017-02-06 15:35:29 -0800562 DCHECK_EQ(16u, instruction->GetVectorLength());
563 __ psubb(dst, src);
564 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100565 case DataType::Type::kUint16:
566 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800567 DCHECK_EQ(8u, instruction->GetVectorLength());
568 __ psubw(dst, src);
569 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100570 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800571 DCHECK_EQ(4u, instruction->GetVectorLength());
572 __ psubd(dst, src);
573 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100574 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800575 DCHECK_EQ(2u, instruction->GetVectorLength());
576 __ psubq(dst, src);
577 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100578 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800579 DCHECK_EQ(4u, instruction->GetVectorLength());
580 __ subps(dst, src);
581 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100582 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800583 DCHECK_EQ(2u, instruction->GetVectorLength());
584 __ subpd(dst, src);
585 break;
586 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800587 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
588 UNREACHABLE();
589 }
590}
591
592void LocationsBuilderX86::VisitVecSaturationSub(HVecSaturationSub* instruction) {
593 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
594}
595
596void InstructionCodeGeneratorX86::VisitVecSaturationSub(HVecSaturationSub* instruction) {
597 LocationSummary* locations = instruction->GetLocations();
598 DCHECK(locations->InAt(0).Equals(locations->Out()));
599 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
600 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
601 switch (instruction->GetPackedType()) {
602 case DataType::Type::kUint8:
603 DCHECK_EQ(16u, instruction->GetVectorLength());
604 __ psubusb(dst, src);
605 break;
606 case DataType::Type::kInt8:
607 DCHECK_EQ(16u, instruction->GetVectorLength());
608 __ psubsb(dst, src);
609 break;
610 case DataType::Type::kUint16:
611 DCHECK_EQ(8u, instruction->GetVectorLength());
612 __ psubusw(dst, src);
613 break;
614 case DataType::Type::kInt16:
615 DCHECK_EQ(8u, instruction->GetVectorLength());
616 __ psubsw(dst, src);
617 break;
618 default:
619 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800620 UNREACHABLE();
621 }
622}
623
624void LocationsBuilderX86::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100625 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800626}
627
628void InstructionCodeGeneratorX86::VisitVecMul(HVecMul* instruction) {
629 LocationSummary* locations = instruction->GetLocations();
630 DCHECK(locations->InAt(0).Equals(locations->Out()));
631 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
632 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
633 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100634 case DataType::Type::kUint16:
635 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800636 DCHECK_EQ(8u, instruction->GetVectorLength());
637 __ pmullw(dst, src);
638 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100639 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800640 DCHECK_EQ(4u, instruction->GetVectorLength());
641 __ pmulld(dst, src);
642 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100643 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800644 DCHECK_EQ(4u, instruction->GetVectorLength());
645 __ mulps(dst, src);
646 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100647 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800648 DCHECK_EQ(2u, instruction->GetVectorLength());
649 __ mulpd(dst, src);
650 break;
651 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800652 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800653 UNREACHABLE();
654 }
655}
656
657void LocationsBuilderX86::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100658 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800659}
660
661void InstructionCodeGeneratorX86::VisitVecDiv(HVecDiv* instruction) {
662 LocationSummary* locations = instruction->GetLocations();
663 DCHECK(locations->InAt(0).Equals(locations->Out()));
664 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
665 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
666 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100667 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800668 DCHECK_EQ(4u, instruction->GetVectorLength());
669 __ divps(dst, src);
670 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100671 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800672 DCHECK_EQ(2u, instruction->GetVectorLength());
673 __ divpd(dst, src);
674 break;
675 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800676 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800677 UNREACHABLE();
678 }
679}
680
Aart Bikf3e61ee2017-04-12 17:09:20 -0700681void LocationsBuilderX86::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100682 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700683}
684
685void InstructionCodeGeneratorX86::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700686 LocationSummary* locations = instruction->GetLocations();
687 DCHECK(locations->InAt(0).Equals(locations->Out()));
688 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
689 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
690 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100691 case DataType::Type::kUint8:
692 DCHECK_EQ(16u, instruction->GetVectorLength());
693 __ pminub(dst, src);
694 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100695 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700696 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100697 __ pminsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700698 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100699 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100700 DCHECK_EQ(8u, instruction->GetVectorLength());
701 __ pminuw(dst, src);
702 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100703 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700704 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100705 __ pminsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700706 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800707 case DataType::Type::kUint32:
708 DCHECK_EQ(4u, instruction->GetVectorLength());
709 __ pminud(dst, src);
710 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100711 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700712 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800713 __ pminsd(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700714 break;
715 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100716 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700717 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700718 __ minps(dst, src);
719 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100720 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700721 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700722 __ minpd(dst, src);
723 break;
724 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800725 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700726 UNREACHABLE();
727 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700728}
729
730void LocationsBuilderX86::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100731 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700732}
733
734void InstructionCodeGeneratorX86::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700735 LocationSummary* locations = instruction->GetLocations();
736 DCHECK(locations->InAt(0).Equals(locations->Out()));
737 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
738 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
739 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100740 case DataType::Type::kUint8:
741 DCHECK_EQ(16u, instruction->GetVectorLength());
742 __ pmaxub(dst, src);
743 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100744 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700745 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100746 __ pmaxsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700747 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100748 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100749 DCHECK_EQ(8u, instruction->GetVectorLength());
750 __ pmaxuw(dst, src);
751 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100752 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700753 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100754 __ pmaxsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700755 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800756 case DataType::Type::kUint32:
757 DCHECK_EQ(4u, instruction->GetVectorLength());
758 __ pmaxud(dst, src);
759 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100760 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700761 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800762 __ pmaxsd(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700763 break;
764 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100765 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700766 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700767 __ maxps(dst, src);
768 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100769 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700770 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700771 __ maxpd(dst, src);
772 break;
773 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800774 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700775 UNREACHABLE();
776 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700777}
778
Aart Bikf8f5a162017-02-06 15:35:29 -0800779void LocationsBuilderX86::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100780 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800781}
782
783void InstructionCodeGeneratorX86::VisitVecAnd(HVecAnd* instruction) {
784 LocationSummary* locations = instruction->GetLocations();
785 DCHECK(locations->InAt(0).Equals(locations->Out()));
786 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
787 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
788 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100789 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100790 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100791 case DataType::Type::kInt8:
792 case DataType::Type::kUint16:
793 case DataType::Type::kInt16:
794 case DataType::Type::kInt32:
795 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800796 DCHECK_LE(2u, instruction->GetVectorLength());
797 DCHECK_LE(instruction->GetVectorLength(), 16u);
798 __ pand(dst, src);
799 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100800 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800801 DCHECK_EQ(4u, instruction->GetVectorLength());
802 __ andps(dst, src);
803 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100804 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800805 DCHECK_EQ(2u, instruction->GetVectorLength());
806 __ andpd(dst, src);
807 break;
808 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800809 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800810 UNREACHABLE();
811 }
812}
813
814void LocationsBuilderX86::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100815 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800816}
817
818void InstructionCodeGeneratorX86::VisitVecAndNot(HVecAndNot* instruction) {
819 LocationSummary* locations = instruction->GetLocations();
820 DCHECK(locations->InAt(0).Equals(locations->Out()));
821 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
822 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
823 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100824 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100825 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100826 case DataType::Type::kInt8:
827 case DataType::Type::kUint16:
828 case DataType::Type::kInt16:
829 case DataType::Type::kInt32:
830 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800831 DCHECK_LE(2u, instruction->GetVectorLength());
832 DCHECK_LE(instruction->GetVectorLength(), 16u);
833 __ pandn(dst, src);
834 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100835 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800836 DCHECK_EQ(4u, instruction->GetVectorLength());
837 __ andnps(dst, src);
838 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100839 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800840 DCHECK_EQ(2u, instruction->GetVectorLength());
841 __ andnpd(dst, src);
842 break;
843 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800844 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800845 UNREACHABLE();
846 }
847}
848
849void LocationsBuilderX86::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100850 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800851}
852
853void InstructionCodeGeneratorX86::VisitVecOr(HVecOr* instruction) {
854 LocationSummary* locations = instruction->GetLocations();
855 DCHECK(locations->InAt(0).Equals(locations->Out()));
856 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
857 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
858 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100859 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100860 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100861 case DataType::Type::kInt8:
862 case DataType::Type::kUint16:
863 case DataType::Type::kInt16:
864 case DataType::Type::kInt32:
865 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800866 DCHECK_LE(2u, instruction->GetVectorLength());
867 DCHECK_LE(instruction->GetVectorLength(), 16u);
868 __ por(dst, src);
869 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100870 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800871 DCHECK_EQ(4u, instruction->GetVectorLength());
872 __ orps(dst, src);
873 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100874 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800875 DCHECK_EQ(2u, instruction->GetVectorLength());
876 __ orpd(dst, src);
877 break;
878 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800879 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800880 UNREACHABLE();
881 }
882}
883
884void LocationsBuilderX86::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100885 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800886}
887
888void InstructionCodeGeneratorX86::VisitVecXor(HVecXor* instruction) {
889 LocationSummary* locations = instruction->GetLocations();
890 DCHECK(locations->InAt(0).Equals(locations->Out()));
891 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
892 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
893 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100894 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100895 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100896 case DataType::Type::kInt8:
897 case DataType::Type::kUint16:
898 case DataType::Type::kInt16:
899 case DataType::Type::kInt32:
900 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800901 DCHECK_LE(2u, instruction->GetVectorLength());
902 DCHECK_LE(instruction->GetVectorLength(), 16u);
903 __ pxor(dst, src);
904 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100905 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800906 DCHECK_EQ(4u, instruction->GetVectorLength());
907 __ xorps(dst, src);
908 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100909 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800910 DCHECK_EQ(2u, instruction->GetVectorLength());
911 __ xorpd(dst, src);
912 break;
913 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800914 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800915 UNREACHABLE();
916 }
917}
918
919// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100920static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
921 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800922 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100923 case DataType::Type::kUint16:
924 case DataType::Type::kInt16:
925 case DataType::Type::kInt32:
926 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800927 locations->SetInAt(0, Location::RequiresFpuRegister());
928 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
929 locations->SetOut(Location::SameAsFirstInput());
930 break;
931 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800932 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800933 UNREACHABLE();
934 }
935}
936
937void LocationsBuilderX86::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100938 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800939}
940
941void InstructionCodeGeneratorX86::VisitVecShl(HVecShl* instruction) {
942 LocationSummary* locations = instruction->GetLocations();
943 DCHECK(locations->InAt(0).Equals(locations->Out()));
944 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
945 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
946 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100947 case DataType::Type::kUint16:
948 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800949 DCHECK_EQ(8u, instruction->GetVectorLength());
950 __ psllw(dst, Immediate(static_cast<uint8_t>(value)));
951 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100952 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800953 DCHECK_EQ(4u, instruction->GetVectorLength());
954 __ pslld(dst, Immediate(static_cast<uint8_t>(value)));
955 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100956 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800957 DCHECK_EQ(2u, instruction->GetVectorLength());
958 __ psllq(dst, Immediate(static_cast<uint8_t>(value)));
959 break;
960 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800961 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800962 UNREACHABLE();
963 }
964}
965
966void LocationsBuilderX86::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100967 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800968}
969
970void InstructionCodeGeneratorX86::VisitVecShr(HVecShr* instruction) {
971 LocationSummary* locations = instruction->GetLocations();
972 DCHECK(locations->InAt(0).Equals(locations->Out()));
973 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
974 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
975 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100976 case DataType::Type::kUint16:
977 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800978 DCHECK_EQ(8u, instruction->GetVectorLength());
979 __ psraw(dst, Immediate(static_cast<uint8_t>(value)));
980 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100981 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800982 DCHECK_EQ(4u, instruction->GetVectorLength());
983 __ psrad(dst, Immediate(static_cast<uint8_t>(value)));
984 break;
985 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800986 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800987 UNREACHABLE();
988 }
989}
990
991void LocationsBuilderX86::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100992 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800993}
994
995void InstructionCodeGeneratorX86::VisitVecUShr(HVecUShr* instruction) {
996 LocationSummary* locations = instruction->GetLocations();
997 DCHECK(locations->InAt(0).Equals(locations->Out()));
998 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
999 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
1000 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001001 case DataType::Type::kUint16:
1002 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -08001003 DCHECK_EQ(8u, instruction->GetVectorLength());
1004 __ psrlw(dst, Immediate(static_cast<uint8_t>(value)));
1005 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001006 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001007 DCHECK_EQ(4u, instruction->GetVectorLength());
1008 __ psrld(dst, Immediate(static_cast<uint8_t>(value)));
1009 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001010 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001011 DCHECK_EQ(2u, instruction->GetVectorLength());
1012 __ psrlq(dst, Immediate(static_cast<uint8_t>(value)));
1013 break;
1014 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001015 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001016 UNREACHABLE();
1017 }
1018}
1019
Aart Bik0148de42017-09-05 09:25:01 -07001020void LocationsBuilderX86::VisitVecSetScalars(HVecSetScalars* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001021 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -07001022
1023 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
1024
1025 HInstruction* input = instruction->InputAt(0);
1026 bool is_zero = IsZeroBitPattern(input);
1027
1028 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001029 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -07001030 // Long needs extra temporary to load from register pairs.
1031 if (!is_zero) {
1032 locations->AddTemp(Location::RequiresFpuRegister());
1033 }
1034 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001035 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001036 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001037 case DataType::Type::kInt8:
1038 case DataType::Type::kUint16:
1039 case DataType::Type::kInt16:
1040 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001041 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
1042 : Location::RequiresRegister());
1043 locations->SetOut(Location::RequiresFpuRegister());
1044 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001045 case DataType::Type::kFloat32:
1046 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -07001047 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
1048 : Location::RequiresFpuRegister());
1049 locations->SetOut(Location::RequiresFpuRegister());
1050 break;
1051 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001052 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001053 UNREACHABLE();
1054 }
1055}
1056
1057void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction) {
1058 LocationSummary* locations = instruction->GetLocations();
1059 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
1060
1061 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
1062
1063 // Zero out all other elements first.
1064 __ xorps(dst, dst);
1065
1066 // Shorthand for any type of zero.
1067 if (IsZeroBitPattern(instruction->InputAt(0))) {
1068 return;
1069 }
1070
1071 // Set required elements.
1072 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001073 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001074 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001075 case DataType::Type::kInt8:
1076 case DataType::Type::kUint16:
1077 case DataType::Type::kInt16: // TODO: up to here, and?
Aart Bik29aa0822018-03-08 11:28:00 -08001078 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001079 UNREACHABLE();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001080 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001081 DCHECK_EQ(4u, instruction->GetVectorLength());
1082 __ movd(dst, locations->InAt(0).AsRegister<Register>());
1083 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001084 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -07001085 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -08001086 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Aart Bik0148de42017-09-05 09:25:01 -07001087 __ xorps(tmp, tmp);
1088 __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
1089 __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
1090 __ punpckldq(dst, tmp);
1091 break;
1092 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001093 case DataType::Type::kFloat32:
Aart Bik0148de42017-09-05 09:25:01 -07001094 DCHECK_EQ(4u, instruction->GetVectorLength());
1095 __ movss(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1096 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001097 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -07001098 DCHECK_EQ(2u, instruction->GetVectorLength());
1099 __ movsd(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1100 break;
1101 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001102 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001103 UNREACHABLE();
1104 }
1105}
1106
Aart Bikdbbac8f2017-09-01 13:06:08 -07001107// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001108static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1109 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001110 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001111 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001112 case DataType::Type::kInt8:
1113 case DataType::Type::kUint16:
1114 case DataType::Type::kInt16:
1115 case DataType::Type::kInt32:
1116 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001117 locations->SetInAt(0, Location::RequiresFpuRegister());
1118 locations->SetInAt(1, Location::RequiresFpuRegister());
1119 locations->SetInAt(2, Location::RequiresFpuRegister());
1120 locations->SetOut(Location::SameAsFirstInput());
1121 break;
1122 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001123 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001124 UNREACHABLE();
1125 }
Artem Serovf34dd202017-04-10 17:41:46 +01001126}
1127
Aart Bikdbbac8f2017-09-01 13:06:08 -07001128void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001129 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001130}
1131
1132void InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1133 // TODO: pmaddwd?
1134 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1135}
1136
1137void LocationsBuilderX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001138 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001139}
1140
1141void InstructionCodeGeneratorX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
1142 // TODO: psadbw for unsigned?
1143 LOG(FATAL) << "No SIMD for " << instruction->GetId();
Artem Serovf34dd202017-04-10 17:41:46 +01001144}
1145
Aart Bikf8f5a162017-02-06 15:35:29 -08001146// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001147static void CreateVecMemLocations(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001148 HVecMemoryOperation* instruction,
1149 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001150 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001151 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001152 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001153 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001154 case DataType::Type::kInt8:
1155 case DataType::Type::kUint16:
1156 case DataType::Type::kInt16:
1157 case DataType::Type::kInt32:
1158 case DataType::Type::kInt64:
1159 case DataType::Type::kFloat32:
1160 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001161 locations->SetInAt(0, Location::RequiresRegister());
1162 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1163 if (is_load) {
1164 locations->SetOut(Location::RequiresFpuRegister());
1165 } else {
1166 locations->SetInAt(2, Location::RequiresFpuRegister());
1167 }
1168 break;
1169 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001170 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001171 UNREACHABLE();
1172 }
1173}
1174
Aart Bik472821b2017-04-27 17:23:51 -07001175// Helper to construct address for vector memory operations.
1176static Address VecAddress(LocationSummary* locations, size_t size, bool is_string_char_at) {
Aart Bikf8f5a162017-02-06 15:35:29 -08001177 Location base = locations->InAt(0);
1178 Location index = locations->InAt(1);
Aart Bikf8f5a162017-02-06 15:35:29 -08001179 ScaleFactor scale = TIMES_1;
1180 switch (size) {
1181 case 2: scale = TIMES_2; break;
1182 case 4: scale = TIMES_4; break;
1183 case 8: scale = TIMES_8; break;
1184 default: break;
1185 }
Aart Bik0148de42017-09-05 09:25:01 -07001186 // Incorporate the string or array offset in the address computation.
Aart Bik472821b2017-04-27 17:23:51 -07001187 uint32_t offset = is_string_char_at
1188 ? mirror::String::ValueOffset().Uint32Value()
1189 : mirror::Array::DataOffset(size).Uint32Value();
Aart Bikf8f5a162017-02-06 15:35:29 -08001190 return CodeGeneratorX86::ArrayAddress(base.AsRegister<Register>(), index, scale, offset);
1191}
1192
1193void LocationsBuilderX86::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001194 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bik472821b2017-04-27 17:23:51 -07001195 // String load requires a temporary for the compressed load.
1196 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1197 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
1198 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001199}
1200
1201void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001202 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001203 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001204 Address address = VecAddress(locations, size, instruction->IsStringCharAt());
1205 XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001206 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1207 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001208 case DataType::Type::kUint16:
Aart Bik472821b2017-04-27 17:23:51 -07001209 DCHECK_EQ(8u, instruction->GetVectorLength());
1210 // Special handling of compressed/uncompressed string load.
1211 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1212 NearLabel done, not_compressed;
1213 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1214 // Test compression bit.
1215 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
1216 "Expecting 0=compressed, 1=uncompressed");
1217 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
1218 __ testb(Address(locations->InAt(0).AsRegister<Register>(), count_offset), Immediate(1));
1219 __ j(kNotZero, &not_compressed);
1220 // Zero extend 8 compressed bytes into 8 chars.
Aart Bik0148de42017-09-05 09:25:01 -07001221 __ movsd(reg, VecAddress(locations, 1, instruction->IsStringCharAt()));
Aart Bik472821b2017-04-27 17:23:51 -07001222 __ pxor(tmp, tmp);
1223 __ punpcklbw(reg, tmp);
1224 __ jmp(&done);
1225 // Load 4 direct uncompressed chars.
1226 __ Bind(&not_compressed);
1227 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1228 __ Bind(&done);
1229 return;
1230 }
1231 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001232 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001233 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001234 case DataType::Type::kInt8:
1235 case DataType::Type::kInt16:
1236 case DataType::Type::kInt32:
1237 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001238 DCHECK_LE(2u, instruction->GetVectorLength());
1239 DCHECK_LE(instruction->GetVectorLength(), 16u);
1240 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1241 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001242 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001243 DCHECK_EQ(4u, instruction->GetVectorLength());
1244 is_aligned16 ? __ movaps(reg, address) : __ movups(reg, address);
1245 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001246 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001247 DCHECK_EQ(2u, instruction->GetVectorLength());
1248 is_aligned16 ? __ movapd(reg, address) : __ movupd(reg, address);
1249 break;
1250 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001251 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001252 UNREACHABLE();
1253 }
1254}
1255
1256void LocationsBuilderX86::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001257 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001258}
1259
1260void InstructionCodeGeneratorX86::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001261 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001262 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001263 Address address = VecAddress(locations, size, /*is_string_char_at*/ false);
1264 XmmRegister reg = locations->InAt(2).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001265 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1266 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001267 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001268 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001269 case DataType::Type::kInt8:
1270 case DataType::Type::kUint16:
1271 case DataType::Type::kInt16:
1272 case DataType::Type::kInt32:
1273 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001274 DCHECK_LE(2u, instruction->GetVectorLength());
1275 DCHECK_LE(instruction->GetVectorLength(), 16u);
1276 is_aligned16 ? __ movdqa(address, reg) : __ movdqu(address, reg);
1277 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001278 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001279 DCHECK_EQ(4u, instruction->GetVectorLength());
1280 is_aligned16 ? __ movaps(address, reg) : __ movups(address, reg);
1281 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001282 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001283 DCHECK_EQ(2u, instruction->GetVectorLength());
1284 is_aligned16 ? __ movapd(address, reg) : __ movupd(address, reg);
1285 break;
1286 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001287 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001288 UNREACHABLE();
1289 }
1290}
1291
1292#undef __
1293
1294} // namespace x86
1295} // namespace art