blob: fb9dfb7afa705d909a410b637268ba509a00f1c5 [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
101 private:
102 // 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
110 const size_t vector_length_;
111
112 DISALLOW_COPY_AND_ASSIGN(HVecOperation);
113};
114
115// Abstraction of a unary vector operation.
116class HVecUnaryOperation : public HVecOperation {
117 public:
118 HVecUnaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700119 HInstruction* input,
Aart Bikf8f5a162017-02-06 15:35:29 -0800120 Primitive::Type packed_type,
121 size_t vector_length,
122 uint32_t dex_pc)
123 : HVecOperation(arena,
124 packed_type,
125 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700126 /* number_of_inputs */ 1,
Aart Bikf8f5a162017-02-06 15:35:29 -0800127 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700128 dex_pc) {
129 SetRawInputAt(0, input);
130 }
131
132 HInstruction* GetInput() const { return InputAt(0); }
133
Aart Bikf8f5a162017-02-06 15:35:29 -0800134 DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700135
Aart Bikf8f5a162017-02-06 15:35:29 -0800136 private:
137 DISALLOW_COPY_AND_ASSIGN(HVecUnaryOperation);
138};
139
140// Abstraction of a binary vector operation.
141class HVecBinaryOperation : public HVecOperation {
142 public:
143 HVecBinaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700144 HInstruction* left,
145 HInstruction* right,
Aart Bikf8f5a162017-02-06 15:35:29 -0800146 Primitive::Type packed_type,
147 size_t vector_length,
148 uint32_t dex_pc)
149 : HVecOperation(arena,
150 packed_type,
151 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700152 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800153 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700154 dex_pc) {
155 SetRawInputAt(0, left);
156 SetRawInputAt(1, right);
157 }
Artem Serovf34dd202017-04-10 17:41:46 +0100158
159 HInstruction* GetLeft() const { return InputAt(0); }
160 HInstruction* GetRight() const { return InputAt(1); }
161
Aart Bikf8f5a162017-02-06 15:35:29 -0800162 DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700163
Aart Bikf8f5a162017-02-06 15:35:29 -0800164 private:
165 DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation);
166};
167
168// Abstraction of a vector operation that references memory, with an alignment.
169// The Android runtime guarantees at least "component size" alignment for array
170// elements and, thus, vectors.
171class HVecMemoryOperation : public HVecOperation {
172 public:
173 HVecMemoryOperation(ArenaAllocator* arena,
174 Primitive::Type packed_type,
175 SideEffects side_effects,
176 size_t number_of_inputs,
177 size_t vector_length,
178 uint32_t dex_pc)
179 : HVecOperation(arena, packed_type, side_effects, number_of_inputs, vector_length, dex_pc),
180 alignment_(Primitive::ComponentSize(packed_type), 0) { }
181
182 void SetAlignment(Alignment alignment) { alignment_ = alignment; }
183
184 Alignment GetAlignment() const { return alignment_; }
185
186 DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
187
188 private:
189 Alignment alignment_;
190
191 DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
192};
193
194//
Aart Bik8de59162017-04-21 09:42:01 -0700195// Definitions of concrete unary vector operations in HIR.
Aart Bikf8f5a162017-02-06 15:35:29 -0800196//
197
198// Replicates the given scalar into a vector,
199// viz. replicate(x) = [ x, .. , x ].
200class HVecReplicateScalar FINAL : public HVecUnaryOperation {
201 public:
202 HVecReplicateScalar(ArenaAllocator* arena,
203 HInstruction* scalar,
204 Primitive::Type packed_type,
205 size_t vector_length,
206 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700207 : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) {
208 DCHECK(!scalar->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800209 }
210 DECLARE_INSTRUCTION(VecReplicateScalar);
211 private:
212 DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
213};
214
Aart Bikf8f5a162017-02-06 15:35:29 -0800215// Sum-reduces the given vector into a shorter vector (m < n) or scalar (m = 1),
216// viz. sum-reduce[ x1, .. , xn ] = [ y1, .., ym ], where yi = sum_j x_j.
217class HVecSumReduce FINAL : public HVecUnaryOperation {
218 HVecSumReduce(ArenaAllocator* arena,
219 HInstruction* input,
220 Primitive::Type packed_type,
221 size_t vector_length,
222 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700223 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800224 DCHECK(input->IsVecOperation());
225 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800226 }
227
228 // TODO: probably integral promotion
229 Primitive::Type GetType() const OVERRIDE { return GetPackedType(); }
230
231 DECLARE_INSTRUCTION(VecSumReduce);
232 private:
233 DISALLOW_COPY_AND_ASSIGN(HVecSumReduce);
234};
235
236// Converts every component in the vector,
237// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
238class HVecCnv FINAL : public HVecUnaryOperation {
239 public:
240 HVecCnv(ArenaAllocator* arena,
241 HInstruction* input,
242 Primitive::Type packed_type,
243 size_t vector_length,
244 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700245 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800246 DCHECK(input->IsVecOperation());
247 DCHECK_NE(input->AsVecOperation()->GetPackedType(), packed_type); // actual convert
Aart Bikf8f5a162017-02-06 15:35:29 -0800248 }
249
250 Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
251 Primitive::Type GetResultType() const { return GetPackedType(); }
252
253 DECLARE_INSTRUCTION(VecCnv);
254
255 private:
256 DISALLOW_COPY_AND_ASSIGN(HVecCnv);
257};
258
259// Negates every component in the vector,
260// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
261class HVecNeg FINAL : public HVecUnaryOperation {
262 public:
263 HVecNeg(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());
270 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800271 }
272 DECLARE_INSTRUCTION(VecNeg);
273 private:
274 DISALLOW_COPY_AND_ASSIGN(HVecNeg);
275};
276
Aart Bik6daebeb2017-04-03 14:35:41 -0700277// Takes absolute value of every component in the vector,
278// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ].
279class HVecAbs FINAL : public HVecUnaryOperation {
280 public:
281 HVecAbs(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 Bik6daebeb2017-04-03 14:35:41 -0700287 DCHECK(input->IsVecOperation());
288 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
Aart Bik6daebeb2017-04-03 14:35:41 -0700289 }
290 DECLARE_INSTRUCTION(VecAbs);
291 private:
292 DISALLOW_COPY_AND_ASSIGN(HVecAbs);
293};
294
Aart Bikf8f5a162017-02-06 15:35:29 -0800295// Bitwise- or boolean-nots every component in the vector,
296// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
297// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
298class HVecNot FINAL : public HVecUnaryOperation {
299 public:
300 HVecNot(ArenaAllocator* arena,
301 HInstruction* input,
302 Primitive::Type packed_type,
303 size_t vector_length,
304 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700305 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800306 DCHECK(input->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800307 }
308 DECLARE_INSTRUCTION(VecNot);
309 private:
310 DISALLOW_COPY_AND_ASSIGN(HVecNot);
311};
312
Aart Bik8de59162017-04-21 09:42:01 -0700313//
314// Definitions of concrete binary vector operations in HIR.
315//
316
Aart Bikf8f5a162017-02-06 15:35:29 -0800317// Adds every component in the two vectors,
318// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
319class HVecAdd FINAL : public HVecBinaryOperation {
320 public:
321 HVecAdd(ArenaAllocator* arena,
322 HInstruction* left,
323 HInstruction* right,
324 Primitive::Type packed_type,
325 size_t vector_length,
326 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700327 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800328 DCHECK(left->IsVecOperation() && right->IsVecOperation());
329 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
330 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800331 }
332 DECLARE_INSTRUCTION(VecAdd);
333 private:
334 DISALLOW_COPY_AND_ASSIGN(HVecAdd);
335};
336
Aart Bikf3e61ee2017-04-12 17:09:20 -0700337// Performs halving add on every component in the two vectors, viz.
338// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
339// or [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ]
340// for signed operands x, y (sign extension) or unsigned operands x, y (zero extension).
341class HVecHalvingAdd FINAL : public HVecBinaryOperation {
342 public:
343 HVecHalvingAdd(ArenaAllocator* arena,
344 HInstruction* left,
345 HInstruction* right,
346 Primitive::Type packed_type,
347 size_t vector_length,
348 bool is_unsigned,
349 bool is_rounded,
350 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700351 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc),
Aart Bikf3e61ee2017-04-12 17:09:20 -0700352 is_unsigned_(is_unsigned),
353 is_rounded_(is_rounded) {
354 DCHECK(left->IsVecOperation() && right->IsVecOperation());
355 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
356 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700357 }
358
359 bool IsUnsigned() const { return is_unsigned_; }
360 bool IsRounded() const { return is_rounded_; }
361
362 DECLARE_INSTRUCTION(VecHalvingAdd);
363
364 private:
365 bool is_unsigned_;
366 bool is_rounded_;
367
368 DISALLOW_COPY_AND_ASSIGN(HVecHalvingAdd);
369};
370
Aart Bikf8f5a162017-02-06 15:35:29 -0800371// Subtracts every component in the two vectors,
372// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
373class HVecSub FINAL : public HVecBinaryOperation {
374 public:
375 HVecSub(ArenaAllocator* arena,
376 HInstruction* left,
377 HInstruction* right,
378 Primitive::Type packed_type,
379 size_t vector_length,
380 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700381 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800382 DCHECK(left->IsVecOperation() && right->IsVecOperation());
383 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
384 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800385 }
386 DECLARE_INSTRUCTION(VecSub);
387 private:
388 DISALLOW_COPY_AND_ASSIGN(HVecSub);
389};
390
391// Multiplies every component in the two vectors,
392// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
393class HVecMul FINAL : public HVecBinaryOperation {
394 public:
395 HVecMul(ArenaAllocator* arena,
396 HInstruction* left,
397 HInstruction* right,
398 Primitive::Type packed_type,
399 size_t vector_length,
400 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700401 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800402 DCHECK(left->IsVecOperation() && right->IsVecOperation());
403 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
404 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800405 }
406 DECLARE_INSTRUCTION(VecMul);
407 private:
408 DISALLOW_COPY_AND_ASSIGN(HVecMul);
409};
410
411// Divides every component in the two vectors,
412// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
413class HVecDiv FINAL : public HVecBinaryOperation {
414 public:
415 HVecDiv(ArenaAllocator* arena,
416 HInstruction* left,
417 HInstruction* right,
418 Primitive::Type packed_type,
419 size_t vector_length,
420 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700421 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800422 DCHECK(left->IsVecOperation() && right->IsVecOperation());
423 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
424 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800425 }
426 DECLARE_INSTRUCTION(VecDiv);
427 private:
428 DISALLOW_COPY_AND_ASSIGN(HVecDiv);
429};
430
Aart Bikf3e61ee2017-04-12 17:09:20 -0700431// Takes minimum of every component in the two vectors,
432// viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ].
433class HVecMin FINAL : public HVecBinaryOperation {
434 public:
435 HVecMin(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 Bikf3e61ee2017-04-12 17:09:20 -0700442 DCHECK(left->IsVecOperation() && right->IsVecOperation());
443 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
444 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700445 }
446 DECLARE_INSTRUCTION(VecMin);
447 private:
448 DISALLOW_COPY_AND_ASSIGN(HVecMin);
449};
450
451// Takes maximum of every component in the two vectors,
452// viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ].
453class HVecMax FINAL : public HVecBinaryOperation {
454 public:
455 HVecMax(ArenaAllocator* arena,
456 HInstruction* left,
457 HInstruction* right,
458 Primitive::Type packed_type,
459 size_t vector_length,
460 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700461 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf3e61ee2017-04-12 17:09:20 -0700462 DCHECK(left->IsVecOperation() && right->IsVecOperation());
463 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
464 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700465 }
466 DECLARE_INSTRUCTION(VecMax);
467 private:
468 DISALLOW_COPY_AND_ASSIGN(HVecMax);
469};
470
Aart Bikf8f5a162017-02-06 15:35:29 -0800471// Bitwise-ands every component in the two vectors,
472// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
473class HVecAnd FINAL : public HVecBinaryOperation {
474 public:
475 HVecAnd(ArenaAllocator* arena,
476 HInstruction* left,
477 HInstruction* right,
478 Primitive::Type packed_type,
479 size_t vector_length,
480 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700481 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800482 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800483 }
484 DECLARE_INSTRUCTION(VecAnd);
485 private:
486 DISALLOW_COPY_AND_ASSIGN(HVecAnd);
487};
488
489// Bitwise-and-nots every component in the two vectors,
490// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
491class HVecAndNot FINAL : public HVecBinaryOperation {
492 public:
493 HVecAndNot(ArenaAllocator* arena,
494 HInstruction* left,
495 HInstruction* right,
496 Primitive::Type packed_type,
497 size_t vector_length,
498 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700499 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800500 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800501 }
502 DECLARE_INSTRUCTION(VecAndNot);
503 private:
504 DISALLOW_COPY_AND_ASSIGN(HVecAndNot);
505};
506
507// Bitwise-ors every component in the two vectors,
508// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
509class HVecOr FINAL : public HVecBinaryOperation {
510 public:
511 HVecOr(ArenaAllocator* arena,
512 HInstruction* left,
513 HInstruction* right,
514 Primitive::Type packed_type,
515 size_t vector_length,
516 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700517 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800518 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800519 }
520 DECLARE_INSTRUCTION(VecOr);
521 private:
522 DISALLOW_COPY_AND_ASSIGN(HVecOr);
523};
524
525// Bitwise-xors every component in the two vectors,
526// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
527class HVecXor FINAL : public HVecBinaryOperation {
528 public:
529 HVecXor(ArenaAllocator* arena,
530 HInstruction* left,
531 HInstruction* right,
532 Primitive::Type packed_type,
533 size_t vector_length,
534 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700535 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800536 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800537 }
538 DECLARE_INSTRUCTION(VecXor);
539 private:
540 DISALLOW_COPY_AND_ASSIGN(HVecXor);
541};
542
543// Logically shifts every component in the vector left by the given distance,
544// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
545class HVecShl FINAL : public HVecBinaryOperation {
546 public:
547 HVecShl(ArenaAllocator* arena,
548 HInstruction* left,
549 HInstruction* right,
550 Primitive::Type packed_type,
551 size_t vector_length,
552 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700553 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800554 DCHECK(left->IsVecOperation());
555 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800556 }
557 DECLARE_INSTRUCTION(VecShl);
558 private:
559 DISALLOW_COPY_AND_ASSIGN(HVecShl);
560};
561
562// Arithmetically shifts every component in the vector right by the given distance,
563// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
564class HVecShr FINAL : public HVecBinaryOperation {
565 public:
566 HVecShr(ArenaAllocator* arena,
567 HInstruction* left,
568 HInstruction* right,
569 Primitive::Type packed_type,
570 size_t vector_length,
571 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700572 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800573 DCHECK(left->IsVecOperation());
574 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800575 }
576 DECLARE_INSTRUCTION(VecShr);
577 private:
578 DISALLOW_COPY_AND_ASSIGN(HVecShr);
579};
580
581// Logically shifts every component in the vector right by the given distance,
582// viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
583class HVecUShr FINAL : public HVecBinaryOperation {
584 public:
585 HVecUShr(ArenaAllocator* arena,
586 HInstruction* left,
587 HInstruction* right,
588 Primitive::Type packed_type,
589 size_t vector_length,
590 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700591 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800592 DCHECK(left->IsVecOperation());
593 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -0800594 }
595 DECLARE_INSTRUCTION(VecUShr);
596 private:
597 DISALLOW_COPY_AND_ASSIGN(HVecUShr);
598};
599
Aart Bik8de59162017-04-21 09:42:01 -0700600//
601// Definitions of concrete miscellaneous vector operations in HIR.
602//
603
604// Assigns the given scalar elements to a vector,
605// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
606class HVecSetScalars FINAL : public HVecOperation {
607 HVecSetScalars(ArenaAllocator* arena,
608 HInstruction** scalars, // array
609 Primitive::Type packed_type,
610 size_t vector_length,
611 uint32_t dex_pc = kNoDexPc)
612 : HVecOperation(arena,
613 packed_type,
614 SideEffects::None(),
615 /* number_of_inputs */ vector_length,
616 vector_length,
617 dex_pc) {
618 for (size_t i = 0; i < vector_length; i++) {
619 DCHECK(!scalars[i]->IsVecOperation());
620 SetRawInputAt(0, scalars[i]);
621 }
622 }
623 DECLARE_INSTRUCTION(VecSetScalars);
624 private:
625 DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
626};
627
Artem Serovf34dd202017-04-10 17:41:46 +0100628// Multiplies every component in the two vectors, adds the result vector to the accumulator vector.
629// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] =
630// [ acc1 + x1 * y1, .. , accn + xn * yn ].
631class HVecMultiplyAccumulate FINAL : public HVecOperation {
632 public:
633 HVecMultiplyAccumulate(ArenaAllocator* arena,
634 InstructionKind op,
635 HInstruction* accumulator,
636 HInstruction* mul_left,
637 HInstruction* mul_right,
638 Primitive::Type packed_type,
639 size_t vector_length,
640 uint32_t dex_pc = kNoDexPc)
641 : HVecOperation(arena,
642 packed_type,
643 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700644 /* number_of_inputs */ 3,
Artem Serovf34dd202017-04-10 17:41:46 +0100645 vector_length,
646 dex_pc),
647 op_kind_(op) {
648 DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
649 DCHECK(accumulator->IsVecOperation());
650 DCHECK(mul_left->IsVecOperation() && mul_right->IsVecOperation());
651 DCHECK_EQ(accumulator->AsVecOperation()->GetPackedType(), packed_type);
652 DCHECK_EQ(mul_left->AsVecOperation()->GetPackedType(), packed_type);
653 DCHECK_EQ(mul_right->AsVecOperation()->GetPackedType(), packed_type);
654
655 SetRawInputAt(kInputAccumulatorIndex, accumulator);
656 SetRawInputAt(kInputMulLeftIndex, mul_left);
657 SetRawInputAt(kInputMulRightIndex, mul_right);
658 }
659
660 static constexpr int kInputAccumulatorIndex = 0;
661 static constexpr int kInputMulLeftIndex = 1;
662 static constexpr int kInputMulRightIndex = 2;
663
664 bool CanBeMoved() const OVERRIDE { return true; }
665
666 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
667 return op_kind_ == other->AsVecMultiplyAccumulate()->op_kind_;
668 }
669
670 InstructionKind GetOpKind() const { return op_kind_; }
671
672 DECLARE_INSTRUCTION(VecMultiplyAccumulate);
673
674 private:
675 // Indicates if this is a MADD or MSUB.
676 const InstructionKind op_kind_;
677
678 DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate);
679};
680
Aart Bikf8f5a162017-02-06 15:35:29 -0800681// Loads a vector from memory, viz. load(mem, 1)
682// yield the vector [ mem(1), .. , mem(n) ].
683class HVecLoad FINAL : public HVecMemoryOperation {
684 public:
685 HVecLoad(ArenaAllocator* arena,
686 HInstruction* base,
687 HInstruction* index,
688 Primitive::Type packed_type,
689 size_t vector_length,
690 uint32_t dex_pc = kNoDexPc)
691 : HVecMemoryOperation(arena,
692 packed_type,
693 SideEffects::ArrayReadOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700694 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800695 vector_length,
696 dex_pc) {
697 SetRawInputAt(0, base);
698 SetRawInputAt(1, index);
699 }
700 DECLARE_INSTRUCTION(VecLoad);
701 private:
702 DISALLOW_COPY_AND_ASSIGN(HVecLoad);
703};
704
705// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
706// sets mem(1) = x1, .. , mem(n) = xn.
707class HVecStore FINAL : public HVecMemoryOperation {
708 public:
709 HVecStore(ArenaAllocator* arena,
710 HInstruction* base,
711 HInstruction* index,
712 HInstruction* value,
713 Primitive::Type packed_type,
714 size_t vector_length,
715 uint32_t dex_pc = kNoDexPc)
716 : HVecMemoryOperation(arena,
717 packed_type,
718 SideEffects::ArrayWriteOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700719 /* number_of_inputs */ 3,
Aart Bikf8f5a162017-02-06 15:35:29 -0800720 vector_length,
721 dex_pc) {
722 DCHECK(value->IsVecOperation());
723 DCHECK_EQ(value->AsVecOperation()->GetPackedType(), packed_type);
724 SetRawInputAt(0, base);
725 SetRawInputAt(1, index);
726 SetRawInputAt(2, value);
727 }
728 DECLARE_INSTRUCTION(VecStore);
729 private:
730 DISALLOW_COPY_AND_ASSIGN(HVecStore);
731};
732
733} // namespace art
734
735#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_