blob: c9d6ff83ad0eb3cf392779c6300932b174c687e3 [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
195//
Aart Bik8de59162017-04-21 09:42:01 -0700196// Definitions of concrete unary vector operations in HIR.
Aart Bikf8f5a162017-02-06 15:35:29 -0800197//
198
199// Replicates the given scalar into a vector,
200// viz. replicate(x) = [ x, .. , x ].
201class HVecReplicateScalar FINAL : public HVecUnaryOperation {
202 public:
203 HVecReplicateScalar(ArenaAllocator* arena,
204 HInstruction* scalar,
205 Primitive::Type packed_type,
206 size_t vector_length,
207 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700208 : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) {
209 DCHECK(!scalar->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800210 }
211 DECLARE_INSTRUCTION(VecReplicateScalar);
212 private:
213 DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
214};
215
Aart Bikf8f5a162017-02-06 15:35:29 -0800216// Sum-reduces the given vector into a shorter vector (m < n) or scalar (m = 1),
217// viz. sum-reduce[ x1, .. , xn ] = [ y1, .., ym ], where yi = sum_j x_j.
218class HVecSumReduce FINAL : public HVecUnaryOperation {
219 HVecSumReduce(ArenaAllocator* arena,
220 HInstruction* input,
221 Primitive::Type packed_type,
222 size_t vector_length,
223 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700224 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800225 DCHECK(input->IsVecOperation());
226 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800227 }
228
229 // TODO: probably integral promotion
230 Primitive::Type GetType() const OVERRIDE { return GetPackedType(); }
231
232 DECLARE_INSTRUCTION(VecSumReduce);
233 private:
234 DISALLOW_COPY_AND_ASSIGN(HVecSumReduce);
235};
236
237// Converts every component in the vector,
238// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
239class HVecCnv FINAL : public HVecUnaryOperation {
240 public:
241 HVecCnv(ArenaAllocator* arena,
242 HInstruction* input,
243 Primitive::Type packed_type,
244 size_t vector_length,
245 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700246 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800247 DCHECK(input->IsVecOperation());
248 DCHECK_NE(input->AsVecOperation()->GetPackedType(), packed_type); // actual convert
Aart Bikf8f5a162017-02-06 15:35:29 -0800249 }
250
251 Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
252 Primitive::Type GetResultType() const { return GetPackedType(); }
253
254 DECLARE_INSTRUCTION(VecCnv);
255
256 private:
257 DISALLOW_COPY_AND_ASSIGN(HVecCnv);
258};
259
260// Negates every component in the vector,
261// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
262class HVecNeg FINAL : public HVecUnaryOperation {
263 public:
264 HVecNeg(ArenaAllocator* arena,
265 HInstruction* input,
266 Primitive::Type packed_type,
267 size_t vector_length,
268 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700269 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800270 DCHECK(input->IsVecOperation());
271 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800272 }
273 DECLARE_INSTRUCTION(VecNeg);
274 private:
275 DISALLOW_COPY_AND_ASSIGN(HVecNeg);
276};
277
Aart Bik6daebeb2017-04-03 14:35:41 -0700278// Takes absolute value of every component in the vector,
279// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ].
280class HVecAbs FINAL : public HVecUnaryOperation {
281 public:
282 HVecAbs(ArenaAllocator* arena,
283 HInstruction* input,
284 Primitive::Type packed_type,
285 size_t vector_length,
286 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700287 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bik6daebeb2017-04-03 14:35:41 -0700288 DCHECK(input->IsVecOperation());
289 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
Aart Bik6daebeb2017-04-03 14:35:41 -0700290 }
291 DECLARE_INSTRUCTION(VecAbs);
292 private:
293 DISALLOW_COPY_AND_ASSIGN(HVecAbs);
294};
295
Aart Bikf8f5a162017-02-06 15:35:29 -0800296// Bitwise- or boolean-nots every component in the vector,
297// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
298// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
299class HVecNot FINAL : public HVecUnaryOperation {
300 public:
301 HVecNot(ArenaAllocator* arena,
302 HInstruction* input,
303 Primitive::Type packed_type,
304 size_t vector_length,
305 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700306 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800307 DCHECK(input->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800308 }
309 DECLARE_INSTRUCTION(VecNot);
310 private:
311 DISALLOW_COPY_AND_ASSIGN(HVecNot);
312};
313
Aart Bik8de59162017-04-21 09:42:01 -0700314//
315// Definitions of concrete binary vector operations in HIR.
316//
317
Aart Bikf8f5a162017-02-06 15:35:29 -0800318// Adds every component in the two vectors,
319// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
320class HVecAdd FINAL : public HVecBinaryOperation {
321 public:
322 HVecAdd(ArenaAllocator* arena,
323 HInstruction* left,
324 HInstruction* right,
325 Primitive::Type packed_type,
326 size_t vector_length,
327 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700328 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800329 DCHECK(left->IsVecOperation() && right->IsVecOperation());
330 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
331 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800332 }
333 DECLARE_INSTRUCTION(VecAdd);
334 private:
335 DISALLOW_COPY_AND_ASSIGN(HVecAdd);
336};
337
Aart Bikf3e61ee2017-04-12 17:09:20 -0700338// Performs halving add on every component in the two vectors, viz.
339// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
340// or [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ]
341// for signed operands x, y (sign extension) or unsigned operands x, y (zero extension).
342class HVecHalvingAdd FINAL : public HVecBinaryOperation {
343 public:
344 HVecHalvingAdd(ArenaAllocator* arena,
345 HInstruction* left,
346 HInstruction* right,
347 Primitive::Type packed_type,
348 size_t vector_length,
349 bool is_unsigned,
350 bool is_rounded,
351 uint32_t dex_pc = kNoDexPc)
Aart Bikdb14fcf2017-04-25 15:53:58 -0700352 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf3e61ee2017-04-12 17:09:20 -0700353 DCHECK(left->IsVecOperation() && right->IsVecOperation());
354 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
355 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700356 SetPackedFlag<kFieldHAddIsUnsigned>(is_unsigned);
357 SetPackedFlag<kFieldHAddIsRounded>(is_rounded);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700358 }
359
Aart Bikdb14fcf2017-04-25 15:53:58 -0700360 bool IsUnsigned() const { return GetPackedFlag<kFieldHAddIsUnsigned>(); }
361 bool IsRounded() const { return GetPackedFlag<kFieldHAddIsRounded>(); }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700362
363 DECLARE_INSTRUCTION(VecHalvingAdd);
364
365 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700366 // Additional packed bits.
367 static constexpr size_t kFieldHAddIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
368 static constexpr size_t kFieldHAddIsRounded = kFieldHAddIsUnsigned + 1;
369 static constexpr size_t kNumberOfHAddPackedBits = kFieldHAddIsRounded + 1;
370 static_assert(kNumberOfHAddPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Aart Bikf3e61ee2017-04-12 17:09:20 -0700371
372 DISALLOW_COPY_AND_ASSIGN(HVecHalvingAdd);
373};
374
Aart Bikf8f5a162017-02-06 15:35:29 -0800375// Subtracts every component in the two vectors,
376// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
377class HVecSub FINAL : public HVecBinaryOperation {
378 public:
379 HVecSub(ArenaAllocator* arena,
380 HInstruction* left,
381 HInstruction* right,
382 Primitive::Type packed_type,
383 size_t vector_length,
384 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700385 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800386 DCHECK(left->IsVecOperation() && right->IsVecOperation());
387 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
388 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800389 }
390 DECLARE_INSTRUCTION(VecSub);
391 private:
392 DISALLOW_COPY_AND_ASSIGN(HVecSub);
393};
394
395// Multiplies every component in the two vectors,
396// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
397class HVecMul FINAL : public HVecBinaryOperation {
398 public:
399 HVecMul(ArenaAllocator* arena,
400 HInstruction* left,
401 HInstruction* right,
402 Primitive::Type packed_type,
403 size_t vector_length,
404 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700405 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800406 DCHECK(left->IsVecOperation() && right->IsVecOperation());
407 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
408 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800409 }
410 DECLARE_INSTRUCTION(VecMul);
411 private:
412 DISALLOW_COPY_AND_ASSIGN(HVecMul);
413};
414
415// Divides every component in the two vectors,
416// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
417class HVecDiv FINAL : public HVecBinaryOperation {
418 public:
419 HVecDiv(ArenaAllocator* arena,
420 HInstruction* left,
421 HInstruction* right,
422 Primitive::Type packed_type,
423 size_t vector_length,
424 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700425 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800426 DCHECK(left->IsVecOperation() && right->IsVecOperation());
427 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
428 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800429 }
430 DECLARE_INSTRUCTION(VecDiv);
431 private:
432 DISALLOW_COPY_AND_ASSIGN(HVecDiv);
433};
434
Aart Bikf3e61ee2017-04-12 17:09:20 -0700435// Takes minimum of every component in the two vectors,
436// viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ].
437class HVecMin FINAL : public HVecBinaryOperation {
438 public:
439 HVecMin(ArenaAllocator* arena,
440 HInstruction* left,
441 HInstruction* right,
442 Primitive::Type packed_type,
443 size_t vector_length,
444 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700445 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf3e61ee2017-04-12 17:09:20 -0700446 DCHECK(left->IsVecOperation() && right->IsVecOperation());
447 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
448 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700449 }
450 DECLARE_INSTRUCTION(VecMin);
451 private:
452 DISALLOW_COPY_AND_ASSIGN(HVecMin);
453};
454
455// Takes maximum of every component in the two vectors,
456// viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ].
457class HVecMax FINAL : public HVecBinaryOperation {
458 public:
459 HVecMax(ArenaAllocator* arena,
460 HInstruction* left,
461 HInstruction* right,
462 Primitive::Type packed_type,
463 size_t vector_length,
464 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700465 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf3e61ee2017-04-12 17:09:20 -0700466 DCHECK(left->IsVecOperation() && right->IsVecOperation());
467 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
468 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700469 }
470 DECLARE_INSTRUCTION(VecMax);
471 private:
472 DISALLOW_COPY_AND_ASSIGN(HVecMax);
473};
474
Aart Bikf8f5a162017-02-06 15:35:29 -0800475// Bitwise-ands every component in the two vectors,
476// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
477class HVecAnd FINAL : public HVecBinaryOperation {
478 public:
479 HVecAnd(ArenaAllocator* arena,
480 HInstruction* left,
481 HInstruction* right,
482 Primitive::Type packed_type,
483 size_t vector_length,
484 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700485 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800486 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800487 }
488 DECLARE_INSTRUCTION(VecAnd);
489 private:
490 DISALLOW_COPY_AND_ASSIGN(HVecAnd);
491};
492
493// Bitwise-and-nots every component in the two vectors,
494// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
495class HVecAndNot FINAL : public HVecBinaryOperation {
496 public:
497 HVecAndNot(ArenaAllocator* arena,
498 HInstruction* left,
499 HInstruction* right,
500 Primitive::Type packed_type,
501 size_t vector_length,
502 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700503 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800504 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800505 }
506 DECLARE_INSTRUCTION(VecAndNot);
507 private:
508 DISALLOW_COPY_AND_ASSIGN(HVecAndNot);
509};
510
511// Bitwise-ors every component in the two vectors,
512// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
513class HVecOr FINAL : public HVecBinaryOperation {
514 public:
515 HVecOr(ArenaAllocator* arena,
516 HInstruction* left,
517 HInstruction* right,
518 Primitive::Type packed_type,
519 size_t vector_length,
520 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700521 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800522 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800523 }
524 DECLARE_INSTRUCTION(VecOr);
525 private:
526 DISALLOW_COPY_AND_ASSIGN(HVecOr);
527};
528
529// Bitwise-xors every component in the two vectors,
530// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
531class HVecXor FINAL : public HVecBinaryOperation {
532 public:
533 HVecXor(ArenaAllocator* arena,
534 HInstruction* left,
535 HInstruction* right,
536 Primitive::Type packed_type,
537 size_t vector_length,
538 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700539 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800540 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800541 }
542 DECLARE_INSTRUCTION(VecXor);
543 private:
544 DISALLOW_COPY_AND_ASSIGN(HVecXor);
545};
546
547// Logically shifts every component in the vector left by the given distance,
548// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
549class HVecShl FINAL : public HVecBinaryOperation {
550 public:
551 HVecShl(ArenaAllocator* arena,
552 HInstruction* left,
553 HInstruction* right,
554 Primitive::Type packed_type,
555 size_t vector_length,
556 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700557 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800558 DCHECK(left->IsVecOperation());
559 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800560 }
561 DECLARE_INSTRUCTION(VecShl);
562 private:
563 DISALLOW_COPY_AND_ASSIGN(HVecShl);
564};
565
566// Arithmetically shifts every component in the vector right by the given distance,
567// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
568class HVecShr FINAL : public HVecBinaryOperation {
569 public:
570 HVecShr(ArenaAllocator* arena,
571 HInstruction* left,
572 HInstruction* right,
573 Primitive::Type packed_type,
574 size_t vector_length,
575 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700576 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800577 DCHECK(left->IsVecOperation());
578 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800579 }
580 DECLARE_INSTRUCTION(VecShr);
581 private:
582 DISALLOW_COPY_AND_ASSIGN(HVecShr);
583};
584
585// Logically shifts every component in the vector right by the given distance,
586// viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
587class HVecUShr FINAL : public HVecBinaryOperation {
588 public:
589 HVecUShr(ArenaAllocator* arena,
590 HInstruction* left,
591 HInstruction* right,
592 Primitive::Type packed_type,
593 size_t vector_length,
594 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700595 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800596 DCHECK(left->IsVecOperation());
597 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800598 }
599 DECLARE_INSTRUCTION(VecUShr);
600 private:
601 DISALLOW_COPY_AND_ASSIGN(HVecUShr);
602};
603
Aart Bik8de59162017-04-21 09:42:01 -0700604//
605// Definitions of concrete miscellaneous vector operations in HIR.
606//
607
608// Assigns the given scalar elements to a vector,
609// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
610class HVecSetScalars FINAL : public HVecOperation {
611 HVecSetScalars(ArenaAllocator* arena,
612 HInstruction** scalars, // array
613 Primitive::Type packed_type,
614 size_t vector_length,
615 uint32_t dex_pc = kNoDexPc)
616 : HVecOperation(arena,
617 packed_type,
618 SideEffects::None(),
619 /* number_of_inputs */ vector_length,
620 vector_length,
621 dex_pc) {
622 for (size_t i = 0; i < vector_length; i++) {
623 DCHECK(!scalars[i]->IsVecOperation());
624 SetRawInputAt(0, scalars[i]);
625 }
626 }
627 DECLARE_INSTRUCTION(VecSetScalars);
628 private:
629 DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
630};
631
Artem Serovf34dd202017-04-10 17:41:46 +0100632// Multiplies every component in the two vectors, adds the result vector to the accumulator vector.
633// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] =
634// [ acc1 + x1 * y1, .. , accn + xn * yn ].
635class HVecMultiplyAccumulate FINAL : public HVecOperation {
636 public:
637 HVecMultiplyAccumulate(ArenaAllocator* arena,
638 InstructionKind op,
639 HInstruction* accumulator,
640 HInstruction* mul_left,
641 HInstruction* mul_right,
642 Primitive::Type packed_type,
643 size_t vector_length,
644 uint32_t dex_pc = kNoDexPc)
645 : HVecOperation(arena,
646 packed_type,
647 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700648 /* number_of_inputs */ 3,
Artem Serovf34dd202017-04-10 17:41:46 +0100649 vector_length,
650 dex_pc),
651 op_kind_(op) {
652 DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
653 DCHECK(accumulator->IsVecOperation());
654 DCHECK(mul_left->IsVecOperation() && mul_right->IsVecOperation());
655 DCHECK_EQ(accumulator->AsVecOperation()->GetPackedType(), packed_type);
656 DCHECK_EQ(mul_left->AsVecOperation()->GetPackedType(), packed_type);
657 DCHECK_EQ(mul_right->AsVecOperation()->GetPackedType(), packed_type);
658
659 SetRawInputAt(kInputAccumulatorIndex, accumulator);
660 SetRawInputAt(kInputMulLeftIndex, mul_left);
661 SetRawInputAt(kInputMulRightIndex, mul_right);
662 }
663
664 static constexpr int kInputAccumulatorIndex = 0;
665 static constexpr int kInputMulLeftIndex = 1;
666 static constexpr int kInputMulRightIndex = 2;
667
668 bool CanBeMoved() const OVERRIDE { return true; }
669
670 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
671 return op_kind_ == other->AsVecMultiplyAccumulate()->op_kind_;
672 }
673
674 InstructionKind GetOpKind() const { return op_kind_; }
675
676 DECLARE_INSTRUCTION(VecMultiplyAccumulate);
677
678 private:
679 // Indicates if this is a MADD or MSUB.
680 const InstructionKind op_kind_;
681
682 DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate);
683};
684
Aart Bikf8f5a162017-02-06 15:35:29 -0800685// Loads a vector from memory, viz. load(mem, 1)
686// yield the vector [ mem(1), .. , mem(n) ].
687class HVecLoad FINAL : public HVecMemoryOperation {
688 public:
689 HVecLoad(ArenaAllocator* arena,
690 HInstruction* base,
691 HInstruction* index,
692 Primitive::Type packed_type,
693 size_t vector_length,
Aart Bikdb14fcf2017-04-25 15:53:58 -0700694 bool is_string_char_at,
Aart Bikf8f5a162017-02-06 15:35:29 -0800695 uint32_t dex_pc = kNoDexPc)
696 : HVecMemoryOperation(arena,
697 packed_type,
698 SideEffects::ArrayReadOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700699 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800700 vector_length,
701 dex_pc) {
702 SetRawInputAt(0, base);
703 SetRawInputAt(1, index);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700704 SetPackedFlag<kFieldIsStringCharAt>(is_string_char_at);
Aart Bikf8f5a162017-02-06 15:35:29 -0800705 }
706 DECLARE_INSTRUCTION(VecLoad);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700707
708 bool IsStringCharAt() const { return GetPackedFlag<kFieldIsStringCharAt>(); }
709
Aart Bikf8f5a162017-02-06 15:35:29 -0800710 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700711 // Additional packed bits.
712 static constexpr size_t kFieldIsStringCharAt = HVecOperation::kNumberOfVectorOpPackedBits;
713 static constexpr size_t kNumberOfVecLoadPackedBits = kFieldIsStringCharAt + 1;
714 static_assert(kNumberOfVecLoadPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
715
Aart Bikf8f5a162017-02-06 15:35:29 -0800716 DISALLOW_COPY_AND_ASSIGN(HVecLoad);
717};
718
719// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
720// sets mem(1) = x1, .. , mem(n) = xn.
721class HVecStore FINAL : public HVecMemoryOperation {
722 public:
723 HVecStore(ArenaAllocator* arena,
724 HInstruction* base,
725 HInstruction* index,
726 HInstruction* value,
727 Primitive::Type packed_type,
728 size_t vector_length,
729 uint32_t dex_pc = kNoDexPc)
730 : HVecMemoryOperation(arena,
731 packed_type,
732 SideEffects::ArrayWriteOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700733 /* number_of_inputs */ 3,
Aart Bikf8f5a162017-02-06 15:35:29 -0800734 vector_length,
735 dex_pc) {
736 DCHECK(value->IsVecOperation());
737 DCHECK_EQ(value->AsVecOperation()->GetPackedType(), packed_type);
738 SetRawInputAt(0, base);
739 SetRawInputAt(1, index);
740 SetRawInputAt(2, value);
741 }
742 DECLARE_INSTRUCTION(VecStore);
743 private:
744 DISALLOW_COPY_AND_ASSIGN(HVecStore);
745};
746
747} // namespace art
748
749#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_