blob: 5dbe29b4faa63804747e06028b24069e4568ae29 [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
49 private:
50 size_t base_;
51 size_t offset_;
52};
53
54//
55// Definitions of abstract vector operations in HIR.
56//
57
58// Abstraction of a vector operation, i.e., an operation that performs
59// GetVectorLength() x GetPackedType() operations simultaneously.
60class HVecOperation : public HVariableInputSizeInstruction {
61 public:
62 HVecOperation(ArenaAllocator* arena,
63 Primitive::Type packed_type,
64 SideEffects side_effects,
65 size_t number_of_inputs,
66 size_t vector_length,
67 uint32_t dex_pc)
68 : HVariableInputSizeInstruction(side_effects,
69 dex_pc,
70 arena,
71 number_of_inputs,
72 kArenaAllocVectorNode),
73 vector_length_(vector_length) {
74 SetPackedField<TypeField>(packed_type);
75 DCHECK_LT(1u, vector_length);
76 }
77
78 // Returns the number of elements packed in a vector.
79 size_t GetVectorLength() const {
80 return vector_length_;
81 }
82
83 // Returns the number of bytes in a full vector.
84 size_t GetVectorNumberOfBytes() const {
85 return vector_length_ * Primitive::ComponentSize(GetPackedType());
86 }
87
88 // Returns the type of the vector operation: a SIMD operation looks like a FPU location.
89 // TODO: we could introduce SIMD types in HIR.
90 Primitive::Type GetType() const OVERRIDE {
91 return Primitive::kPrimDouble;
92 }
93
94 // Returns the true component type packed in a vector.
95 Primitive::Type GetPackedType() const {
96 return GetPackedField<TypeField>();
97 }
98
99 DECLARE_ABSTRACT_INSTRUCTION(VecOperation);
100
Aart Bikdb14fcf2017-04-25 15:53:58 -0700101 protected:
Aart Bikf8f5a162017-02-06 15:35:29 -0800102 // Additional packed bits.
103 static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits;
104 static constexpr size_t kFieldTypeSize =
105 MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast));
106 static constexpr size_t kNumberOfVectorOpPackedBits = kFieldType + kFieldTypeSize;
107 static_assert(kNumberOfVectorOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
108 using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>;
109
Aart Bikdb14fcf2017-04-25 15:53:58 -0700110 private:
Aart Bikf8f5a162017-02-06 15:35:29 -0800111 const size_t vector_length_;
112
113 DISALLOW_COPY_AND_ASSIGN(HVecOperation);
114};
115
116// Abstraction of a unary vector operation.
117class HVecUnaryOperation : public HVecOperation {
118 public:
119 HVecUnaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700120 HInstruction* input,
Aart Bikf8f5a162017-02-06 15:35:29 -0800121 Primitive::Type packed_type,
122 size_t vector_length,
123 uint32_t dex_pc)
124 : HVecOperation(arena,
125 packed_type,
126 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700127 /* number_of_inputs */ 1,
Aart Bikf8f5a162017-02-06 15:35:29 -0800128 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700129 dex_pc) {
130 SetRawInputAt(0, input);
131 }
132
133 HInstruction* GetInput() const { return InputAt(0); }
134
Aart Bikf8f5a162017-02-06 15:35:29 -0800135 DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700136
Aart Bikf8f5a162017-02-06 15:35:29 -0800137 private:
138 DISALLOW_COPY_AND_ASSIGN(HVecUnaryOperation);
139};
140
141// Abstraction of a binary vector operation.
142class HVecBinaryOperation : public HVecOperation {
143 public:
144 HVecBinaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700145 HInstruction* left,
146 HInstruction* right,
Aart Bikf8f5a162017-02-06 15:35:29 -0800147 Primitive::Type packed_type,
148 size_t vector_length,
149 uint32_t dex_pc)
150 : HVecOperation(arena,
151 packed_type,
152 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700153 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800154 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700155 dex_pc) {
156 SetRawInputAt(0, left);
157 SetRawInputAt(1, right);
158 }
Artem Serovf34dd202017-04-10 17:41:46 +0100159
160 HInstruction* GetLeft() const { return InputAt(0); }
161 HInstruction* GetRight() const { return InputAt(1); }
162
Aart Bikf8f5a162017-02-06 15:35:29 -0800163 DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700164
Aart Bikf8f5a162017-02-06 15:35:29 -0800165 private:
166 DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation);
167};
168
169// Abstraction of a vector operation that references memory, with an alignment.
170// The Android runtime guarantees at least "component size" alignment for array
171// elements and, thus, vectors.
172class HVecMemoryOperation : public HVecOperation {
173 public:
174 HVecMemoryOperation(ArenaAllocator* arena,
175 Primitive::Type packed_type,
176 SideEffects side_effects,
177 size_t number_of_inputs,
178 size_t vector_length,
179 uint32_t dex_pc)
180 : HVecOperation(arena, packed_type, side_effects, number_of_inputs, vector_length, dex_pc),
Artem Serove1811ed2017-04-27 16:50:47 +0100181 alignment_(Primitive::ComponentSize(packed_type), 0) {
182 DCHECK_GE(number_of_inputs, 2u);
183 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800184
185 void SetAlignment(Alignment alignment) { alignment_ = alignment; }
186
187 Alignment GetAlignment() const { return alignment_; }
188
Artem Serove1811ed2017-04-27 16:50:47 +0100189 HInstruction* GetArray() const { return InputAt(0); }
190 HInstruction* GetIndex() const { return InputAt(1); }
191
Aart Bikf8f5a162017-02-06 15:35:29 -0800192 DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
193
194 private:
195 Alignment alignment_;
196
197 DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
198};
199
Aart Bikd58bc322017-05-01 14:49:18 -0700200// Packed type consistency checker (same vector length integral types may mix freely).
201inline static bool HasConsistentPackedTypes(HInstruction* input, Primitive::Type type) {
202 DCHECK(input->IsVecOperation());
203 Primitive::Type input_type = input->AsVecOperation()->GetPackedType();
204 switch (input_type) {
205 case Primitive::kPrimBoolean:
206 case Primitive::kPrimByte:
207 return type == Primitive::kPrimBoolean ||
208 type == Primitive::kPrimByte;
209 case Primitive::kPrimChar:
210 case Primitive::kPrimShort:
211 return type == Primitive::kPrimChar ||
212 type == Primitive::kPrimShort;
213 default:
214 return type == input_type;
215 }
216}
217
Aart Bikf8f5a162017-02-06 15:35:29 -0800218//
Aart Bik8de59162017-04-21 09:42:01 -0700219// Definitions of concrete unary vector operations in HIR.
Aart Bikf8f5a162017-02-06 15:35:29 -0800220//
221
222// Replicates the given scalar into a vector,
223// viz. replicate(x) = [ x, .. , x ].
224class HVecReplicateScalar FINAL : public HVecUnaryOperation {
225 public:
226 HVecReplicateScalar(ArenaAllocator* arena,
227 HInstruction* scalar,
228 Primitive::Type packed_type,
229 size_t vector_length,
230 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700231 : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) {
232 DCHECK(!scalar->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800233 }
234 DECLARE_INSTRUCTION(VecReplicateScalar);
235 private:
236 DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
237};
238
Aart Bikf8f5a162017-02-06 15:35:29 -0800239// Sum-reduces the given vector into a shorter vector (m < n) or scalar (m = 1),
240// viz. sum-reduce[ x1, .. , xn ] = [ y1, .., ym ], where yi = sum_j x_j.
241class HVecSumReduce FINAL : public HVecUnaryOperation {
242 HVecSumReduce(ArenaAllocator* arena,
243 HInstruction* input,
244 Primitive::Type packed_type,
245 size_t vector_length,
246 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700247 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700248 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800249 }
250
251 // TODO: probably integral promotion
252 Primitive::Type GetType() const OVERRIDE { return GetPackedType(); }
253
254 DECLARE_INSTRUCTION(VecSumReduce);
255 private:
256 DISALLOW_COPY_AND_ASSIGN(HVecSumReduce);
257};
258
259// Converts every component in the vector,
260// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
261class HVecCnv FINAL : public HVecUnaryOperation {
262 public:
263 HVecCnv(ArenaAllocator* arena,
264 HInstruction* input,
265 Primitive::Type packed_type,
266 size_t vector_length,
267 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700268 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800269 DCHECK(input->IsVecOperation());
Aart Bikd58bc322017-05-01 14:49:18 -0700270 DCHECK_NE(GetInputType(), GetResultType()); // actual convert
Aart Bikf8f5a162017-02-06 15:35:29 -0800271 }
272
273 Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
274 Primitive::Type GetResultType() const { return GetPackedType(); }
275
276 DECLARE_INSTRUCTION(VecCnv);
277
278 private:
279 DISALLOW_COPY_AND_ASSIGN(HVecCnv);
280};
281
282// Negates every component in the vector,
283// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
284class HVecNeg FINAL : public HVecUnaryOperation {
285 public:
286 HVecNeg(ArenaAllocator* arena,
287 HInstruction* input,
288 Primitive::Type packed_type,
289 size_t vector_length,
290 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700291 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700292 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800293 }
294 DECLARE_INSTRUCTION(VecNeg);
295 private:
296 DISALLOW_COPY_AND_ASSIGN(HVecNeg);
297};
298
Aart Bik6daebeb2017-04-03 14:35:41 -0700299// Takes absolute value of every component in the vector,
300// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ].
301class HVecAbs FINAL : public HVecUnaryOperation {
302 public:
303 HVecAbs(ArenaAllocator* arena,
304 HInstruction* input,
305 Primitive::Type packed_type,
306 size_t vector_length,
307 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700308 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700309 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik6daebeb2017-04-03 14:35:41 -0700310 }
311 DECLARE_INSTRUCTION(VecAbs);
312 private:
313 DISALLOW_COPY_AND_ASSIGN(HVecAbs);
314};
315
Aart Bikf8f5a162017-02-06 15:35:29 -0800316// Bitwise- or boolean-nots every component in the vector,
317// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
318// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
319class HVecNot FINAL : public HVecUnaryOperation {
320 public:
321 HVecNot(ArenaAllocator* arena,
322 HInstruction* input,
323 Primitive::Type packed_type,
324 size_t vector_length,
325 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700326 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800327 DCHECK(input->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800328 }
329 DECLARE_INSTRUCTION(VecNot);
330 private:
331 DISALLOW_COPY_AND_ASSIGN(HVecNot);
332};
333
Aart Bik8de59162017-04-21 09:42:01 -0700334//
335// Definitions of concrete binary vector operations in HIR.
336//
337
Aart Bikf8f5a162017-02-06 15:35:29 -0800338// Adds every component in the two vectors,
339// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
340class HVecAdd FINAL : public HVecBinaryOperation {
341 public:
342 HVecAdd(ArenaAllocator* arena,
343 HInstruction* left,
344 HInstruction* right,
345 Primitive::Type packed_type,
346 size_t vector_length,
347 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700348 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700349 DCHECK(HasConsistentPackedTypes(left, packed_type));
350 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800351 }
352 DECLARE_INSTRUCTION(VecAdd);
353 private:
354 DISALLOW_COPY_AND_ASSIGN(HVecAdd);
355};
356
Aart Bikf3e61ee2017-04-12 17:09:20 -0700357// Performs halving add on every component in the two vectors, viz.
358// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
359// or [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ]
360// for signed operands x, y (sign extension) or unsigned operands x, y (zero extension).
361class HVecHalvingAdd FINAL : public HVecBinaryOperation {
362 public:
363 HVecHalvingAdd(ArenaAllocator* arena,
364 HInstruction* left,
365 HInstruction* right,
366 Primitive::Type packed_type,
367 size_t vector_length,
368 bool is_unsigned,
369 bool is_rounded,
370 uint32_t dex_pc = kNoDexPc)
Aart Bikdb14fcf2017-04-25 15:53:58 -0700371 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700372 DCHECK(HasConsistentPackedTypes(left, packed_type));
373 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikdb14fcf2017-04-25 15:53:58 -0700374 SetPackedFlag<kFieldHAddIsUnsigned>(is_unsigned);
375 SetPackedFlag<kFieldHAddIsRounded>(is_rounded);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700376 }
377
Aart Bikdb14fcf2017-04-25 15:53:58 -0700378 bool IsUnsigned() const { return GetPackedFlag<kFieldHAddIsUnsigned>(); }
379 bool IsRounded() const { return GetPackedFlag<kFieldHAddIsRounded>(); }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700380
381 DECLARE_INSTRUCTION(VecHalvingAdd);
382
383 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700384 // Additional packed bits.
385 static constexpr size_t kFieldHAddIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
386 static constexpr size_t kFieldHAddIsRounded = kFieldHAddIsUnsigned + 1;
387 static constexpr size_t kNumberOfHAddPackedBits = kFieldHAddIsRounded + 1;
388 static_assert(kNumberOfHAddPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Aart Bikf3e61ee2017-04-12 17:09:20 -0700389
390 DISALLOW_COPY_AND_ASSIGN(HVecHalvingAdd);
391};
392
Aart Bikf8f5a162017-02-06 15:35:29 -0800393// Subtracts every component in the two vectors,
394// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
395class HVecSub FINAL : public HVecBinaryOperation {
396 public:
397 HVecSub(ArenaAllocator* arena,
398 HInstruction* left,
399 HInstruction* right,
400 Primitive::Type packed_type,
401 size_t vector_length,
402 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700403 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700404 DCHECK(HasConsistentPackedTypes(left, packed_type));
405 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800406 }
407 DECLARE_INSTRUCTION(VecSub);
408 private:
409 DISALLOW_COPY_AND_ASSIGN(HVecSub);
410};
411
412// Multiplies every component in the two vectors,
413// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
414class HVecMul FINAL : public HVecBinaryOperation {
415 public:
416 HVecMul(ArenaAllocator* arena,
417 HInstruction* left,
418 HInstruction* right,
419 Primitive::Type packed_type,
420 size_t vector_length,
421 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700422 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700423 DCHECK(HasConsistentPackedTypes(left, packed_type));
424 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800425 }
426 DECLARE_INSTRUCTION(VecMul);
427 private:
428 DISALLOW_COPY_AND_ASSIGN(HVecMul);
429};
430
431// Divides every component in the two vectors,
432// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
433class HVecDiv FINAL : public HVecBinaryOperation {
434 public:
435 HVecDiv(ArenaAllocator* arena,
436 HInstruction* left,
437 HInstruction* right,
438 Primitive::Type packed_type,
439 size_t vector_length,
440 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700441 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700442 DCHECK(HasConsistentPackedTypes(left, packed_type));
443 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800444 }
445 DECLARE_INSTRUCTION(VecDiv);
446 private:
447 DISALLOW_COPY_AND_ASSIGN(HVecDiv);
448};
449
Aart Bikf3e61ee2017-04-12 17:09:20 -0700450// Takes minimum of every component in the two vectors,
451// viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ].
452class HVecMin FINAL : public HVecBinaryOperation {
453 public:
454 HVecMin(ArenaAllocator* arena,
455 HInstruction* left,
456 HInstruction* right,
457 Primitive::Type packed_type,
458 size_t vector_length,
Aart Bikc8e93c72017-05-10 10:49:22 -0700459 bool is_unsigned,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700460 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700461 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700462 DCHECK(HasConsistentPackedTypes(left, packed_type));
463 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700464 SetPackedFlag<kFieldMinOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700465 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700466
467 bool IsUnsigned() const { return GetPackedFlag<kFieldMinOpIsUnsigned>(); }
468
Aart Bikf3e61ee2017-04-12 17:09:20 -0700469 DECLARE_INSTRUCTION(VecMin);
Aart Bikc8e93c72017-05-10 10:49:22 -0700470
Aart Bikf3e61ee2017-04-12 17:09:20 -0700471 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700472 // Additional packed bits.
473 static constexpr size_t kFieldMinOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
474 static constexpr size_t kNumberOfMinOpPackedBits = kFieldMinOpIsUnsigned + 1;
475 static_assert(kNumberOfMinOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
476
Aart Bikf3e61ee2017-04-12 17:09:20 -0700477 DISALLOW_COPY_AND_ASSIGN(HVecMin);
478};
479
480// Takes maximum of every component in the two vectors,
481// viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ].
482class HVecMax FINAL : public HVecBinaryOperation {
483 public:
484 HVecMax(ArenaAllocator* arena,
485 HInstruction* left,
486 HInstruction* right,
487 Primitive::Type packed_type,
488 size_t vector_length,
Aart Bikc8e93c72017-05-10 10:49:22 -0700489 bool is_unsigned,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700490 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700491 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700492 DCHECK(HasConsistentPackedTypes(left, packed_type));
493 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700494 SetPackedFlag<kFieldMaxOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700495 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700496
497 bool IsUnsigned() const { return GetPackedFlag<kFieldMaxOpIsUnsigned>(); }
498
Aart Bikf3e61ee2017-04-12 17:09:20 -0700499 DECLARE_INSTRUCTION(VecMax);
Aart Bikc8e93c72017-05-10 10:49:22 -0700500
Aart Bikf3e61ee2017-04-12 17:09:20 -0700501 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700502 // Additional packed bits.
503 static constexpr size_t kFieldMaxOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
504 static constexpr size_t kNumberOfMaxOpPackedBits = kFieldMaxOpIsUnsigned + 1;
505 static_assert(kNumberOfMaxOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
506
Aart Bikf3e61ee2017-04-12 17:09:20 -0700507 DISALLOW_COPY_AND_ASSIGN(HVecMax);
508};
509
Aart Bikf8f5a162017-02-06 15:35:29 -0800510// Bitwise-ands every component in the two vectors,
511// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
512class HVecAnd FINAL : public HVecBinaryOperation {
513 public:
514 HVecAnd(ArenaAllocator* arena,
515 HInstruction* left,
516 HInstruction* right,
517 Primitive::Type packed_type,
518 size_t vector_length,
519 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700520 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800521 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800522 }
523 DECLARE_INSTRUCTION(VecAnd);
524 private:
525 DISALLOW_COPY_AND_ASSIGN(HVecAnd);
526};
527
528// Bitwise-and-nots every component in the two vectors,
529// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
530class HVecAndNot FINAL : public HVecBinaryOperation {
531 public:
532 HVecAndNot(ArenaAllocator* arena,
533 HInstruction* left,
534 HInstruction* right,
535 Primitive::Type packed_type,
536 size_t vector_length,
537 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700538 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800539 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800540 }
541 DECLARE_INSTRUCTION(VecAndNot);
542 private:
543 DISALLOW_COPY_AND_ASSIGN(HVecAndNot);
544};
545
546// Bitwise-ors every component in the two vectors,
547// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
548class HVecOr FINAL : public HVecBinaryOperation {
549 public:
550 HVecOr(ArenaAllocator* arena,
551 HInstruction* left,
552 HInstruction* right,
553 Primitive::Type packed_type,
554 size_t vector_length,
555 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700556 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800557 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800558 }
559 DECLARE_INSTRUCTION(VecOr);
560 private:
561 DISALLOW_COPY_AND_ASSIGN(HVecOr);
562};
563
564// Bitwise-xors every component in the two vectors,
565// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
566class HVecXor FINAL : public HVecBinaryOperation {
567 public:
568 HVecXor(ArenaAllocator* arena,
569 HInstruction* left,
570 HInstruction* right,
571 Primitive::Type packed_type,
572 size_t vector_length,
573 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700574 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800575 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800576 }
577 DECLARE_INSTRUCTION(VecXor);
578 private:
579 DISALLOW_COPY_AND_ASSIGN(HVecXor);
580};
581
582// Logically shifts every component in the vector left by the given distance,
583// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
584class HVecShl FINAL : public HVecBinaryOperation {
585 public:
586 HVecShl(ArenaAllocator* arena,
587 HInstruction* left,
588 HInstruction* right,
589 Primitive::Type packed_type,
590 size_t vector_length,
591 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700592 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700593 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800594 }
595 DECLARE_INSTRUCTION(VecShl);
596 private:
597 DISALLOW_COPY_AND_ASSIGN(HVecShl);
598};
599
600// Arithmetically shifts every component in the vector right by the given distance,
601// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
602class HVecShr FINAL : public HVecBinaryOperation {
603 public:
604 HVecShr(ArenaAllocator* arena,
605 HInstruction* left,
606 HInstruction* right,
607 Primitive::Type packed_type,
608 size_t vector_length,
609 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700610 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700611 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800612 }
613 DECLARE_INSTRUCTION(VecShr);
614 private:
615 DISALLOW_COPY_AND_ASSIGN(HVecShr);
616};
617
618// Logically shifts every component in the vector right by the given distance,
619// viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
620class HVecUShr FINAL : public HVecBinaryOperation {
621 public:
622 HVecUShr(ArenaAllocator* arena,
623 HInstruction* left,
624 HInstruction* right,
625 Primitive::Type packed_type,
626 size_t vector_length,
627 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700628 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700629 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800630 }
631 DECLARE_INSTRUCTION(VecUShr);
632 private:
633 DISALLOW_COPY_AND_ASSIGN(HVecUShr);
634};
635
Aart Bik8de59162017-04-21 09:42:01 -0700636//
637// Definitions of concrete miscellaneous vector operations in HIR.
638//
639
640// Assigns the given scalar elements to a vector,
641// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
642class HVecSetScalars FINAL : public HVecOperation {
643 HVecSetScalars(ArenaAllocator* arena,
644 HInstruction** scalars, // array
645 Primitive::Type packed_type,
646 size_t vector_length,
647 uint32_t dex_pc = kNoDexPc)
648 : HVecOperation(arena,
649 packed_type,
650 SideEffects::None(),
651 /* number_of_inputs */ vector_length,
652 vector_length,
653 dex_pc) {
654 for (size_t i = 0; i < vector_length; i++) {
655 DCHECK(!scalars[i]->IsVecOperation());
656 SetRawInputAt(0, scalars[i]);
657 }
658 }
659 DECLARE_INSTRUCTION(VecSetScalars);
660 private:
661 DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
662};
663
Artem Serovf34dd202017-04-10 17:41:46 +0100664// Multiplies every component in the two vectors, adds the result vector to the accumulator vector.
665// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] =
666// [ acc1 + x1 * y1, .. , accn + xn * yn ].
667class HVecMultiplyAccumulate FINAL : public HVecOperation {
668 public:
669 HVecMultiplyAccumulate(ArenaAllocator* arena,
670 InstructionKind op,
671 HInstruction* accumulator,
672 HInstruction* mul_left,
673 HInstruction* mul_right,
674 Primitive::Type packed_type,
675 size_t vector_length,
676 uint32_t dex_pc = kNoDexPc)
677 : HVecOperation(arena,
678 packed_type,
679 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700680 /* number_of_inputs */ 3,
Artem Serovf34dd202017-04-10 17:41:46 +0100681 vector_length,
682 dex_pc),
683 op_kind_(op) {
684 DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
Aart Bikd58bc322017-05-01 14:49:18 -0700685 DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
686 DCHECK(HasConsistentPackedTypes(mul_left, packed_type));
687 DCHECK(HasConsistentPackedTypes(mul_right, packed_type));
Artem Serovf34dd202017-04-10 17:41:46 +0100688 SetRawInputAt(kInputAccumulatorIndex, accumulator);
689 SetRawInputAt(kInputMulLeftIndex, mul_left);
690 SetRawInputAt(kInputMulRightIndex, mul_right);
691 }
692
693 static constexpr int kInputAccumulatorIndex = 0;
694 static constexpr int kInputMulLeftIndex = 1;
695 static constexpr int kInputMulRightIndex = 2;
696
697 bool CanBeMoved() const OVERRIDE { return true; }
698
699 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
700 return op_kind_ == other->AsVecMultiplyAccumulate()->op_kind_;
701 }
702
703 InstructionKind GetOpKind() const { return op_kind_; }
704
705 DECLARE_INSTRUCTION(VecMultiplyAccumulate);
706
707 private:
708 // Indicates if this is a MADD or MSUB.
709 const InstructionKind op_kind_;
710
711 DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate);
712};
713
Aart Bikf8f5a162017-02-06 15:35:29 -0800714// Loads a vector from memory, viz. load(mem, 1)
715// yield the vector [ mem(1), .. , mem(n) ].
716class HVecLoad FINAL : public HVecMemoryOperation {
717 public:
718 HVecLoad(ArenaAllocator* arena,
719 HInstruction* base,
720 HInstruction* index,
721 Primitive::Type packed_type,
722 size_t vector_length,
Aart Bikdb14fcf2017-04-25 15:53:58 -0700723 bool is_string_char_at,
Aart Bikf8f5a162017-02-06 15:35:29 -0800724 uint32_t dex_pc = kNoDexPc)
725 : HVecMemoryOperation(arena,
726 packed_type,
727 SideEffects::ArrayReadOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700728 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800729 vector_length,
730 dex_pc) {
731 SetRawInputAt(0, base);
732 SetRawInputAt(1, index);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700733 SetPackedFlag<kFieldIsStringCharAt>(is_string_char_at);
Aart Bikf8f5a162017-02-06 15:35:29 -0800734 }
735 DECLARE_INSTRUCTION(VecLoad);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700736
737 bool IsStringCharAt() const { return GetPackedFlag<kFieldIsStringCharAt>(); }
738
Aart Bikf8f5a162017-02-06 15:35:29 -0800739 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700740 // Additional packed bits.
741 static constexpr size_t kFieldIsStringCharAt = HVecOperation::kNumberOfVectorOpPackedBits;
742 static constexpr size_t kNumberOfVecLoadPackedBits = kFieldIsStringCharAt + 1;
743 static_assert(kNumberOfVecLoadPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
744
Aart Bikf8f5a162017-02-06 15:35:29 -0800745 DISALLOW_COPY_AND_ASSIGN(HVecLoad);
746};
747
748// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
749// sets mem(1) = x1, .. , mem(n) = xn.
750class HVecStore FINAL : public HVecMemoryOperation {
751 public:
752 HVecStore(ArenaAllocator* arena,
753 HInstruction* base,
754 HInstruction* index,
755 HInstruction* value,
756 Primitive::Type packed_type,
757 size_t vector_length,
758 uint32_t dex_pc = kNoDexPc)
759 : HVecMemoryOperation(arena,
760 packed_type,
761 SideEffects::ArrayWriteOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700762 /* number_of_inputs */ 3,
Aart Bikf8f5a162017-02-06 15:35:29 -0800763 vector_length,
764 dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700765 DCHECK(HasConsistentPackedTypes(value, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800766 SetRawInputAt(0, base);
767 SetRawInputAt(1, index);
768 SetRawInputAt(2, value);
769 }
770 DECLARE_INSTRUCTION(VecStore);
771 private:
772 DISALLOW_COPY_AND_ASSIGN(HVecStore);
773};
774
775} // namespace art
776
777#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_