blob: 9c837dd986376609d7bbb550b819c41e500a47d1 [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
Vladimir Marko0a516052019-10-14 13:00:44 +000022namespace art {
Aart Bikf8f5a162017-02-06 15:35:29 -080023namespace 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
Neeraj Solanki48349ad2019-08-05 23:16:56 +053066 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Aart Bik0148de42017-09-05 09:25:01 -070067 // Shorthand for any type of zero.
68 if (IsZeroBitPattern(instruction->InputAt(0))) {
Neeraj Solanki48349ad2019-08-05 23:16:56 +053069 cpu_has_avx ? __ vxorps(dst, dst, dst) : __ xorps(dst, dst);
Aart Bik0148de42017-09-05 09:25:01 -070070 return;
71 }
72
73 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010074 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010075 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010076 case DataType::Type::kInt8:
Aart Bik0148de42017-09-05 09:25:01 -070077 DCHECK_EQ(16u, instruction->GetVectorLength());
78 __ movd(dst, locations->InAt(0).AsRegister<Register>());
79 __ punpcklbw(dst, dst);
80 __ punpcklwd(dst, dst);
81 __ pshufd(dst, dst, Immediate(0));
82 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010083 case DataType::Type::kUint16:
84 case DataType::Type::kInt16:
Aart Bik0148de42017-09-05 09:25:01 -070085 DCHECK_EQ(8u, instruction->GetVectorLength());
86 __ movd(dst, locations->InAt(0).AsRegister<Register>());
87 __ punpcklwd(dst, dst);
88 __ pshufd(dst, dst, Immediate(0));
89 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010090 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -070091 DCHECK_EQ(4u, instruction->GetVectorLength());
92 __ movd(dst, locations->InAt(0).AsRegister<Register>());
93 __ pshufd(dst, dst, Immediate(0));
94 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010095 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -070096 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -080097 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Aart Bik0148de42017-09-05 09:25:01 -070098 __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
99 __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
100 __ punpckldq(dst, tmp);
101 __ punpcklqdq(dst, dst);
102 break;
103 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100104 case DataType::Type::kFloat32:
Aart Bik0148de42017-09-05 09:25:01 -0700105 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -0800106 DCHECK(locations->InAt(0).Equals(locations->Out()));
Aart Bik0148de42017-09-05 09:25:01 -0700107 __ shufps(dst, dst, Immediate(0));
108 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100109 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700110 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -0800111 DCHECK(locations->InAt(0).Equals(locations->Out()));
Aart Bik0148de42017-09-05 09:25:01 -0700112 __ shufpd(dst, dst, Immediate(0));
113 break;
114 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800115 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700116 UNREACHABLE();
117 }
118}
119
120void LocationsBuilderX86::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100121 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700122 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100123 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700124 // Long needs extra temporary to store into the register pair.
Aart Bika57b4ee2017-08-30 21:21:41 +0000125 locations->AddTemp(Location::RequiresFpuRegister());
Aart Bik9879d0e2017-08-15 10:51:25 -0700126 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100127 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100128 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100129 case DataType::Type::kInt8:
130 case DataType::Type::kUint16:
131 case DataType::Type::kInt16:
132 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700133 locations->SetInAt(0, Location::RequiresFpuRegister());
134 locations->SetOut(Location::RequiresRegister());
Aart Bik9879d0e2017-08-15 10:51:25 -0700135 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100136 case DataType::Type::kFloat32:
137 case DataType::Type::kFloat64:
Aart Bika57b4ee2017-08-30 21:21:41 +0000138 locations->SetInAt(0, Location::RequiresFpuRegister());
Aart Bik9879d0e2017-08-15 10:51:25 -0700139 locations->SetOut(Location::SameAsFirstInput());
140 break;
141 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800142 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik9879d0e2017-08-15 10:51:25 -0700143 UNREACHABLE();
144 }
145}
146
Aart Bik0148de42017-09-05 09:25:01 -0700147void InstructionCodeGeneratorX86::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Aart Bik9879d0e2017-08-15 10:51:25 -0700148 LocationSummary* locations = instruction->GetLocations();
Aart Bik0148de42017-09-05 09:25:01 -0700149 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bik9879d0e2017-08-15 10:51:25 -0700150 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100151 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100152 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100153 case DataType::Type::kInt8:
154 case DataType::Type::kUint16:
155 case DataType::Type::kInt16: // TODO: up to here, and?
Aart Bik29aa0822018-03-08 11:28:00 -0800156 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700157 UNREACHABLE();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100158 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700159 DCHECK_LE(4u, instruction->GetVectorLength());
160 DCHECK_LE(instruction->GetVectorLength(), 16u);
161 __ movd(locations->Out().AsRegister<Register>(), src);
Aart Bik9879d0e2017-08-15 10:51:25 -0700162 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100163 case DataType::Type::kInt64: {
Aart Bik9879d0e2017-08-15 10:51:25 -0700164 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -0800165 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Aart Bik0148de42017-09-05 09:25:01 -0700166 __ movd(locations->Out().AsRegisterPairLow<Register>(), src);
167 __ pshufd(tmp, src, Immediate(1));
168 __ movd(locations->Out().AsRegisterPairHigh<Register>(), tmp);
Aart Bik9879d0e2017-08-15 10:51:25 -0700169 break;
170 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100171 case DataType::Type::kFloat32:
172 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700173 DCHECK_LE(2u, instruction->GetVectorLength());
174 DCHECK_LE(instruction->GetVectorLength(), 4u);
175 DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required
Aart Bik9879d0e2017-08-15 10:51:25 -0700176 break;
177 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800178 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik9879d0e2017-08-15 10:51:25 -0700179 UNREACHABLE();
180 }
181}
182
Aart Bikf8f5a162017-02-06 15:35:29 -0800183// Helper to set up locations for vector unary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100184static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
185 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800186 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100187 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100188 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100189 case DataType::Type::kInt8:
190 case DataType::Type::kUint16:
191 case DataType::Type::kInt16:
192 case DataType::Type::kInt32:
193 case DataType::Type::kInt64:
194 case DataType::Type::kFloat32:
195 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800196 locations->SetInAt(0, Location::RequiresFpuRegister());
197 locations->SetOut(Location::RequiresFpuRegister());
198 break;
199 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800200 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800201 UNREACHABLE();
202 }
203}
204
Aart Bik0148de42017-09-05 09:25:01 -0700205void LocationsBuilderX86::VisitVecReduce(HVecReduce* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100206 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700207 // Long reduction or min/max require a temporary.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100208 if (instruction->GetPackedType() == DataType::Type::kInt64 ||
Vladimir Marko4e3734a2018-11-14 15:45:28 +0000209 instruction->GetReductionKind() == HVecReduce::kMin ||
210 instruction->GetReductionKind() == HVecReduce::kMax) {
Aart Bik0148de42017-09-05 09:25:01 -0700211 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
212 }
213}
214
215void InstructionCodeGeneratorX86::VisitVecReduce(HVecReduce* instruction) {
216 LocationSummary* locations = instruction->GetLocations();
217 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
218 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
219 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100220 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700221 DCHECK_EQ(4u, instruction->GetVectorLength());
Vladimir Marko4e3734a2018-11-14 15:45:28 +0000222 switch (instruction->GetReductionKind()) {
Aart Bik0148de42017-09-05 09:25:01 -0700223 case HVecReduce::kSum:
224 __ movaps(dst, src);
225 __ phaddd(dst, dst);
226 __ phaddd(dst, dst);
227 break;
Vladimir Marko8786fd92018-11-14 15:47:03 +0000228 case HVecReduce::kMin:
229 case HVecReduce::kMax:
230 // Historical note: We've had a broken implementation here. b/117863065
231 // Do not draw on the old code if we ever want to bring MIN/MAX reduction back.
232 LOG(FATAL) << "Unsupported reduction type.";
Aart Bik0148de42017-09-05 09:25:01 -0700233 }
234 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100235 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -0700236 DCHECK_EQ(2u, instruction->GetVectorLength());
237 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Vladimir Marko4e3734a2018-11-14 15:45:28 +0000238 switch (instruction->GetReductionKind()) {
Aart Bik0148de42017-09-05 09:25:01 -0700239 case HVecReduce::kSum:
240 __ movaps(tmp, src);
241 __ movaps(dst, src);
242 __ punpckhqdq(tmp, tmp);
243 __ paddq(dst, tmp);
244 break;
245 case HVecReduce::kMin:
246 case HVecReduce::kMax:
Aart Bik29aa0822018-03-08 11:28:00 -0800247 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700248 }
249 break;
250 }
251 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800252 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -0700253 UNREACHABLE();
254 }
255}
256
Aart Bikf8f5a162017-02-06 15:35:29 -0800257void LocationsBuilderX86::VisitVecCnv(HVecCnv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100258 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800259}
260
261void InstructionCodeGeneratorX86::VisitVecCnv(HVecCnv* instruction) {
262 LocationSummary* locations = instruction->GetLocations();
263 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
264 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100265 DataType::Type from = instruction->GetInputType();
266 DataType::Type to = instruction->GetResultType();
267 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800268 DCHECK_EQ(4u, instruction->GetVectorLength());
269 __ cvtdq2ps(dst, src);
270 } else {
Aart Bik29aa0822018-03-08 11:28:00 -0800271 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800272 }
273}
274
275void LocationsBuilderX86::VisitVecNeg(HVecNeg* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100276 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800277}
278
279void InstructionCodeGeneratorX86::VisitVecNeg(HVecNeg* instruction) {
280 LocationSummary* locations = instruction->GetLocations();
281 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
282 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
283 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100284 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100285 case DataType::Type::kInt8:
Aart Bikf8f5a162017-02-06 15:35:29 -0800286 DCHECK_EQ(16u, instruction->GetVectorLength());
287 __ pxor(dst, dst);
288 __ psubb(dst, src);
289 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100290 case DataType::Type::kUint16:
291 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800292 DCHECK_EQ(8u, instruction->GetVectorLength());
293 __ pxor(dst, dst);
294 __ psubw(dst, src);
295 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100296 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800297 DCHECK_EQ(4u, instruction->GetVectorLength());
298 __ pxor(dst, dst);
299 __ psubd(dst, src);
300 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100301 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800302 DCHECK_EQ(2u, instruction->GetVectorLength());
303 __ pxor(dst, dst);
304 __ psubq(dst, src);
305 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100306 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800307 DCHECK_EQ(4u, instruction->GetVectorLength());
308 __ xorps(dst, dst);
309 __ subps(dst, src);
310 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100311 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800312 DCHECK_EQ(2u, instruction->GetVectorLength());
313 __ xorpd(dst, dst);
314 __ subpd(dst, src);
315 break;
316 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800317 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800318 UNREACHABLE();
319 }
320}
321
Aart Bik6daebeb2017-04-03 14:35:41 -0700322void LocationsBuilderX86::VisitVecAbs(HVecAbs* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100323 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik472821b2017-04-27 17:23:51 -0700324 // Integral-abs requires a temporary for the comparison.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100325 if (instruction->GetPackedType() == DataType::Type::kInt32) {
Aart Bik6daebeb2017-04-03 14:35:41 -0700326 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
327 }
328}
329
330void InstructionCodeGeneratorX86::VisitVecAbs(HVecAbs* instruction) {
331 LocationSummary* locations = instruction->GetLocations();
332 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
333 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
334 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100335 case DataType::Type::kInt32: {
Aart Bik6daebeb2017-04-03 14:35:41 -0700336 DCHECK_EQ(4u, instruction->GetVectorLength());
337 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
338 __ movaps(dst, src);
339 __ pxor(tmp, tmp);
340 __ pcmpgtd(tmp, dst);
341 __ pxor(dst, tmp);
342 __ psubd(dst, tmp);
343 break;
344 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100345 case DataType::Type::kFloat32:
Aart Bik6daebeb2017-04-03 14:35:41 -0700346 DCHECK_EQ(4u, instruction->GetVectorLength());
347 __ pcmpeqb(dst, dst); // all ones
348 __ psrld(dst, Immediate(1));
349 __ andps(dst, src);
350 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100351 case DataType::Type::kFloat64:
Aart Bik6daebeb2017-04-03 14:35:41 -0700352 DCHECK_EQ(2u, instruction->GetVectorLength());
353 __ pcmpeqb(dst, dst); // all ones
354 __ psrlq(dst, Immediate(1));
355 __ andpd(dst, src);
356 break;
357 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800358 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik6daebeb2017-04-03 14:35:41 -0700359 UNREACHABLE();
360 }
361}
362
Aart Bikf8f5a162017-02-06 15:35:29 -0800363void LocationsBuilderX86::VisitVecNot(HVecNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100364 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800365 // Boolean-not requires a temporary to construct the 16 x one.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100366 if (instruction->GetPackedType() == DataType::Type::kBool) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800367 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
368 }
369}
370
371void InstructionCodeGeneratorX86::VisitVecNot(HVecNot* instruction) {
372 LocationSummary* locations = instruction->GetLocations();
373 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
374 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
375 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100376 case DataType::Type::kBool: { // special case boolean-not
Aart Bikf8f5a162017-02-06 15:35:29 -0800377 DCHECK_EQ(16u, instruction->GetVectorLength());
378 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
379 __ pxor(dst, dst);
380 __ pcmpeqb(tmp, tmp); // all ones
381 __ psubb(dst, tmp); // 16 x one
382 __ pxor(dst, src);
383 break;
384 }
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100385 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100386 case DataType::Type::kInt8:
387 case DataType::Type::kUint16:
388 case DataType::Type::kInt16:
389 case DataType::Type::kInt32:
390 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800391 DCHECK_LE(2u, instruction->GetVectorLength());
392 DCHECK_LE(instruction->GetVectorLength(), 16u);
393 __ pcmpeqb(dst, dst); // all ones
394 __ pxor(dst, src);
395 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100396 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800397 DCHECK_EQ(4u, instruction->GetVectorLength());
398 __ pcmpeqb(dst, dst); // all ones
399 __ xorps(dst, src);
400 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100401 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800402 DCHECK_EQ(2u, instruction->GetVectorLength());
403 __ pcmpeqb(dst, dst); // all ones
404 __ xorpd(dst, src);
405 break;
406 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800407 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800408 UNREACHABLE();
409 }
410}
411
412// Helper to set up locations for vector binary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100413static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
414 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800415 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100416 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100417 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100418 case DataType::Type::kInt8:
419 case DataType::Type::kUint16:
420 case DataType::Type::kInt16:
421 case DataType::Type::kInt32:
422 case DataType::Type::kInt64:
423 case DataType::Type::kFloat32:
424 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800425 locations->SetInAt(0, Location::RequiresFpuRegister());
426 locations->SetInAt(1, Location::RequiresFpuRegister());
427 locations->SetOut(Location::SameAsFirstInput());
428 break;
429 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800430 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800431 UNREACHABLE();
432 }
433}
434
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530435static void CreateVecTerOpLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
436 LocationSummary* locations = new (allocator) LocationSummary(instruction);
437 switch (instruction->GetPackedType()) {
438 case DataType::Type::kBool:
439 case DataType::Type::kUint8:
440 case DataType::Type::kInt8:
441 case DataType::Type::kUint16:
442 case DataType::Type::kInt16:
443 case DataType::Type::kInt32:
444 case DataType::Type::kInt64:
445 case DataType::Type::kFloat32:
446 case DataType::Type::kFloat64:
447 locations->SetInAt(0, Location::RequiresFpuRegister());
448 locations->SetInAt(1, Location::RequiresFpuRegister());
449 locations->SetOut(Location::RequiresFpuRegister());
450 break;
451 default:
452 LOG(FATAL) << "Unsupported SIMD type";
453 UNREACHABLE();
454 }
455}
456
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530457void LocationsBuilderX86::VisitVecAdd(HVecAdd* instruction) {
458 if (CpuHasAvxFeatureFlag()) {
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530459 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530460 } else {
461 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
462 }
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530463}
464
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530465void InstructionCodeGeneratorX86::VisitVecAdd(HVecAdd* instruction) {
466 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530467 LocationSummary* locations = instruction->GetLocations();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530468 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
469 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530470 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530471 DCHECK(cpu_has_avx || other_src == dst);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530472 switch (instruction->GetPackedType()) {
473 case DataType::Type::kUint8:
474 case DataType::Type::kInt8:
475 DCHECK_EQ(16u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530476 cpu_has_avx ? __ vpaddb(dst, other_src, src) : __ paddb(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530477 break;
478 case DataType::Type::kUint16:
479 case DataType::Type::kInt16:
480 DCHECK_EQ(8u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530481 cpu_has_avx ? __ vpaddw(dst, other_src, src) : __ paddw(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530482 break;
483 case DataType::Type::kInt32:
484 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530485 cpu_has_avx ? __ vpaddd(dst, other_src, src) : __ paddd(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530486 break;
487 case DataType::Type::kInt64:
488 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530489 cpu_has_avx ? __ vpaddq(dst, other_src, src) : __ paddq(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530490 break;
491 case DataType::Type::kFloat32:
492 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530493 cpu_has_avx ? __ vaddps(dst, other_src, src) : __ addps(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530494 break;
495 case DataType::Type::kFloat64:
496 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530497 cpu_has_avx ? __ vaddpd(dst, other_src, src) : __ addpd(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530498 break;
499 default:
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530500 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530501 UNREACHABLE();
502 }
503}
504
Aart Bik29aa0822018-03-08 11:28:00 -0800505void LocationsBuilderX86::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
506 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
507}
508
509void InstructionCodeGeneratorX86::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
510 LocationSummary* locations = instruction->GetLocations();
511 DCHECK(locations->InAt(0).Equals(locations->Out()));
512 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
513 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
514 switch (instruction->GetPackedType()) {
515 case DataType::Type::kUint8:
516 DCHECK_EQ(16u, instruction->GetVectorLength());
517 __ paddusb(dst, src);
518 break;
519 case DataType::Type::kInt8:
520 DCHECK_EQ(16u, instruction->GetVectorLength());
521 __ paddsb(dst, src);
522 break;
523 case DataType::Type::kUint16:
524 DCHECK_EQ(8u, instruction->GetVectorLength());
525 __ paddusw(dst, src);
526 break;
527 case DataType::Type::kInt16:
528 DCHECK_EQ(8u, instruction->GetVectorLength());
529 __ paddsw(dst, src);
530 break;
531 default:
532 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800533 UNREACHABLE();
534 }
535}
536
Aart Bikf3e61ee2017-04-12 17:09:20 -0700537void LocationsBuilderX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100538 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700539}
540
541void InstructionCodeGeneratorX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
542 LocationSummary* locations = instruction->GetLocations();
543 DCHECK(locations->InAt(0).Equals(locations->Out()));
544 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
545 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
546
547 DCHECK(instruction->IsRounded());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700548
549 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100550 case DataType::Type::kUint8:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700551 DCHECK_EQ(16u, instruction->GetVectorLength());
Aart Bik29aa0822018-03-08 11:28:00 -0800552 __ pavgb(dst, src);
553 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100554 case DataType::Type::kUint16:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700555 DCHECK_EQ(8u, instruction->GetVectorLength());
556 __ pavgw(dst, src);
Aart Bik29aa0822018-03-08 11:28:00 -0800557 break;
Aart Bikf3e61ee2017-04-12 17:09:20 -0700558 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800559 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf3e61ee2017-04-12 17:09:20 -0700560 UNREACHABLE();
561 }
562}
563
Aart Bikf8f5a162017-02-06 15:35:29 -0800564void LocationsBuilderX86::VisitVecSub(HVecSub* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530565 if (CpuHasAvxFeatureFlag()) {
566 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
567 } else {
568 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik29aa0822018-03-08 11:28:00 -0800569 }
570}
571
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530572void InstructionCodeGeneratorX86::VisitVecSub(HVecSub* instruction) {
573 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530574 LocationSummary* locations = instruction->GetLocations();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530575 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
576 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530577 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530578 DCHECK(cpu_has_avx || other_src == dst);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530579 switch (instruction->GetPackedType()) {
580 case DataType::Type::kUint8:
581 case DataType::Type::kInt8:
582 DCHECK_EQ(16u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530583 cpu_has_avx ? __ vpsubb(dst, other_src, src) : __ psubb(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530584 break;
585 case DataType::Type::kUint16:
586 case DataType::Type::kInt16:
587 DCHECK_EQ(8u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530588 cpu_has_avx ? __ vpsubw(dst, other_src, src) : __ psubw(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530589 break;
590 case DataType::Type::kInt32:
591 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530592 cpu_has_avx ? __ vpsubd(dst, other_src, src) : __ psubd(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530593 break;
594 case DataType::Type::kInt64:
595 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530596 cpu_has_avx ? __ vpsubq(dst, other_src, src) : __ psubq(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530597 break;
598 case DataType::Type::kFloat32:
599 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530600 cpu_has_avx ? __ vsubps(dst, other_src, src) : __ subps(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530601 break;
602 case DataType::Type::kFloat64:
603 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530604 cpu_has_avx ? __ vsubpd(dst, other_src, src) : __ subpd(dst, src);
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530605 break;
606 default:
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530607 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530608 UNREACHABLE();
609 }
610}
611
Aart Bik29aa0822018-03-08 11:28:00 -0800612void LocationsBuilderX86::VisitVecSaturationSub(HVecSaturationSub* instruction) {
613 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
614}
615
616void InstructionCodeGeneratorX86::VisitVecSaturationSub(HVecSaturationSub* instruction) {
617 LocationSummary* locations = instruction->GetLocations();
618 DCHECK(locations->InAt(0).Equals(locations->Out()));
619 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
620 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
621 switch (instruction->GetPackedType()) {
622 case DataType::Type::kUint8:
623 DCHECK_EQ(16u, instruction->GetVectorLength());
624 __ psubusb(dst, src);
625 break;
626 case DataType::Type::kInt8:
627 DCHECK_EQ(16u, instruction->GetVectorLength());
628 __ psubsb(dst, src);
629 break;
630 case DataType::Type::kUint16:
631 DCHECK_EQ(8u, instruction->GetVectorLength());
632 __ psubusw(dst, src);
633 break;
634 case DataType::Type::kInt16:
635 DCHECK_EQ(8u, instruction->GetVectorLength());
636 __ psubsw(dst, src);
637 break;
638 default:
639 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800640 UNREACHABLE();
641 }
642}
643
644void LocationsBuilderX86::VisitVecMul(HVecMul* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530645 if (CpuHasAvxFeatureFlag()) {
646 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
647 } else {
648 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
649 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800650}
651
652void InstructionCodeGeneratorX86::VisitVecMul(HVecMul* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530653 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Aart Bikf8f5a162017-02-06 15:35:29 -0800654 LocationSummary* locations = instruction->GetLocations();
Aart Bikf8f5a162017-02-06 15:35:29 -0800655 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530656 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -0800657 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530658 DCHECK(cpu_has_avx || other_src == dst);
Aart Bikf8f5a162017-02-06 15:35:29 -0800659 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100660 case DataType::Type::kUint16:
661 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800662 DCHECK_EQ(8u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530663 cpu_has_avx ? __ vpmullw(dst, other_src, src) : __ pmullw(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800664 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100665 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800666 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530667 cpu_has_avx ? __ vpmulld(dst, other_src, src) : __ pmulld(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800668 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100669 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800670 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530671 cpu_has_avx ? __ vmulps(dst, other_src, src) : __ mulps(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800672 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100673 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800674 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530675 cpu_has_avx ? __ vmulpd(dst, other_src, src) : __ mulpd(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800676 break;
677 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800678 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800679 UNREACHABLE();
680 }
681}
682
683void LocationsBuilderX86::VisitVecDiv(HVecDiv* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530684 if (CpuHasAvxFeatureFlag()) {
685 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
686 } else {
687 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
688 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800689}
690
691void InstructionCodeGeneratorX86::VisitVecDiv(HVecDiv* instruction) {
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530692 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Aart Bikf8f5a162017-02-06 15:35:29 -0800693 LocationSummary* locations = instruction->GetLocations();
Aart Bikf8f5a162017-02-06 15:35:29 -0800694 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530695 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -0800696 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530697 DCHECK(cpu_has_avx || other_src == dst);
Aart Bikf8f5a162017-02-06 15:35:29 -0800698 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100699 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800700 DCHECK_EQ(4u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530701 cpu_has_avx ? __ vdivps(dst, other_src, src) : __ divps(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800702 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100703 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800704 DCHECK_EQ(2u, instruction->GetVectorLength());
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530705 cpu_has_avx ? __ vdivpd(dst, other_src, src) : __ divpd(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800706 break;
707 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800708 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800709 UNREACHABLE();
710 }
711}
712
Aart Bikf3e61ee2017-04-12 17:09:20 -0700713void LocationsBuilderX86::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100714 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700715}
716
717void InstructionCodeGeneratorX86::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700718 LocationSummary* locations = instruction->GetLocations();
719 DCHECK(locations->InAt(0).Equals(locations->Out()));
720 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
721 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
722 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100723 case DataType::Type::kUint8:
724 DCHECK_EQ(16u, instruction->GetVectorLength());
725 __ pminub(dst, src);
726 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100727 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700728 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100729 __ pminsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700730 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100731 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100732 DCHECK_EQ(8u, instruction->GetVectorLength());
733 __ pminuw(dst, src);
734 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100735 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700736 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100737 __ pminsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700738 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800739 case DataType::Type::kUint32:
740 DCHECK_EQ(4u, instruction->GetVectorLength());
741 __ pminud(dst, src);
742 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100743 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700744 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800745 __ pminsd(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700746 break;
747 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100748 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700749 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700750 __ minps(dst, src);
751 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100752 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700753 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700754 __ minpd(dst, src);
755 break;
756 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800757 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700758 UNREACHABLE();
759 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700760}
761
762void LocationsBuilderX86::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100763 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700764}
765
766void InstructionCodeGeneratorX86::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700767 LocationSummary* locations = instruction->GetLocations();
768 DCHECK(locations->InAt(0).Equals(locations->Out()));
769 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
770 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
771 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100772 case DataType::Type::kUint8:
773 DCHECK_EQ(16u, instruction->GetVectorLength());
774 __ pmaxub(dst, src);
775 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100776 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700777 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100778 __ pmaxsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700779 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100780 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100781 DCHECK_EQ(8u, instruction->GetVectorLength());
782 __ pmaxuw(dst, src);
783 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100784 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700785 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100786 __ pmaxsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700787 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800788 case DataType::Type::kUint32:
789 DCHECK_EQ(4u, instruction->GetVectorLength());
790 __ pmaxud(dst, src);
791 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100792 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700793 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800794 __ pmaxsd(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700795 break;
796 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100797 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700798 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700799 __ maxps(dst, src);
800 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100801 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700802 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikc8e93c72017-05-10 10:49:22 -0700803 __ maxpd(dst, src);
804 break;
805 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800806 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikc8e93c72017-05-10 10:49:22 -0700807 UNREACHABLE();
808 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700809}
810
Aart Bikf8f5a162017-02-06 15:35:29 -0800811void LocationsBuilderX86::VisitVecAnd(HVecAnd* instruction) {
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530812 if (CpuHasAvxFeatureFlag()) {
813 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
814 } else {
815 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
816 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800817}
818
819void InstructionCodeGeneratorX86::VisitVecAnd(HVecAnd* instruction) {
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530820 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Aart Bikf8f5a162017-02-06 15:35:29 -0800821 LocationSummary* locations = instruction->GetLocations();
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530822 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -0800823 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
824 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530825 DCHECK(cpu_has_avx || other_src == dst);
Aart Bikf8f5a162017-02-06 15:35:29 -0800826 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100827 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100828 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100829 case DataType::Type::kInt8:
830 case DataType::Type::kUint16:
831 case DataType::Type::kInt16:
832 case DataType::Type::kInt32:
833 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800834 DCHECK_LE(2u, instruction->GetVectorLength());
835 DCHECK_LE(instruction->GetVectorLength(), 16u);
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530836 cpu_has_avx ? __ vpand(dst, other_src, src) : __ pand(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800837 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100838 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800839 DCHECK_EQ(4u, instruction->GetVectorLength());
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530840 cpu_has_avx ? __ vandps(dst, other_src, src) : __ andps(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800841 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100842 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800843 DCHECK_EQ(2u, instruction->GetVectorLength());
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530844 cpu_has_avx ? __ vandpd(dst, other_src, src) : __ andpd(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800845 break;
846 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800847 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800848 UNREACHABLE();
849 }
850}
851
852void LocationsBuilderX86::VisitVecAndNot(HVecAndNot* instruction) {
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530853 if (CpuHasAvxFeatureFlag()) {
854 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
855 } else {
856 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
857 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800858}
859
860void InstructionCodeGeneratorX86::VisitVecAndNot(HVecAndNot* instruction) {
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530861 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Aart Bikf8f5a162017-02-06 15:35:29 -0800862 LocationSummary* locations = instruction->GetLocations();
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530863 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -0800864 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
865 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530866 DCHECK(cpu_has_avx || other_src == dst);
Aart Bikf8f5a162017-02-06 15:35:29 -0800867 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100868 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100869 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100870 case DataType::Type::kInt8:
871 case DataType::Type::kUint16:
872 case DataType::Type::kInt16:
873 case DataType::Type::kInt32:
874 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800875 DCHECK_LE(2u, instruction->GetVectorLength());
876 DCHECK_LE(instruction->GetVectorLength(), 16u);
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530877 cpu_has_avx ? __ vpandn(dst, other_src, src) : __ pandn(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800878 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100879 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800880 DCHECK_EQ(4u, instruction->GetVectorLength());
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530881 cpu_has_avx ? __ vandnps(dst, other_src, src) : __ andnps(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800882 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100883 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800884 DCHECK_EQ(2u, instruction->GetVectorLength());
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530885 cpu_has_avx ? __ vandnpd(dst, other_src, src) : __ andnpd(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800886 break;
887 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800888 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800889 UNREACHABLE();
890 }
891}
892
893void LocationsBuilderX86::VisitVecOr(HVecOr* instruction) {
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530894 if (CpuHasAvxFeatureFlag()) {
895 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
896 } else {
897 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
898 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800899}
900
901void InstructionCodeGeneratorX86::VisitVecOr(HVecOr* instruction) {
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530902 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Aart Bikf8f5a162017-02-06 15:35:29 -0800903 LocationSummary* locations = instruction->GetLocations();
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530904 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -0800905 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
906 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530907 DCHECK(cpu_has_avx || other_src == dst);
Aart Bikf8f5a162017-02-06 15:35:29 -0800908 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100909 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100910 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100911 case DataType::Type::kInt8:
912 case DataType::Type::kUint16:
913 case DataType::Type::kInt16:
914 case DataType::Type::kInt32:
915 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800916 DCHECK_LE(2u, instruction->GetVectorLength());
917 DCHECK_LE(instruction->GetVectorLength(), 16u);
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530918 cpu_has_avx ? __ vpor(dst, other_src, src) : __ por(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800919 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100920 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800921 DCHECK_EQ(4u, instruction->GetVectorLength());
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530922 cpu_has_avx ? __ vorps(dst, other_src, src) : __ orps(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800923 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100924 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800925 DCHECK_EQ(2u, instruction->GetVectorLength());
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530926 cpu_has_avx ? __ vorpd(dst, other_src, src) : __ orpd(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800927 break;
928 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800929 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800930 UNREACHABLE();
931 }
932}
933
934void LocationsBuilderX86::VisitVecXor(HVecXor* instruction) {
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530935 if (CpuHasAvxFeatureFlag()) {
936 CreateVecTerOpLocations(GetGraph()->GetAllocator(), instruction);
937 } else {
938 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
939 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800940}
941
942void InstructionCodeGeneratorX86::VisitVecXor(HVecXor* instruction) {
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530943 bool cpu_has_avx = CpuHasAvxFeatureFlag();
Aart Bikf8f5a162017-02-06 15:35:29 -0800944 LocationSummary* locations = instruction->GetLocations();
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530945 XmmRegister other_src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -0800946 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
947 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530948 DCHECK(cpu_has_avx || other_src == dst);
Aart Bikf8f5a162017-02-06 15:35:29 -0800949 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100950 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100951 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100952 case DataType::Type::kInt8:
953 case DataType::Type::kUint16:
954 case DataType::Type::kInt16:
955 case DataType::Type::kInt32:
956 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800957 DCHECK_LE(2u, instruction->GetVectorLength());
958 DCHECK_LE(instruction->GetVectorLength(), 16u);
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530959 cpu_has_avx ? __ vpxor(dst, other_src, src) : __ pxor(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800960 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100961 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800962 DCHECK_EQ(4u, instruction->GetVectorLength());
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530963 cpu_has_avx ? __ vxorps(dst, other_src, src) : __ xorps(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800964 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100965 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800966 DCHECK_EQ(2u, instruction->GetVectorLength());
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530967 cpu_has_avx ? __ vxorpd(dst, other_src, src) : __ xorpd(dst, src);
Aart Bikf8f5a162017-02-06 15:35:29 -0800968 break;
969 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800970 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800971 UNREACHABLE();
972 }
973}
974
975// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100976static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
977 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800978 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100979 case DataType::Type::kUint16:
980 case DataType::Type::kInt16:
981 case DataType::Type::kInt32:
982 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800983 locations->SetInAt(0, Location::RequiresFpuRegister());
984 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
985 locations->SetOut(Location::SameAsFirstInput());
986 break;
987 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800988 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800989 UNREACHABLE();
990 }
991}
992
993void LocationsBuilderX86::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100994 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800995}
996
997void InstructionCodeGeneratorX86::VisitVecShl(HVecShl* instruction) {
998 LocationSummary* locations = instruction->GetLocations();
999 DCHECK(locations->InAt(0).Equals(locations->Out()));
1000 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
1001 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
1002 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001003 case DataType::Type::kUint16:
1004 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -08001005 DCHECK_EQ(8u, instruction->GetVectorLength());
1006 __ psllw(dst, Immediate(static_cast<uint8_t>(value)));
1007 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001008 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001009 DCHECK_EQ(4u, instruction->GetVectorLength());
1010 __ pslld(dst, Immediate(static_cast<uint8_t>(value)));
1011 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001012 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001013 DCHECK_EQ(2u, instruction->GetVectorLength());
1014 __ psllq(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::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001023 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001024}
1025
1026void InstructionCodeGeneratorX86::VisitVecShr(HVecShr* 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 __ psraw(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 __ psrad(dst, Immediate(static_cast<uint8_t>(value)));
1040 break;
1041 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001042 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001043 UNREACHABLE();
1044 }
1045}
1046
1047void LocationsBuilderX86::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001048 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001049}
1050
1051void InstructionCodeGeneratorX86::VisitVecUShr(HVecUShr* instruction) {
1052 LocationSummary* locations = instruction->GetLocations();
1053 DCHECK(locations->InAt(0).Equals(locations->Out()));
1054 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
1055 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
1056 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001057 case DataType::Type::kUint16:
1058 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -08001059 DCHECK_EQ(8u, instruction->GetVectorLength());
1060 __ psrlw(dst, Immediate(static_cast<uint8_t>(value)));
1061 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001062 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001063 DCHECK_EQ(4u, instruction->GetVectorLength());
1064 __ psrld(dst, Immediate(static_cast<uint8_t>(value)));
1065 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001066 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001067 DCHECK_EQ(2u, instruction->GetVectorLength());
1068 __ psrlq(dst, Immediate(static_cast<uint8_t>(value)));
1069 break;
1070 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001071 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001072 UNREACHABLE();
1073 }
1074}
1075
Aart Bik0148de42017-09-05 09:25:01 -07001076void LocationsBuilderX86::VisitVecSetScalars(HVecSetScalars* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001077 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -07001078
1079 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
1080
1081 HInstruction* input = instruction->InputAt(0);
1082 bool is_zero = IsZeroBitPattern(input);
1083
1084 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001085 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -07001086 // Long needs extra temporary to load from register pairs.
1087 if (!is_zero) {
1088 locations->AddTemp(Location::RequiresFpuRegister());
1089 }
1090 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001091 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001092 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001093 case DataType::Type::kInt8:
1094 case DataType::Type::kUint16:
1095 case DataType::Type::kInt16:
1096 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001097 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
1098 : Location::RequiresRegister());
1099 locations->SetOut(Location::RequiresFpuRegister());
1100 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001101 case DataType::Type::kFloat32:
1102 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -07001103 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
1104 : Location::RequiresFpuRegister());
1105 locations->SetOut(Location::RequiresFpuRegister());
1106 break;
1107 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001108 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001109 UNREACHABLE();
1110 }
1111}
1112
1113void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction) {
1114 LocationSummary* locations = instruction->GetLocations();
1115 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
1116
1117 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
1118
1119 // Zero out all other elements first.
Neeraj Solanki48349ad2019-08-05 23:16:56 +05301120 bool cpu_has_avx = CpuHasAvxFeatureFlag();
1121 cpu_has_avx ? __ vxorps(dst, dst, dst) : __ xorps(dst, dst);
Aart Bik0148de42017-09-05 09:25:01 -07001122
1123 // Shorthand for any type of zero.
1124 if (IsZeroBitPattern(instruction->InputAt(0))) {
1125 return;
1126 }
1127
1128 // Set required elements.
1129 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001130 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001131 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001132 case DataType::Type::kInt8:
1133 case DataType::Type::kUint16:
1134 case DataType::Type::kInt16: // TODO: up to here, and?
Aart Bik29aa0822018-03-08 11:28:00 -08001135 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001136 UNREACHABLE();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001137 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001138 DCHECK_EQ(4u, instruction->GetVectorLength());
1139 __ movd(dst, locations->InAt(0).AsRegister<Register>());
1140 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001141 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -07001142 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bikb67f7e22018-01-18 13:29:19 -08001143 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
Aart Bik0148de42017-09-05 09:25:01 -07001144 __ xorps(tmp, tmp);
1145 __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
1146 __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
1147 __ punpckldq(dst, tmp);
1148 break;
1149 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001150 case DataType::Type::kFloat32:
Aart Bik0148de42017-09-05 09:25:01 -07001151 DCHECK_EQ(4u, instruction->GetVectorLength());
1152 __ movss(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1153 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001154 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -07001155 DCHECK_EQ(2u, instruction->GetVectorLength());
1156 __ movsd(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1157 break;
1158 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001159 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bik0148de42017-09-05 09:25:01 -07001160 UNREACHABLE();
1161 }
1162}
1163
Aart Bikdbbac8f2017-09-01 13:06:08 -07001164// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001165static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1166 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001167 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001168 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001169 case DataType::Type::kInt8:
1170 case DataType::Type::kUint16:
1171 case DataType::Type::kInt16:
1172 case DataType::Type::kInt32:
1173 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001174 locations->SetInAt(0, Location::RequiresFpuRegister());
1175 locations->SetInAt(1, Location::RequiresFpuRegister());
1176 locations->SetInAt(2, Location::RequiresFpuRegister());
1177 locations->SetOut(Location::SameAsFirstInput());
1178 break;
1179 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001180 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001181 UNREACHABLE();
1182 }
Artem Serovf34dd202017-04-10 17:41:46 +01001183}
1184
Hans Boehmf5f56c72018-07-13 00:05:27 +00001185void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1186 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001187}
1188
Hans Boehmf5f56c72018-07-13 00:05:27 +00001189void InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1190 // TODO: pmaddwd?
1191 LOG(FATAL) << "No SIMD for " << instruction->GetId();
Aart Bikdbbac8f2017-09-01 13:06:08 -07001192}
1193
1194void LocationsBuilderX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001195 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001196}
1197
1198void InstructionCodeGeneratorX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
1199 // TODO: psadbw for unsigned?
1200 LOG(FATAL) << "No SIMD for " << instruction->GetId();
Artem Serovf34dd202017-04-10 17:41:46 +01001201}
1202
Artem Serovaaac0e32018-08-07 00:52:22 +01001203void LocationsBuilderX86::VisitVecDotProd(HVecDotProd* instruction) {
Alex Light43f2f752019-12-04 17:48:45 +00001204 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
1205 locations->SetInAt(0, Location::RequiresFpuRegister());
1206 locations->SetInAt(1, Location::RequiresFpuRegister());
1207 locations->SetInAt(2, Location::RequiresFpuRegister());
1208 locations->SetOut(Location::SameAsFirstInput());
1209 locations->AddTemp(Location::RequiresFpuRegister());
Artem Serovaaac0e32018-08-07 00:52:22 +01001210}
1211
1212void InstructionCodeGeneratorX86::VisitVecDotProd(HVecDotProd* instruction) {
Alex Light43f2f752019-12-04 17:48:45 +00001213 bool cpu_has_avx = CpuHasAvxFeatureFlag();
1214 LocationSummary* locations = instruction->GetLocations();
1215 XmmRegister acc = locations->InAt(0).AsFpuRegister<XmmRegister>();
1216 XmmRegister left = locations->InAt(1).AsFpuRegister<XmmRegister>();
1217 XmmRegister right = locations->InAt(2).AsFpuRegister<XmmRegister>();
1218 switch (instruction->GetPackedType()) {
1219 case DataType::Type::kInt32: {
1220 DCHECK_EQ(4u, instruction->GetVectorLength());
1221 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1222 if (!cpu_has_avx) {
1223 __ movaps(tmp, right);
1224 __ pmaddwd(tmp, left);
1225 __ paddd(acc, tmp);
1226 } else {
1227 __ vpmaddwd(tmp, left, right);
1228 __ vpaddd(acc, acc, tmp);
1229 }
1230 break;
1231 }
1232 default:
1233 LOG(FATAL) << "Unsupported SIMD Type" << instruction->GetPackedType();
1234 UNREACHABLE();
1235 }
Artem Serovaaac0e32018-08-07 00:52:22 +01001236}
1237
Aart Bikf8f5a162017-02-06 15:35:29 -08001238// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001239static void CreateVecMemLocations(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001240 HVecMemoryOperation* instruction,
1241 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001242 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001243 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001244 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001245 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001246 case DataType::Type::kInt8:
1247 case DataType::Type::kUint16:
1248 case DataType::Type::kInt16:
1249 case DataType::Type::kInt32:
1250 case DataType::Type::kInt64:
1251 case DataType::Type::kFloat32:
1252 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001253 locations->SetInAt(0, Location::RequiresRegister());
1254 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1255 if (is_load) {
1256 locations->SetOut(Location::RequiresFpuRegister());
1257 } else {
1258 locations->SetInAt(2, Location::RequiresFpuRegister());
1259 }
1260 break;
1261 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001262 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001263 UNREACHABLE();
1264 }
1265}
1266
Aart Bik472821b2017-04-27 17:23:51 -07001267// Helper to construct address for vector memory operations.
1268static Address VecAddress(LocationSummary* locations, size_t size, bool is_string_char_at) {
Aart Bikf8f5a162017-02-06 15:35:29 -08001269 Location base = locations->InAt(0);
1270 Location index = locations->InAt(1);
Aart Bikf8f5a162017-02-06 15:35:29 -08001271 ScaleFactor scale = TIMES_1;
1272 switch (size) {
1273 case 2: scale = TIMES_2; break;
1274 case 4: scale = TIMES_4; break;
1275 case 8: scale = TIMES_8; break;
1276 default: break;
1277 }
Aart Bik0148de42017-09-05 09:25:01 -07001278 // Incorporate the string or array offset in the address computation.
Aart Bik472821b2017-04-27 17:23:51 -07001279 uint32_t offset = is_string_char_at
1280 ? mirror::String::ValueOffset().Uint32Value()
1281 : mirror::Array::DataOffset(size).Uint32Value();
Aart Bikf8f5a162017-02-06 15:35:29 -08001282 return CodeGeneratorX86::ArrayAddress(base.AsRegister<Register>(), index, scale, offset);
1283}
1284
1285void LocationsBuilderX86::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001286 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bik472821b2017-04-27 17:23:51 -07001287 // String load requires a temporary for the compressed load.
1288 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1289 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
1290 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001291}
1292
1293void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001294 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001295 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001296 Address address = VecAddress(locations, size, instruction->IsStringCharAt());
1297 XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001298 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1299 switch (instruction->GetPackedType()) {
Vladimir Marko805b6312018-09-05 14:46:06 +01001300 case DataType::Type::kInt16: // (short) s.charAt(.) can yield HVecLoad/Int16/StringCharAt.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001301 case DataType::Type::kUint16:
Aart Bik472821b2017-04-27 17:23:51 -07001302 DCHECK_EQ(8u, instruction->GetVectorLength());
1303 // Special handling of compressed/uncompressed string load.
1304 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1305 NearLabel done, not_compressed;
1306 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1307 // Test compression bit.
1308 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
1309 "Expecting 0=compressed, 1=uncompressed");
1310 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
1311 __ testb(Address(locations->InAt(0).AsRegister<Register>(), count_offset), Immediate(1));
1312 __ j(kNotZero, &not_compressed);
1313 // Zero extend 8 compressed bytes into 8 chars.
Aart Bik0148de42017-09-05 09:25:01 -07001314 __ movsd(reg, VecAddress(locations, 1, instruction->IsStringCharAt()));
Aart Bik472821b2017-04-27 17:23:51 -07001315 __ pxor(tmp, tmp);
1316 __ punpcklbw(reg, tmp);
1317 __ jmp(&done);
1318 // Load 4 direct uncompressed chars.
1319 __ Bind(&not_compressed);
1320 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1321 __ Bind(&done);
1322 return;
1323 }
1324 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001325 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001326 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001327 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001328 case DataType::Type::kInt32:
1329 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001330 DCHECK_LE(2u, instruction->GetVectorLength());
1331 DCHECK_LE(instruction->GetVectorLength(), 16u);
1332 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1333 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001334 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001335 DCHECK_EQ(4u, instruction->GetVectorLength());
1336 is_aligned16 ? __ movaps(reg, address) : __ movups(reg, address);
1337 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001338 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001339 DCHECK_EQ(2u, instruction->GetVectorLength());
1340 is_aligned16 ? __ movapd(reg, address) : __ movupd(reg, address);
1341 break;
1342 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001343 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001344 UNREACHABLE();
1345 }
1346}
1347
1348void LocationsBuilderX86::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001349 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001350}
1351
1352void InstructionCodeGeneratorX86::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001353 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001354 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001355 Address address = VecAddress(locations, size, /*is_string_char_at*/ false);
1356 XmmRegister reg = locations->InAt(2).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001357 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1358 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001359 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001360 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001361 case DataType::Type::kInt8:
1362 case DataType::Type::kUint16:
1363 case DataType::Type::kInt16:
1364 case DataType::Type::kInt32:
1365 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001366 DCHECK_LE(2u, instruction->GetVectorLength());
1367 DCHECK_LE(instruction->GetVectorLength(), 16u);
1368 is_aligned16 ? __ movdqa(address, reg) : __ movdqu(address, reg);
1369 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001370 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001371 DCHECK_EQ(4u, instruction->GetVectorLength());
1372 is_aligned16 ? __ movaps(address, reg) : __ movups(address, reg);
1373 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001374 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001375 DCHECK_EQ(2u, instruction->GetVectorLength());
1376 is_aligned16 ? __ movapd(address, reg) : __ movupd(address, reg);
1377 break;
1378 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001379 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -08001380 UNREACHABLE();
1381 }
1382}
1383
Artem Serov07718842020-02-24 18:51:42 +00001384void LocationsBuilderX86::VisitVecPredSetAll(HVecPredSetAll* instruction) {
1385 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1386 UNREACHABLE();
1387}
1388
1389void InstructionCodeGeneratorX86::VisitVecPredSetAll(HVecPredSetAll* instruction) {
1390 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1391 UNREACHABLE();
1392}
1393
1394void LocationsBuilderX86::VisitVecPredWhile(HVecPredWhile* instruction) {
1395 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1396 UNREACHABLE();
1397}
1398
1399void InstructionCodeGeneratorX86::VisitVecPredWhile(HVecPredWhile* instruction) {
1400 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1401 UNREACHABLE();
1402}
1403
1404void LocationsBuilderX86::VisitVecPredCondition(HVecPredCondition* instruction) {
1405 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1406 UNREACHABLE();
1407}
1408
1409void InstructionCodeGeneratorX86::VisitVecPredCondition(HVecPredCondition* instruction) {
1410 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1411 UNREACHABLE();
1412}
1413
Aart Bikf8f5a162017-02-06 15:35:29 -08001414#undef __
1415
1416} // namespace x86
1417} // namespace art