blob: c2bb6e79c001b3b24c1485d88db332ac4336754d [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),
181 alignment_(Primitive::ComponentSize(packed_type), 0) { }
182
183 void SetAlignment(Alignment alignment) { alignment_ = alignment; }
184
185 Alignment GetAlignment() const { return alignment_; }
186
187 DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
188
189 private:
190 Alignment alignment_;
191
192 DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
193};
194
Aart Bikd58bc322017-05-01 14:49:18 -0700195// Packed type consistency checker (same vector length integral types may mix freely).
196inline static bool HasConsistentPackedTypes(HInstruction* input, Primitive::Type type) {
197 DCHECK(input->IsVecOperation());
198 Primitive::Type input_type = input->AsVecOperation()->GetPackedType();
199 switch (input_type) {
200 case Primitive::kPrimBoolean:
201 case Primitive::kPrimByte:
202 return type == Primitive::kPrimBoolean ||
203 type == Primitive::kPrimByte;
204 case Primitive::kPrimChar:
205 case Primitive::kPrimShort:
206 return type == Primitive::kPrimChar ||
207 type == Primitive::kPrimShort;
208 default:
209 return type == input_type;
210 }
211}
212
Aart Bikf8f5a162017-02-06 15:35:29 -0800213//
Aart Bik8de59162017-04-21 09:42:01 -0700214// Definitions of concrete unary vector operations in HIR.
Aart Bikf8f5a162017-02-06 15:35:29 -0800215//
216
217// Replicates the given scalar into a vector,
218// viz. replicate(x) = [ x, .. , x ].
219class HVecReplicateScalar FINAL : public HVecUnaryOperation {
220 public:
221 HVecReplicateScalar(ArenaAllocator* arena,
222 HInstruction* scalar,
223 Primitive::Type packed_type,
224 size_t vector_length,
225 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700226 : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) {
227 DCHECK(!scalar->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800228 }
229 DECLARE_INSTRUCTION(VecReplicateScalar);
230 private:
231 DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
232};
233
Aart Bikf8f5a162017-02-06 15:35:29 -0800234// Sum-reduces the given vector into a shorter vector (m < n) or scalar (m = 1),
235// viz. sum-reduce[ x1, .. , xn ] = [ y1, .., ym ], where yi = sum_j x_j.
236class HVecSumReduce FINAL : public HVecUnaryOperation {
237 HVecSumReduce(ArenaAllocator* arena,
238 HInstruction* input,
239 Primitive::Type packed_type,
240 size_t vector_length,
241 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700242 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700243 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800244 }
245
246 // TODO: probably integral promotion
247 Primitive::Type GetType() const OVERRIDE { return GetPackedType(); }
248
249 DECLARE_INSTRUCTION(VecSumReduce);
250 private:
251 DISALLOW_COPY_AND_ASSIGN(HVecSumReduce);
252};
253
254// Converts every component in the vector,
255// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
256class HVecCnv FINAL : public HVecUnaryOperation {
257 public:
258 HVecCnv(ArenaAllocator* arena,
259 HInstruction* input,
260 Primitive::Type packed_type,
261 size_t vector_length,
262 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700263 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800264 DCHECK(input->IsVecOperation());
Aart Bikd58bc322017-05-01 14:49:18 -0700265 DCHECK_NE(GetInputType(), GetResultType()); // actual convert
Aart Bikf8f5a162017-02-06 15:35:29 -0800266 }
267
268 Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
269 Primitive::Type GetResultType() const { return GetPackedType(); }
270
271 DECLARE_INSTRUCTION(VecCnv);
272
273 private:
274 DISALLOW_COPY_AND_ASSIGN(HVecCnv);
275};
276
277// Negates every component in the vector,
278// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
279class HVecNeg FINAL : public HVecUnaryOperation {
280 public:
281 HVecNeg(ArenaAllocator* arena,
282 HInstruction* input,
283 Primitive::Type packed_type,
284 size_t vector_length,
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 Bikf8f5a162017-02-06 15:35:29 -0800288 }
289 DECLARE_INSTRUCTION(VecNeg);
290 private:
291 DISALLOW_COPY_AND_ASSIGN(HVecNeg);
292};
293
Aart Bik6daebeb2017-04-03 14:35:41 -0700294// Takes absolute value of every component in the vector,
295// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ].
296class HVecAbs FINAL : public HVecUnaryOperation {
297 public:
298 HVecAbs(ArenaAllocator* arena,
299 HInstruction* input,
300 Primitive::Type packed_type,
301 size_t vector_length,
302 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700303 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700304 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik6daebeb2017-04-03 14:35:41 -0700305 }
306 DECLARE_INSTRUCTION(VecAbs);
307 private:
308 DISALLOW_COPY_AND_ASSIGN(HVecAbs);
309};
310
Aart Bikf8f5a162017-02-06 15:35:29 -0800311// Bitwise- or boolean-nots every component in the vector,
312// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
313// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
314class HVecNot FINAL : public HVecUnaryOperation {
315 public:
316 HVecNot(ArenaAllocator* arena,
317 HInstruction* input,
318 Primitive::Type packed_type,
319 size_t vector_length,
320 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700321 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800322 DCHECK(input->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800323 }
324 DECLARE_INSTRUCTION(VecNot);
325 private:
326 DISALLOW_COPY_AND_ASSIGN(HVecNot);
327};
328
Aart Bik8de59162017-04-21 09:42:01 -0700329//
330// Definitions of concrete binary vector operations in HIR.
331//
332
Aart Bikf8f5a162017-02-06 15:35:29 -0800333// Adds every component in the two vectors,
334// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
335class HVecAdd FINAL : public HVecBinaryOperation {
336 public:
337 HVecAdd(ArenaAllocator* arena,
338 HInstruction* left,
339 HInstruction* right,
340 Primitive::Type packed_type,
341 size_t vector_length,
342 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700343 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700344 DCHECK(HasConsistentPackedTypes(left, packed_type));
345 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800346 }
347 DECLARE_INSTRUCTION(VecAdd);
348 private:
349 DISALLOW_COPY_AND_ASSIGN(HVecAdd);
350};
351
Aart Bikf3e61ee2017-04-12 17:09:20 -0700352// Performs halving add on every component in the two vectors, viz.
353// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
354// or [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ]
355// for signed operands x, y (sign extension) or unsigned operands x, y (zero extension).
356class HVecHalvingAdd FINAL : public HVecBinaryOperation {
357 public:
358 HVecHalvingAdd(ArenaAllocator* arena,
359 HInstruction* left,
360 HInstruction* right,
361 Primitive::Type packed_type,
362 size_t vector_length,
363 bool is_unsigned,
364 bool is_rounded,
365 uint32_t dex_pc = kNoDexPc)
Aart Bikdb14fcf2017-04-25 15:53:58 -0700366 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700367 DCHECK(HasConsistentPackedTypes(left, packed_type));
368 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikdb14fcf2017-04-25 15:53:58 -0700369 SetPackedFlag<kFieldHAddIsUnsigned>(is_unsigned);
370 SetPackedFlag<kFieldHAddIsRounded>(is_rounded);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700371 }
372
Aart Bikdb14fcf2017-04-25 15:53:58 -0700373 bool IsUnsigned() const { return GetPackedFlag<kFieldHAddIsUnsigned>(); }
374 bool IsRounded() const { return GetPackedFlag<kFieldHAddIsRounded>(); }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700375
376 DECLARE_INSTRUCTION(VecHalvingAdd);
377
378 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700379 // Additional packed bits.
380 static constexpr size_t kFieldHAddIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
381 static constexpr size_t kFieldHAddIsRounded = kFieldHAddIsUnsigned + 1;
382 static constexpr size_t kNumberOfHAddPackedBits = kFieldHAddIsRounded + 1;
383 static_assert(kNumberOfHAddPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Aart Bikf3e61ee2017-04-12 17:09:20 -0700384
385 DISALLOW_COPY_AND_ASSIGN(HVecHalvingAdd);
386};
387
Aart Bikf8f5a162017-02-06 15:35:29 -0800388// Subtracts every component in the two vectors,
389// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
390class HVecSub FINAL : public HVecBinaryOperation {
391 public:
392 HVecSub(ArenaAllocator* arena,
393 HInstruction* left,
394 HInstruction* right,
395 Primitive::Type packed_type,
396 size_t vector_length,
397 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700398 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700399 DCHECK(HasConsistentPackedTypes(left, packed_type));
400 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800401 }
402 DECLARE_INSTRUCTION(VecSub);
403 private:
404 DISALLOW_COPY_AND_ASSIGN(HVecSub);
405};
406
407// Multiplies every component in the two vectors,
408// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
409class HVecMul FINAL : public HVecBinaryOperation {
410 public:
411 HVecMul(ArenaAllocator* arena,
412 HInstruction* left,
413 HInstruction* right,
414 Primitive::Type packed_type,
415 size_t vector_length,
416 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700417 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700418 DCHECK(HasConsistentPackedTypes(left, packed_type));
419 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800420 }
421 DECLARE_INSTRUCTION(VecMul);
422 private:
423 DISALLOW_COPY_AND_ASSIGN(HVecMul);
424};
425
426// Divides every component in the two vectors,
427// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
428class HVecDiv FINAL : public HVecBinaryOperation {
429 public:
430 HVecDiv(ArenaAllocator* arena,
431 HInstruction* left,
432 HInstruction* right,
433 Primitive::Type packed_type,
434 size_t vector_length,
435 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700436 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700437 DCHECK(HasConsistentPackedTypes(left, packed_type));
438 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800439 }
440 DECLARE_INSTRUCTION(VecDiv);
441 private:
442 DISALLOW_COPY_AND_ASSIGN(HVecDiv);
443};
444
Aart Bikf3e61ee2017-04-12 17:09:20 -0700445// Takes minimum of every component in the two vectors,
446// viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ].
447class HVecMin FINAL : public HVecBinaryOperation {
448 public:
449 HVecMin(ArenaAllocator* arena,
450 HInstruction* left,
451 HInstruction* right,
452 Primitive::Type packed_type,
453 size_t vector_length,
Aart Bikc8e93c72017-05-10 10:49:22 -0700454 bool is_unsigned,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700455 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700456 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700457 DCHECK(HasConsistentPackedTypes(left, packed_type));
458 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700459 SetPackedFlag<kFieldMinOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700460 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700461
462 bool IsUnsigned() const { return GetPackedFlag<kFieldMinOpIsUnsigned>(); }
463
Aart Bikf3e61ee2017-04-12 17:09:20 -0700464 DECLARE_INSTRUCTION(VecMin);
Aart Bikc8e93c72017-05-10 10:49:22 -0700465
Aart Bikf3e61ee2017-04-12 17:09:20 -0700466 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700467 // Additional packed bits.
468 static constexpr size_t kFieldMinOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
469 static constexpr size_t kNumberOfMinOpPackedBits = kFieldMinOpIsUnsigned + 1;
470 static_assert(kNumberOfMinOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
471
Aart Bikf3e61ee2017-04-12 17:09:20 -0700472 DISALLOW_COPY_AND_ASSIGN(HVecMin);
473};
474
475// Takes maximum of every component in the two vectors,
476// viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ].
477class HVecMax FINAL : public HVecBinaryOperation {
478 public:
479 HVecMax(ArenaAllocator* arena,
480 HInstruction* left,
481 HInstruction* right,
482 Primitive::Type packed_type,
483 size_t vector_length,
Aart Bikc8e93c72017-05-10 10:49:22 -0700484 bool is_unsigned,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700485 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700486 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700487 DCHECK(HasConsistentPackedTypes(left, packed_type));
488 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700489 SetPackedFlag<kFieldMaxOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700490 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700491
492 bool IsUnsigned() const { return GetPackedFlag<kFieldMaxOpIsUnsigned>(); }
493
Aart Bikf3e61ee2017-04-12 17:09:20 -0700494 DECLARE_INSTRUCTION(VecMax);
Aart Bikc8e93c72017-05-10 10:49:22 -0700495
Aart Bikf3e61ee2017-04-12 17:09:20 -0700496 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700497 // Additional packed bits.
498 static constexpr size_t kFieldMaxOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
499 static constexpr size_t kNumberOfMaxOpPackedBits = kFieldMaxOpIsUnsigned + 1;
500 static_assert(kNumberOfMaxOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
501
Aart Bikf3e61ee2017-04-12 17:09:20 -0700502 DISALLOW_COPY_AND_ASSIGN(HVecMax);
503};
504
Aart Bikf8f5a162017-02-06 15:35:29 -0800505// Bitwise-ands every component in the two vectors,
506// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
507class HVecAnd FINAL : public HVecBinaryOperation {
508 public:
509 HVecAnd(ArenaAllocator* arena,
510 HInstruction* left,
511 HInstruction* right,
512 Primitive::Type packed_type,
513 size_t vector_length,
514 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700515 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800516 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800517 }
518 DECLARE_INSTRUCTION(VecAnd);
519 private:
520 DISALLOW_COPY_AND_ASSIGN(HVecAnd);
521};
522
523// Bitwise-and-nots every component in the two vectors,
524// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
525class HVecAndNot FINAL : public HVecBinaryOperation {
526 public:
527 HVecAndNot(ArenaAllocator* arena,
528 HInstruction* left,
529 HInstruction* right,
530 Primitive::Type packed_type,
531 size_t vector_length,
532 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700533 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800534 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800535 }
536 DECLARE_INSTRUCTION(VecAndNot);
537 private:
538 DISALLOW_COPY_AND_ASSIGN(HVecAndNot);
539};
540
541// Bitwise-ors every component in the two vectors,
542// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
543class HVecOr FINAL : public HVecBinaryOperation {
544 public:
545 HVecOr(ArenaAllocator* arena,
546 HInstruction* left,
547 HInstruction* right,
548 Primitive::Type packed_type,
549 size_t vector_length,
550 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700551 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800552 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800553 }
554 DECLARE_INSTRUCTION(VecOr);
555 private:
556 DISALLOW_COPY_AND_ASSIGN(HVecOr);
557};
558
559// Bitwise-xors every component in the two vectors,
560// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
561class HVecXor FINAL : public HVecBinaryOperation {
562 public:
563 HVecXor(ArenaAllocator* arena,
564 HInstruction* left,
565 HInstruction* right,
566 Primitive::Type packed_type,
567 size_t vector_length,
568 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700569 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800570 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800571 }
572 DECLARE_INSTRUCTION(VecXor);
573 private:
574 DISALLOW_COPY_AND_ASSIGN(HVecXor);
575};
576
577// Logically shifts every component in the vector left by the given distance,
578// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
579class HVecShl FINAL : public HVecBinaryOperation {
580 public:
581 HVecShl(ArenaAllocator* arena,
582 HInstruction* left,
583 HInstruction* right,
584 Primitive::Type packed_type,
585 size_t vector_length,
586 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700587 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700588 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800589 }
590 DECLARE_INSTRUCTION(VecShl);
591 private:
592 DISALLOW_COPY_AND_ASSIGN(HVecShl);
593};
594
595// Arithmetically shifts every component in the vector right by the given distance,
596// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
597class HVecShr FINAL : public HVecBinaryOperation {
598 public:
599 HVecShr(ArenaAllocator* arena,
600 HInstruction* left,
601 HInstruction* right,
602 Primitive::Type packed_type,
603 size_t vector_length,
604 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700605 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700606 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800607 }
608 DECLARE_INSTRUCTION(VecShr);
609 private:
610 DISALLOW_COPY_AND_ASSIGN(HVecShr);
611};
612
613// Logically shifts every component in the vector right by the given distance,
614// viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
615class HVecUShr FINAL : public HVecBinaryOperation {
616 public:
617 HVecUShr(ArenaAllocator* arena,
618 HInstruction* left,
619 HInstruction* right,
620 Primitive::Type packed_type,
621 size_t vector_length,
622 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700623 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700624 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800625 }
626 DECLARE_INSTRUCTION(VecUShr);
627 private:
628 DISALLOW_COPY_AND_ASSIGN(HVecUShr);
629};
630
Aart Bik8de59162017-04-21 09:42:01 -0700631//
632// Definitions of concrete miscellaneous vector operations in HIR.
633//
634
635// Assigns the given scalar elements to a vector,
636// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
637class HVecSetScalars FINAL : public HVecOperation {
638 HVecSetScalars(ArenaAllocator* arena,
639 HInstruction** scalars, // array
640 Primitive::Type packed_type,
641 size_t vector_length,
642 uint32_t dex_pc = kNoDexPc)
643 : HVecOperation(arena,
644 packed_type,
645 SideEffects::None(),
646 /* number_of_inputs */ vector_length,
647 vector_length,
648 dex_pc) {
649 for (size_t i = 0; i < vector_length; i++) {
650 DCHECK(!scalars[i]->IsVecOperation());
651 SetRawInputAt(0, scalars[i]);
652 }
653 }
654 DECLARE_INSTRUCTION(VecSetScalars);
655 private:
656 DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
657};
658
Artem Serovf34dd202017-04-10 17:41:46 +0100659// Multiplies every component in the two vectors, adds the result vector to the accumulator vector.
660// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] =
661// [ acc1 + x1 * y1, .. , accn + xn * yn ].
662class HVecMultiplyAccumulate FINAL : public HVecOperation {
663 public:
664 HVecMultiplyAccumulate(ArenaAllocator* arena,
665 InstructionKind op,
666 HInstruction* accumulator,
667 HInstruction* mul_left,
668 HInstruction* mul_right,
669 Primitive::Type packed_type,
670 size_t vector_length,
671 uint32_t dex_pc = kNoDexPc)
672 : HVecOperation(arena,
673 packed_type,
674 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700675 /* number_of_inputs */ 3,
Artem Serovf34dd202017-04-10 17:41:46 +0100676 vector_length,
677 dex_pc),
678 op_kind_(op) {
679 DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
Aart Bikd58bc322017-05-01 14:49:18 -0700680 DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
681 DCHECK(HasConsistentPackedTypes(mul_left, packed_type));
682 DCHECK(HasConsistentPackedTypes(mul_right, packed_type));
Artem Serovf34dd202017-04-10 17:41:46 +0100683 SetRawInputAt(kInputAccumulatorIndex, accumulator);
684 SetRawInputAt(kInputMulLeftIndex, mul_left);
685 SetRawInputAt(kInputMulRightIndex, mul_right);
686 }
687
688 static constexpr int kInputAccumulatorIndex = 0;
689 static constexpr int kInputMulLeftIndex = 1;
690 static constexpr int kInputMulRightIndex = 2;
691
692 bool CanBeMoved() const OVERRIDE { return true; }
693
694 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
695 return op_kind_ == other->AsVecMultiplyAccumulate()->op_kind_;
696 }
697
698 InstructionKind GetOpKind() const { return op_kind_; }
699
700 DECLARE_INSTRUCTION(VecMultiplyAccumulate);
701
702 private:
703 // Indicates if this is a MADD or MSUB.
704 const InstructionKind op_kind_;
705
706 DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate);
707};
708
Aart Bikf8f5a162017-02-06 15:35:29 -0800709// Loads a vector from memory, viz. load(mem, 1)
710// yield the vector [ mem(1), .. , mem(n) ].
711class HVecLoad FINAL : public HVecMemoryOperation {
712 public:
713 HVecLoad(ArenaAllocator* arena,
714 HInstruction* base,
715 HInstruction* index,
716 Primitive::Type packed_type,
717 size_t vector_length,
Aart Bikdb14fcf2017-04-25 15:53:58 -0700718 bool is_string_char_at,
Aart Bikf8f5a162017-02-06 15:35:29 -0800719 uint32_t dex_pc = kNoDexPc)
720 : HVecMemoryOperation(arena,
721 packed_type,
722 SideEffects::ArrayReadOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700723 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800724 vector_length,
725 dex_pc) {
726 SetRawInputAt(0, base);
727 SetRawInputAt(1, index);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700728 SetPackedFlag<kFieldIsStringCharAt>(is_string_char_at);
Aart Bikf8f5a162017-02-06 15:35:29 -0800729 }
730 DECLARE_INSTRUCTION(VecLoad);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700731
732 bool IsStringCharAt() const { return GetPackedFlag<kFieldIsStringCharAt>(); }
733
Aart Bikf8f5a162017-02-06 15:35:29 -0800734 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700735 // Additional packed bits.
736 static constexpr size_t kFieldIsStringCharAt = HVecOperation::kNumberOfVectorOpPackedBits;
737 static constexpr size_t kNumberOfVecLoadPackedBits = kFieldIsStringCharAt + 1;
738 static_assert(kNumberOfVecLoadPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
739
Aart Bikf8f5a162017-02-06 15:35:29 -0800740 DISALLOW_COPY_AND_ASSIGN(HVecLoad);
741};
742
743// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
744// sets mem(1) = x1, .. , mem(n) = xn.
745class HVecStore FINAL : public HVecMemoryOperation {
746 public:
747 HVecStore(ArenaAllocator* arena,
748 HInstruction* base,
749 HInstruction* index,
750 HInstruction* value,
751 Primitive::Type packed_type,
752 size_t vector_length,
753 uint32_t dex_pc = kNoDexPc)
754 : HVecMemoryOperation(arena,
755 packed_type,
756 SideEffects::ArrayWriteOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700757 /* number_of_inputs */ 3,
Aart Bikf8f5a162017-02-06 15:35:29 -0800758 vector_length,
759 dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700760 DCHECK(HasConsistentPackedTypes(value, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800761 SetRawInputAt(0, base);
762 SetRawInputAt(1, index);
763 SetRawInputAt(2, value);
764 }
765 DECLARE_INSTRUCTION(VecStore);
766 private:
767 DISALLOW_COPY_AND_ASSIGN(HVecStore);
768};
769
770} // namespace art
771
772#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_