blob: 886d75e5c77f7bc9331b7f72b7d5f78f7c66f780 [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#ifndef ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_
18#define ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_
19
20// This #include should never be used by compilation, because this header file (nodes_vector.h)
21// is included in the header file nodes.h itself. However it gives editing tools better context.
22#include "nodes.h"
23
24namespace art {
25
26// Memory alignment, represented as an offset relative to a base, where 0 <= offset < base,
27// and base is a power of two. For example, the value Alignment(16, 0) means memory is
28// perfectly aligned at a 16-byte boundary, whereas the value Alignment(16, 4) means
29// memory is always exactly 4 bytes above such a boundary.
30class Alignment {
31 public:
32 Alignment(size_t base, size_t offset) : base_(base), offset_(offset) {
33 DCHECK_LT(offset, base);
34 DCHECK(IsPowerOfTwo(base));
35 }
36
37 // Returns true if memory is "at least" aligned at the given boundary.
38 // Assumes requested base is power of two.
39 bool IsAlignedAt(size_t base) const {
40 DCHECK_NE(0u, base);
41 DCHECK(IsPowerOfTwo(base));
42 return ((offset_ | base_) & (base - 1u)) == 0;
43 }
44
45 std::string ToString() const {
46 return "ALIGN(" + std::to_string(base_) + "," + std::to_string(offset_) + ")";
47 }
48
Aart Bikb79f4ac2017-07-10 10:10:37 -070049 bool operator==(const Alignment& other) const {
50 return base_ == other.base_ && offset_ == other.offset_;
51 }
52
Aart Bikf8f5a162017-02-06 15:35:29 -080053 private:
54 size_t base_;
55 size_t offset_;
56};
57
58//
59// Definitions of abstract vector operations in HIR.
60//
61
62// Abstraction of a vector operation, i.e., an operation that performs
63// GetVectorLength() x GetPackedType() operations simultaneously.
64class HVecOperation : public HVariableInputSizeInstruction {
65 public:
Aart Bikcfa59b42017-08-31 09:08:13 -070066 // A SIMD operation looks like a FPU location.
67 // TODO: we could introduce SIMD types in HIR.
68 static constexpr Primitive::Type kSIMDType = Primitive::kPrimDouble;
69
Aart Bikf8f5a162017-02-06 15:35:29 -080070 HVecOperation(ArenaAllocator* arena,
71 Primitive::Type packed_type,
72 SideEffects side_effects,
73 size_t number_of_inputs,
74 size_t vector_length,
75 uint32_t dex_pc)
76 : HVariableInputSizeInstruction(side_effects,
77 dex_pc,
78 arena,
79 number_of_inputs,
80 kArenaAllocVectorNode),
81 vector_length_(vector_length) {
82 SetPackedField<TypeField>(packed_type);
83 DCHECK_LT(1u, vector_length);
84 }
85
86 // Returns the number of elements packed in a vector.
87 size_t GetVectorLength() const {
88 return vector_length_;
89 }
90
91 // Returns the number of bytes in a full vector.
92 size_t GetVectorNumberOfBytes() const {
93 return vector_length_ * Primitive::ComponentSize(GetPackedType());
94 }
95
Aart Bikcfa59b42017-08-31 09:08:13 -070096 // Returns the type of the vector operation.
Aart Bikf8f5a162017-02-06 15:35:29 -080097 Primitive::Type GetType() const OVERRIDE {
Aart Bikcfa59b42017-08-31 09:08:13 -070098 return kSIMDType;
Aart Bikf8f5a162017-02-06 15:35:29 -080099 }
100
101 // Returns the true component type packed in a vector.
102 Primitive::Type GetPackedType() const {
103 return GetPackedField<TypeField>();
104 }
105
Aart Bikb79f4ac2017-07-10 10:10:37 -0700106 // Assumes vector nodes cannot be moved by default. Each concrete implementation
107 // that can be moved should override this method and return true.
108 bool CanBeMoved() const OVERRIDE { return false; }
109
110 // Tests if all data of a vector node (vector length and packed type) is equal.
111 // Each concrete implementation that adds more fields should test equality of
112 // those fields in its own method *and* call all super methods.
113 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
114 DCHECK(other->IsVecOperation());
115 const HVecOperation* o = other->AsVecOperation();
116 return GetVectorLength() == o->GetVectorLength() && GetPackedType() == o->GetPackedType();
117 }
118
Aart Bikf8f5a162017-02-06 15:35:29 -0800119 DECLARE_ABSTRACT_INSTRUCTION(VecOperation);
120
Aart Bikdb14fcf2017-04-25 15:53:58 -0700121 protected:
Aart Bikf8f5a162017-02-06 15:35:29 -0800122 // Additional packed bits.
123 static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits;
124 static constexpr size_t kFieldTypeSize =
125 MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast));
126 static constexpr size_t kNumberOfVectorOpPackedBits = kFieldType + kFieldTypeSize;
127 static_assert(kNumberOfVectorOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
128 using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>;
129
Aart Bikdb14fcf2017-04-25 15:53:58 -0700130 private:
Aart Bikf8f5a162017-02-06 15:35:29 -0800131 const size_t vector_length_;
132
133 DISALLOW_COPY_AND_ASSIGN(HVecOperation);
134};
135
136// Abstraction of a unary vector operation.
137class HVecUnaryOperation : public HVecOperation {
138 public:
139 HVecUnaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700140 HInstruction* input,
Aart Bikf8f5a162017-02-06 15:35:29 -0800141 Primitive::Type packed_type,
142 size_t vector_length,
143 uint32_t dex_pc)
144 : HVecOperation(arena,
145 packed_type,
146 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700147 /* number_of_inputs */ 1,
Aart Bikf8f5a162017-02-06 15:35:29 -0800148 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700149 dex_pc) {
150 SetRawInputAt(0, input);
151 }
152
153 HInstruction* GetInput() const { return InputAt(0); }
154
Aart Bikf8f5a162017-02-06 15:35:29 -0800155 DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700156
Aart Bikf8f5a162017-02-06 15:35:29 -0800157 private:
158 DISALLOW_COPY_AND_ASSIGN(HVecUnaryOperation);
159};
160
161// Abstraction of a binary vector operation.
162class HVecBinaryOperation : public HVecOperation {
163 public:
164 HVecBinaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700165 HInstruction* left,
166 HInstruction* right,
Aart Bikf8f5a162017-02-06 15:35:29 -0800167 Primitive::Type packed_type,
168 size_t vector_length,
169 uint32_t dex_pc)
170 : HVecOperation(arena,
171 packed_type,
172 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700173 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800174 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700175 dex_pc) {
176 SetRawInputAt(0, left);
177 SetRawInputAt(1, right);
178 }
Artem Serovf34dd202017-04-10 17:41:46 +0100179
180 HInstruction* GetLeft() const { return InputAt(0); }
181 HInstruction* GetRight() const { return InputAt(1); }
182
Aart Bikf8f5a162017-02-06 15:35:29 -0800183 DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700184
Aart Bikf8f5a162017-02-06 15:35:29 -0800185 private:
186 DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation);
187};
188
189// Abstraction of a vector operation that references memory, with an alignment.
190// The Android runtime guarantees at least "component size" alignment for array
191// elements and, thus, vectors.
192class HVecMemoryOperation : public HVecOperation {
193 public:
194 HVecMemoryOperation(ArenaAllocator* arena,
195 Primitive::Type packed_type,
196 SideEffects side_effects,
197 size_t number_of_inputs,
198 size_t vector_length,
199 uint32_t dex_pc)
200 : HVecOperation(arena, packed_type, side_effects, number_of_inputs, vector_length, dex_pc),
Artem Serove1811ed2017-04-27 16:50:47 +0100201 alignment_(Primitive::ComponentSize(packed_type), 0) {
202 DCHECK_GE(number_of_inputs, 2u);
203 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800204
205 void SetAlignment(Alignment alignment) { alignment_ = alignment; }
206
207 Alignment GetAlignment() const { return alignment_; }
208
Artem Serove1811ed2017-04-27 16:50:47 +0100209 HInstruction* GetArray() const { return InputAt(0); }
210 HInstruction* GetIndex() const { return InputAt(1); }
211
Aart Bikb79f4ac2017-07-10 10:10:37 -0700212 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
213 DCHECK(other->IsVecMemoryOperation());
214 const HVecMemoryOperation* o = other->AsVecMemoryOperation();
215 return HVecOperation::InstructionDataEquals(o) && GetAlignment() == o->GetAlignment();
216 }
217
Aart Bikf8f5a162017-02-06 15:35:29 -0800218 DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
219
220 private:
221 Alignment alignment_;
222
223 DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
224};
225
Aart Bikcfa59b42017-08-31 09:08:13 -0700226// Packed type consistency checker ("same vector length" integral types may mix freely).
Aart Bikd58bc322017-05-01 14:49:18 -0700227inline static bool HasConsistentPackedTypes(HInstruction* input, Primitive::Type type) {
Aart Bikcfa59b42017-08-31 09:08:13 -0700228 if (input->IsPhi()) {
229 return input->GetType() == HVecOperation::kSIMDType; // carries SIMD
230 }
Aart Bikd58bc322017-05-01 14:49:18 -0700231 DCHECK(input->IsVecOperation());
232 Primitive::Type input_type = input->AsVecOperation()->GetPackedType();
233 switch (input_type) {
234 case Primitive::kPrimBoolean:
235 case Primitive::kPrimByte:
236 return type == Primitive::kPrimBoolean ||
237 type == Primitive::kPrimByte;
238 case Primitive::kPrimChar:
239 case Primitive::kPrimShort:
240 return type == Primitive::kPrimChar ||
241 type == Primitive::kPrimShort;
242 default:
243 return type == input_type;
244 }
245}
246
Aart Bikf8f5a162017-02-06 15:35:29 -0800247//
Aart Bik8de59162017-04-21 09:42:01 -0700248// Definitions of concrete unary vector operations in HIR.
Aart Bikf8f5a162017-02-06 15:35:29 -0800249//
250
251// Replicates the given scalar into a vector,
252// viz. replicate(x) = [ x, .. , x ].
253class HVecReplicateScalar FINAL : public HVecUnaryOperation {
254 public:
255 HVecReplicateScalar(ArenaAllocator* arena,
256 HInstruction* scalar,
257 Primitive::Type packed_type,
258 size_t vector_length,
259 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700260 : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) {
261 DCHECK(!scalar->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800262 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700263
264 // A replicate needs to stay in place, since SIMD registers are not
265 // kept alive across vector loop boundaries (yet).
266 bool CanBeMoved() const OVERRIDE { return false; }
267
Aart Bikf8f5a162017-02-06 15:35:29 -0800268 DECLARE_INSTRUCTION(VecReplicateScalar);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700269
Aart Bikf8f5a162017-02-06 15:35:29 -0800270 private:
271 DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
272};
273
Aart Bikcfa59b42017-08-31 09:08:13 -0700274// Extracts a particular scalar from the given vector,
275// viz. extract[ x1, .. , xn ] = x_i.
276//
277// TODO: for now only i == 1 case supported.
278class HVecExtractScalar FINAL : public HVecUnaryOperation {
279 public:
280 HVecExtractScalar(ArenaAllocator* arena,
281 HInstruction* input,
282 Primitive::Type packed_type,
283 size_t vector_length,
284 size_t index,
285 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700286 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700287 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikcfa59b42017-08-31 09:08:13 -0700288 DCHECK_LT(index, vector_length);
289 DCHECK_EQ(index, 0u);
290 }
291
292 // Yields a single component in the vector.
293 Primitive::Type GetType() const OVERRIDE {
294 return GetPackedType();
295 }
296
297 // An extract needs to stay in place, since SIMD registers are not
298 // kept alive across vector loop boundaries (yet).
299 bool CanBeMoved() const OVERRIDE { return false; }
300
301 DECLARE_INSTRUCTION(VecExtractScalar);
302
303 private:
304 DISALLOW_COPY_AND_ASSIGN(HVecExtractScalar);
305};
306
307// Reduces the given vector into the first element as sum/min/max,
308// viz. sum-reduce[ x1, .. , xn ] = [ y, ---- ], where y = sum xi
309// and the "-" denotes "don't care" (implementation dependent).
310class HVecReduce FINAL : public HVecUnaryOperation {
311 public:
312 enum ReductionKind {
313 kSum = 1,
314 kMin = 2,
315 kMax = 3
316 };
317
318 HVecReduce(ArenaAllocator* arena,
319 HInstruction* input,
320 Primitive::Type packed_type,
321 size_t vector_length,
322 ReductionKind kind,
323 uint32_t dex_pc = kNoDexPc)
324 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc),
325 kind_(kind) {
326 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik9879d0e2017-08-15 10:51:25 -0700327 }
328
Aart Bikcfa59b42017-08-31 09:08:13 -0700329 ReductionKind GetKind() const { return kind_; }
Aart Bikf8f5a162017-02-06 15:35:29 -0800330
Aart Bikb79f4ac2017-07-10 10:10:37 -0700331 bool CanBeMoved() const OVERRIDE { return true; }
332
Aart Bikcfa59b42017-08-31 09:08:13 -0700333 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
334 DCHECK(other->IsVecReduce());
335 const HVecReduce* o = other->AsVecReduce();
336 return HVecOperation::InstructionDataEquals(o) && GetKind() == o->GetKind();
337 }
338
339 DECLARE_INSTRUCTION(VecReduce);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700340
Aart Bikf8f5a162017-02-06 15:35:29 -0800341 private:
Aart Bikcfa59b42017-08-31 09:08:13 -0700342 const ReductionKind kind_;
343
344 DISALLOW_COPY_AND_ASSIGN(HVecReduce);
Aart Bikf8f5a162017-02-06 15:35:29 -0800345};
346
347// Converts every component in the vector,
348// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
349class HVecCnv FINAL : public HVecUnaryOperation {
350 public:
351 HVecCnv(ArenaAllocator* arena,
352 HInstruction* input,
353 Primitive::Type packed_type,
354 size_t vector_length,
355 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700356 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800357 DCHECK(input->IsVecOperation());
Aart Bikd58bc322017-05-01 14:49:18 -0700358 DCHECK_NE(GetInputType(), GetResultType()); // actual convert
Aart Bikf8f5a162017-02-06 15:35:29 -0800359 }
360
361 Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
362 Primitive::Type GetResultType() const { return GetPackedType(); }
363
Aart Bikb79f4ac2017-07-10 10:10:37 -0700364 bool CanBeMoved() const OVERRIDE { return true; }
365
Aart Bikf8f5a162017-02-06 15:35:29 -0800366 DECLARE_INSTRUCTION(VecCnv);
367
368 private:
369 DISALLOW_COPY_AND_ASSIGN(HVecCnv);
370};
371
372// Negates every component in the vector,
373// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
374class HVecNeg FINAL : public HVecUnaryOperation {
375 public:
376 HVecNeg(ArenaAllocator* arena,
377 HInstruction* input,
378 Primitive::Type packed_type,
379 size_t vector_length,
380 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700381 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700382 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800383 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700384
385 bool CanBeMoved() const OVERRIDE { return true; }
386
Aart Bikf8f5a162017-02-06 15:35:29 -0800387 DECLARE_INSTRUCTION(VecNeg);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700388
Aart Bikf8f5a162017-02-06 15:35:29 -0800389 private:
390 DISALLOW_COPY_AND_ASSIGN(HVecNeg);
391};
392
Aart Bik6daebeb2017-04-03 14:35:41 -0700393// Takes absolute value of every component in the vector,
394// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ].
395class HVecAbs FINAL : public HVecUnaryOperation {
396 public:
397 HVecAbs(ArenaAllocator* arena,
398 HInstruction* input,
399 Primitive::Type packed_type,
400 size_t vector_length,
401 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700402 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700403 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik6daebeb2017-04-03 14:35:41 -0700404 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700405
406 bool CanBeMoved() const OVERRIDE { return true; }
407
Aart Bik6daebeb2017-04-03 14:35:41 -0700408 DECLARE_INSTRUCTION(VecAbs);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700409
Aart Bik6daebeb2017-04-03 14:35:41 -0700410 private:
411 DISALLOW_COPY_AND_ASSIGN(HVecAbs);
412};
413
Aart Bikf8f5a162017-02-06 15:35:29 -0800414// Bitwise- or boolean-nots every component in the vector,
415// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
416// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
417class HVecNot FINAL : public HVecUnaryOperation {
418 public:
419 HVecNot(ArenaAllocator* arena,
420 HInstruction* input,
421 Primitive::Type packed_type,
422 size_t vector_length,
423 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700424 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800425 DCHECK(input->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800426 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700427
428 bool CanBeMoved() const OVERRIDE { return true; }
429
Aart Bikf8f5a162017-02-06 15:35:29 -0800430 DECLARE_INSTRUCTION(VecNot);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700431
Aart Bikf8f5a162017-02-06 15:35:29 -0800432 private:
433 DISALLOW_COPY_AND_ASSIGN(HVecNot);
434};
435
Aart Bik8de59162017-04-21 09:42:01 -0700436//
437// Definitions of concrete binary vector operations in HIR.
438//
439
Aart Bikf8f5a162017-02-06 15:35:29 -0800440// Adds every component in the two vectors,
441// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
442class HVecAdd FINAL : public HVecBinaryOperation {
443 public:
444 HVecAdd(ArenaAllocator* arena,
445 HInstruction* left,
446 HInstruction* right,
447 Primitive::Type packed_type,
448 size_t vector_length,
449 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700450 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700451 DCHECK(HasConsistentPackedTypes(left, packed_type));
452 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800453 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700454
455 bool CanBeMoved() const OVERRIDE { return true; }
456
Aart Bikf8f5a162017-02-06 15:35:29 -0800457 DECLARE_INSTRUCTION(VecAdd);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700458
Aart Bikf8f5a162017-02-06 15:35:29 -0800459 private:
460 DISALLOW_COPY_AND_ASSIGN(HVecAdd);
461};
462
Aart Bikf3e61ee2017-04-12 17:09:20 -0700463// Performs halving add on every component in the two vectors, viz.
464// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
465// or [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ]
466// for signed operands x, y (sign extension) or unsigned operands x, y (zero extension).
467class HVecHalvingAdd FINAL : public HVecBinaryOperation {
468 public:
469 HVecHalvingAdd(ArenaAllocator* arena,
470 HInstruction* left,
471 HInstruction* right,
472 Primitive::Type packed_type,
473 size_t vector_length,
474 bool is_unsigned,
475 bool is_rounded,
476 uint32_t dex_pc = kNoDexPc)
Aart Bikdb14fcf2017-04-25 15:53:58 -0700477 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700478 DCHECK(HasConsistentPackedTypes(left, packed_type));
479 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikdb14fcf2017-04-25 15:53:58 -0700480 SetPackedFlag<kFieldHAddIsUnsigned>(is_unsigned);
481 SetPackedFlag<kFieldHAddIsRounded>(is_rounded);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700482 }
483
Aart Bikdb14fcf2017-04-25 15:53:58 -0700484 bool IsUnsigned() const { return GetPackedFlag<kFieldHAddIsUnsigned>(); }
485 bool IsRounded() const { return GetPackedFlag<kFieldHAddIsRounded>(); }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700486
Aart Bikb79f4ac2017-07-10 10:10:37 -0700487 bool CanBeMoved() const OVERRIDE { return true; }
488
489 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
490 DCHECK(other->IsVecHalvingAdd());
491 const HVecHalvingAdd* o = other->AsVecHalvingAdd();
492 return HVecOperation::InstructionDataEquals(o) &&
493 IsUnsigned() == o->IsUnsigned() &&
494 IsRounded() == o->IsRounded();
495 }
496
Aart Bikf3e61ee2017-04-12 17:09:20 -0700497 DECLARE_INSTRUCTION(VecHalvingAdd);
498
499 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700500 // Additional packed bits.
501 static constexpr size_t kFieldHAddIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
502 static constexpr size_t kFieldHAddIsRounded = kFieldHAddIsUnsigned + 1;
503 static constexpr size_t kNumberOfHAddPackedBits = kFieldHAddIsRounded + 1;
504 static_assert(kNumberOfHAddPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Aart Bikf3e61ee2017-04-12 17:09:20 -0700505
506 DISALLOW_COPY_AND_ASSIGN(HVecHalvingAdd);
507};
508
Aart Bikf8f5a162017-02-06 15:35:29 -0800509// Subtracts every component in the two vectors,
510// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
511class HVecSub FINAL : public HVecBinaryOperation {
512 public:
513 HVecSub(ArenaAllocator* arena,
514 HInstruction* left,
515 HInstruction* right,
516 Primitive::Type packed_type,
517 size_t vector_length,
518 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700519 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700520 DCHECK(HasConsistentPackedTypes(left, packed_type));
521 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800522 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700523
524 bool CanBeMoved() const OVERRIDE { return true; }
525
Aart Bikf8f5a162017-02-06 15:35:29 -0800526 DECLARE_INSTRUCTION(VecSub);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700527
Aart Bikf8f5a162017-02-06 15:35:29 -0800528 private:
529 DISALLOW_COPY_AND_ASSIGN(HVecSub);
530};
531
532// Multiplies every component in the two vectors,
533// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
534class HVecMul FINAL : public HVecBinaryOperation {
535 public:
536 HVecMul(ArenaAllocator* arena,
537 HInstruction* left,
538 HInstruction* right,
539 Primitive::Type packed_type,
540 size_t vector_length,
541 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700542 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700543 DCHECK(HasConsistentPackedTypes(left, packed_type));
544 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800545 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700546
547 bool CanBeMoved() const OVERRIDE { return true; }
548
Aart Bikf8f5a162017-02-06 15:35:29 -0800549 DECLARE_INSTRUCTION(VecMul);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700550
Aart Bikf8f5a162017-02-06 15:35:29 -0800551 private:
552 DISALLOW_COPY_AND_ASSIGN(HVecMul);
553};
554
555// Divides every component in the two vectors,
556// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
557class HVecDiv FINAL : public HVecBinaryOperation {
558 public:
559 HVecDiv(ArenaAllocator* arena,
560 HInstruction* left,
561 HInstruction* right,
562 Primitive::Type packed_type,
563 size_t vector_length,
564 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700565 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700566 DCHECK(HasConsistentPackedTypes(left, packed_type));
567 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800568 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700569
570 bool CanBeMoved() const OVERRIDE { return true; }
571
Aart Bikf8f5a162017-02-06 15:35:29 -0800572 DECLARE_INSTRUCTION(VecDiv);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700573
Aart Bikf8f5a162017-02-06 15:35:29 -0800574 private:
575 DISALLOW_COPY_AND_ASSIGN(HVecDiv);
576};
577
Aart Bikf3e61ee2017-04-12 17:09:20 -0700578// Takes minimum of every component in the two vectors,
579// viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ].
580class HVecMin FINAL : public HVecBinaryOperation {
581 public:
582 HVecMin(ArenaAllocator* arena,
583 HInstruction* left,
584 HInstruction* right,
585 Primitive::Type packed_type,
586 size_t vector_length,
Aart Bikc8e93c72017-05-10 10:49:22 -0700587 bool is_unsigned,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700588 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700589 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700590 DCHECK(HasConsistentPackedTypes(left, packed_type));
591 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700592 SetPackedFlag<kFieldMinOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700593 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700594
595 bool IsUnsigned() const { return GetPackedFlag<kFieldMinOpIsUnsigned>(); }
596
Aart Bikb79f4ac2017-07-10 10:10:37 -0700597 bool CanBeMoved() const OVERRIDE { return true; }
598
599 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
600 DCHECK(other->IsVecMin());
601 const HVecMin* o = other->AsVecMin();
602 return HVecOperation::InstructionDataEquals(o) && IsUnsigned() == o->IsUnsigned();
603 }
604
Aart Bikf3e61ee2017-04-12 17:09:20 -0700605 DECLARE_INSTRUCTION(VecMin);
Aart Bikc8e93c72017-05-10 10:49:22 -0700606
Aart Bikf3e61ee2017-04-12 17:09:20 -0700607 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700608 // Additional packed bits.
609 static constexpr size_t kFieldMinOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
610 static constexpr size_t kNumberOfMinOpPackedBits = kFieldMinOpIsUnsigned + 1;
611 static_assert(kNumberOfMinOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
612
Aart Bikf3e61ee2017-04-12 17:09:20 -0700613 DISALLOW_COPY_AND_ASSIGN(HVecMin);
614};
615
616// Takes maximum of every component in the two vectors,
617// viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ].
618class HVecMax FINAL : public HVecBinaryOperation {
619 public:
620 HVecMax(ArenaAllocator* arena,
621 HInstruction* left,
622 HInstruction* right,
623 Primitive::Type packed_type,
624 size_t vector_length,
Aart Bikc8e93c72017-05-10 10:49:22 -0700625 bool is_unsigned,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700626 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700627 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700628 DCHECK(HasConsistentPackedTypes(left, packed_type));
629 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700630 SetPackedFlag<kFieldMaxOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700631 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700632
633 bool IsUnsigned() const { return GetPackedFlag<kFieldMaxOpIsUnsigned>(); }
634
Aart Bikb79f4ac2017-07-10 10:10:37 -0700635 bool CanBeMoved() const OVERRIDE { return true; }
636
637 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
638 DCHECK(other->IsVecMax());
639 const HVecMax* o = other->AsVecMax();
640 return HVecOperation::InstructionDataEquals(o) && IsUnsigned() == o->IsUnsigned();
641 }
642
Aart Bikf3e61ee2017-04-12 17:09:20 -0700643 DECLARE_INSTRUCTION(VecMax);
Aart Bikc8e93c72017-05-10 10:49:22 -0700644
Aart Bikf3e61ee2017-04-12 17:09:20 -0700645 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700646 // Additional packed bits.
647 static constexpr size_t kFieldMaxOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
648 static constexpr size_t kNumberOfMaxOpPackedBits = kFieldMaxOpIsUnsigned + 1;
649 static_assert(kNumberOfMaxOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
650
Aart Bikf3e61ee2017-04-12 17:09:20 -0700651 DISALLOW_COPY_AND_ASSIGN(HVecMax);
652};
653
Aart Bikf8f5a162017-02-06 15:35:29 -0800654// Bitwise-ands every component in the two vectors,
655// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
656class HVecAnd FINAL : public HVecBinaryOperation {
657 public:
658 HVecAnd(ArenaAllocator* arena,
659 HInstruction* left,
660 HInstruction* right,
661 Primitive::Type packed_type,
662 size_t vector_length,
663 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700664 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800665 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800666 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700667
668 bool CanBeMoved() const OVERRIDE { return true; }
669
Aart Bikf8f5a162017-02-06 15:35:29 -0800670 DECLARE_INSTRUCTION(VecAnd);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700671
Aart Bikf8f5a162017-02-06 15:35:29 -0800672 private:
673 DISALLOW_COPY_AND_ASSIGN(HVecAnd);
674};
675
676// Bitwise-and-nots every component in the two vectors,
677// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
678class HVecAndNot FINAL : public HVecBinaryOperation {
679 public:
680 HVecAndNot(ArenaAllocator* arena,
681 HInstruction* left,
682 HInstruction* right,
683 Primitive::Type packed_type,
684 size_t vector_length,
685 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700686 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800687 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800688 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700689
690 bool CanBeMoved() const OVERRIDE { return true; }
691
Aart Bikf8f5a162017-02-06 15:35:29 -0800692 DECLARE_INSTRUCTION(VecAndNot);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700693
Aart Bikf8f5a162017-02-06 15:35:29 -0800694 private:
695 DISALLOW_COPY_AND_ASSIGN(HVecAndNot);
696};
697
698// Bitwise-ors every component in the two vectors,
699// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
700class HVecOr FINAL : public HVecBinaryOperation {
701 public:
702 HVecOr(ArenaAllocator* arena,
703 HInstruction* left,
704 HInstruction* right,
705 Primitive::Type packed_type,
706 size_t vector_length,
707 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700708 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800709 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800710 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700711
712 bool CanBeMoved() const OVERRIDE { return true; }
713
Aart Bikf8f5a162017-02-06 15:35:29 -0800714 DECLARE_INSTRUCTION(VecOr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700715
Aart Bikf8f5a162017-02-06 15:35:29 -0800716 private:
717 DISALLOW_COPY_AND_ASSIGN(HVecOr);
718};
719
720// Bitwise-xors every component in the two vectors,
721// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
722class HVecXor FINAL : public HVecBinaryOperation {
723 public:
724 HVecXor(ArenaAllocator* arena,
725 HInstruction* left,
726 HInstruction* right,
727 Primitive::Type packed_type,
728 size_t vector_length,
729 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700730 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800731 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800732 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700733
734 bool CanBeMoved() const OVERRIDE { return true; }
735
Aart Bikf8f5a162017-02-06 15:35:29 -0800736 DECLARE_INSTRUCTION(VecXor);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700737
Aart Bikf8f5a162017-02-06 15:35:29 -0800738 private:
739 DISALLOW_COPY_AND_ASSIGN(HVecXor);
740};
741
742// Logically shifts every component in the vector left by the given distance,
743// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
744class HVecShl FINAL : public HVecBinaryOperation {
745 public:
746 HVecShl(ArenaAllocator* arena,
747 HInstruction* left,
748 HInstruction* right,
749 Primitive::Type packed_type,
750 size_t vector_length,
751 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700752 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700753 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800754 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700755
756 bool CanBeMoved() const OVERRIDE { return true; }
757
Aart Bikf8f5a162017-02-06 15:35:29 -0800758 DECLARE_INSTRUCTION(VecShl);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700759
Aart Bikf8f5a162017-02-06 15:35:29 -0800760 private:
761 DISALLOW_COPY_AND_ASSIGN(HVecShl);
762};
763
764// Arithmetically shifts every component in the vector right by the given distance,
765// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
766class HVecShr FINAL : public HVecBinaryOperation {
767 public:
768 HVecShr(ArenaAllocator* arena,
769 HInstruction* left,
770 HInstruction* right,
771 Primitive::Type packed_type,
772 size_t vector_length,
773 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700774 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700775 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800776 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700777
778 bool CanBeMoved() const OVERRIDE { return true; }
779
Aart Bikf8f5a162017-02-06 15:35:29 -0800780 DECLARE_INSTRUCTION(VecShr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700781
Aart Bikf8f5a162017-02-06 15:35:29 -0800782 private:
783 DISALLOW_COPY_AND_ASSIGN(HVecShr);
784};
785
786// Logically shifts every component in the vector right by the given distance,
787// viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
788class HVecUShr FINAL : public HVecBinaryOperation {
789 public:
790 HVecUShr(ArenaAllocator* arena,
791 HInstruction* left,
792 HInstruction* right,
793 Primitive::Type packed_type,
794 size_t vector_length,
795 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700796 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700797 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800798 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700799
800 bool CanBeMoved() const OVERRIDE { return true; }
801
Aart Bikf8f5a162017-02-06 15:35:29 -0800802 DECLARE_INSTRUCTION(VecUShr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700803
Aart Bikf8f5a162017-02-06 15:35:29 -0800804 private:
805 DISALLOW_COPY_AND_ASSIGN(HVecUShr);
806};
807
Aart Bik8de59162017-04-21 09:42:01 -0700808//
809// Definitions of concrete miscellaneous vector operations in HIR.
810//
811
812// Assigns the given scalar elements to a vector,
Aart Bikcfa59b42017-08-31 09:08:13 -0700813// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ] if n == m,
814// set( array(x1, .., xm) ) = [ x1, .. , xm, 0, .., 0 ] if m < n.
Aart Bik8de59162017-04-21 09:42:01 -0700815class HVecSetScalars FINAL : public HVecOperation {
Aart Bikcfa59b42017-08-31 09:08:13 -0700816 public:
Aart Bik8de59162017-04-21 09:42:01 -0700817 HVecSetScalars(ArenaAllocator* arena,
818 HInstruction** scalars, // array
819 Primitive::Type packed_type,
820 size_t vector_length,
Aart Bikcfa59b42017-08-31 09:08:13 -0700821 size_t number_of_scalars,
Aart Bik8de59162017-04-21 09:42:01 -0700822 uint32_t dex_pc = kNoDexPc)
823 : HVecOperation(arena,
824 packed_type,
825 SideEffects::None(),
Aart Bikcfa59b42017-08-31 09:08:13 -0700826 number_of_scalars,
Aart Bik8de59162017-04-21 09:42:01 -0700827 vector_length,
828 dex_pc) {
Aart Bikcfa59b42017-08-31 09:08:13 -0700829 for (size_t i = 0; i < number_of_scalars; i++) {
Aart Bik8de59162017-04-21 09:42:01 -0700830 DCHECK(!scalars[i]->IsVecOperation());
831 SetRawInputAt(0, scalars[i]);
832 }
833 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700834
835 // Setting scalars needs to stay in place, since SIMD registers are not
836 // kept alive across vector loop boundaries (yet).
837 bool CanBeMoved() const OVERRIDE { return false; }
838
Aart Bik8de59162017-04-21 09:42:01 -0700839 DECLARE_INSTRUCTION(VecSetScalars);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700840
Aart Bik8de59162017-04-21 09:42:01 -0700841 private:
842 DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
843};
844
Artem Serovf34dd202017-04-10 17:41:46 +0100845// Multiplies every component in the two vectors, adds the result vector to the accumulator vector.
846// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] =
847// [ acc1 + x1 * y1, .. , accn + xn * yn ].
848class HVecMultiplyAccumulate FINAL : public HVecOperation {
849 public:
850 HVecMultiplyAccumulate(ArenaAllocator* arena,
851 InstructionKind op,
852 HInstruction* accumulator,
853 HInstruction* mul_left,
854 HInstruction* mul_right,
855 Primitive::Type packed_type,
856 size_t vector_length,
857 uint32_t dex_pc = kNoDexPc)
858 : HVecOperation(arena,
859 packed_type,
860 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700861 /* number_of_inputs */ 3,
Artem Serovf34dd202017-04-10 17:41:46 +0100862 vector_length,
863 dex_pc),
864 op_kind_(op) {
865 DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
Aart Bikd58bc322017-05-01 14:49:18 -0700866 DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
867 DCHECK(HasConsistentPackedTypes(mul_left, packed_type));
868 DCHECK(HasConsistentPackedTypes(mul_right, packed_type));
Artem Serovf34dd202017-04-10 17:41:46 +0100869 SetRawInputAt(kInputAccumulatorIndex, accumulator);
870 SetRawInputAt(kInputMulLeftIndex, mul_left);
871 SetRawInputAt(kInputMulRightIndex, mul_right);
872 }
873
874 static constexpr int kInputAccumulatorIndex = 0;
875 static constexpr int kInputMulLeftIndex = 1;
876 static constexpr int kInputMulRightIndex = 2;
877
Nicolas Geoffray9858bf72017-07-08 12:34:55 +0000878 bool CanBeMoved() const OVERRIDE { return true; }
879
Artem Serovf34dd202017-04-10 17:41:46 +0100880 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
Aart Bikb79f4ac2017-07-10 10:10:37 -0700881 DCHECK(other->IsVecMultiplyAccumulate());
882 const HVecMultiplyAccumulate* o = other->AsVecMultiplyAccumulate();
883 return HVecOperation::InstructionDataEquals(o) && GetOpKind() == o->GetOpKind();
Artem Serovf34dd202017-04-10 17:41:46 +0100884 }
885
886 InstructionKind GetOpKind() const { return op_kind_; }
887
888 DECLARE_INSTRUCTION(VecMultiplyAccumulate);
889
890 private:
891 // Indicates if this is a MADD or MSUB.
892 const InstructionKind op_kind_;
893
894 DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate);
895};
896
Aart Bikf8f5a162017-02-06 15:35:29 -0800897// Loads a vector from memory, viz. load(mem, 1)
898// yield the vector [ mem(1), .. , mem(n) ].
899class HVecLoad FINAL : public HVecMemoryOperation {
900 public:
901 HVecLoad(ArenaAllocator* arena,
902 HInstruction* base,
903 HInstruction* index,
904 Primitive::Type packed_type,
905 size_t vector_length,
Aart Bikdb14fcf2017-04-25 15:53:58 -0700906 bool is_string_char_at,
Aart Bikf8f5a162017-02-06 15:35:29 -0800907 uint32_t dex_pc = kNoDexPc)
908 : HVecMemoryOperation(arena,
909 packed_type,
910 SideEffects::ArrayReadOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700911 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800912 vector_length,
913 dex_pc) {
914 SetRawInputAt(0, base);
915 SetRawInputAt(1, index);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700916 SetPackedFlag<kFieldIsStringCharAt>(is_string_char_at);
Aart Bikf8f5a162017-02-06 15:35:29 -0800917 }
Aart Bikdb14fcf2017-04-25 15:53:58 -0700918
919 bool IsStringCharAt() const { return GetPackedFlag<kFieldIsStringCharAt>(); }
920
Aart Bikb79f4ac2017-07-10 10:10:37 -0700921 bool CanBeMoved() const OVERRIDE { return true; }
922
923 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
924 DCHECK(other->IsVecLoad());
925 const HVecLoad* o = other->AsVecLoad();
926 return HVecMemoryOperation::InstructionDataEquals(o) && IsStringCharAt() == o->IsStringCharAt();
927 }
928
929 DECLARE_INSTRUCTION(VecLoad);
930
Aart Bikf8f5a162017-02-06 15:35:29 -0800931 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700932 // Additional packed bits.
933 static constexpr size_t kFieldIsStringCharAt = HVecOperation::kNumberOfVectorOpPackedBits;
934 static constexpr size_t kNumberOfVecLoadPackedBits = kFieldIsStringCharAt + 1;
935 static_assert(kNumberOfVecLoadPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
936
Aart Bikf8f5a162017-02-06 15:35:29 -0800937 DISALLOW_COPY_AND_ASSIGN(HVecLoad);
938};
939
940// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
941// sets mem(1) = x1, .. , mem(n) = xn.
942class HVecStore FINAL : public HVecMemoryOperation {
943 public:
944 HVecStore(ArenaAllocator* arena,
945 HInstruction* base,
946 HInstruction* index,
947 HInstruction* value,
948 Primitive::Type packed_type,
949 size_t vector_length,
950 uint32_t dex_pc = kNoDexPc)
951 : HVecMemoryOperation(arena,
952 packed_type,
953 SideEffects::ArrayWriteOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700954 /* number_of_inputs */ 3,
Aart Bikf8f5a162017-02-06 15:35:29 -0800955 vector_length,
956 dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700957 DCHECK(HasConsistentPackedTypes(value, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800958 SetRawInputAt(0, base);
959 SetRawInputAt(1, index);
960 SetRawInputAt(2, value);
961 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700962
963 // A store needs to stay in place.
964 bool CanBeMoved() const OVERRIDE { return false; }
965
Aart Bikf8f5a162017-02-06 15:35:29 -0800966 DECLARE_INSTRUCTION(VecStore);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700967
Aart Bikf8f5a162017-02-06 15:35:29 -0800968 private:
969 DISALLOW_COPY_AND_ASSIGN(HVecStore);
970};
971
972} // namespace art
973
974#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_