blob: 450691c1eabf11fe7dea98f82973d21410ce2247 [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,
119 Primitive::Type packed_type,
120 size_t vector_length,
121 uint32_t dex_pc)
122 : HVecOperation(arena,
123 packed_type,
124 SideEffects::None(),
125 /*number_of_inputs*/ 1,
126 vector_length,
127 dex_pc) { }
128 DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation);
129 private:
130 DISALLOW_COPY_AND_ASSIGN(HVecUnaryOperation);
131};
132
133// Abstraction of a binary vector operation.
134class HVecBinaryOperation : public HVecOperation {
135 public:
136 HVecBinaryOperation(ArenaAllocator* arena,
137 Primitive::Type packed_type,
138 size_t vector_length,
139 uint32_t dex_pc)
140 : HVecOperation(arena,
141 packed_type,
142 SideEffects::None(),
143 /*number_of_inputs*/ 2,
144 vector_length,
145 dex_pc) { }
Artem Serovf34dd202017-04-10 17:41:46 +0100146
147 HInstruction* GetLeft() const { return InputAt(0); }
148 HInstruction* GetRight() const { return InputAt(1); }
149
Aart Bikf8f5a162017-02-06 15:35:29 -0800150 DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
151 private:
152 DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation);
153};
154
155// Abstraction of a vector operation that references memory, with an alignment.
156// The Android runtime guarantees at least "component size" alignment for array
157// elements and, thus, vectors.
158class HVecMemoryOperation : public HVecOperation {
159 public:
160 HVecMemoryOperation(ArenaAllocator* arena,
161 Primitive::Type packed_type,
162 SideEffects side_effects,
163 size_t number_of_inputs,
164 size_t vector_length,
165 uint32_t dex_pc)
166 : HVecOperation(arena, packed_type, side_effects, number_of_inputs, vector_length, dex_pc),
167 alignment_(Primitive::ComponentSize(packed_type), 0) { }
168
169 void SetAlignment(Alignment alignment) { alignment_ = alignment; }
170
171 Alignment GetAlignment() const { return alignment_; }
172
173 DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
174
175 private:
176 Alignment alignment_;
177
178 DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
179};
180
181//
182// Definitions of concrete vector operations in HIR.
183//
184
185// Replicates the given scalar into a vector,
186// viz. replicate(x) = [ x, .. , x ].
187class HVecReplicateScalar FINAL : public HVecUnaryOperation {
188 public:
189 HVecReplicateScalar(ArenaAllocator* arena,
190 HInstruction* scalar,
191 Primitive::Type packed_type,
192 size_t vector_length,
193 uint32_t dex_pc = kNoDexPc)
194 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
195 SetRawInputAt(0, scalar);
196 }
197 DECLARE_INSTRUCTION(VecReplicateScalar);
198 private:
199 DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
200};
201
202// Assigns the given scalar elements to a vector,
203// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
204class HVecSetScalars FINAL : public HVecUnaryOperation {
205 HVecSetScalars(ArenaAllocator* arena,
206 HInstruction** scalars, // array
207 Primitive::Type packed_type,
208 size_t vector_length,
209 uint32_t dex_pc = kNoDexPc)
210 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
211 for (size_t i = 0; i < vector_length; i++) {
212 SetRawInputAt(0, scalars[i]);
213 }
214 }
215 DECLARE_INSTRUCTION(VecSetScalars);
216 private:
217 DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
218};
219
220// Sum-reduces the given vector into a shorter vector (m < n) or scalar (m = 1),
221// viz. sum-reduce[ x1, .. , xn ] = [ y1, .., ym ], where yi = sum_j x_j.
222class HVecSumReduce FINAL : public HVecUnaryOperation {
223 HVecSumReduce(ArenaAllocator* arena,
224 HInstruction* input,
225 Primitive::Type packed_type,
226 size_t vector_length,
227 uint32_t dex_pc = kNoDexPc)
228 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
229 DCHECK(input->IsVecOperation());
230 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
231 SetRawInputAt(0, input);
232 }
233
234 // TODO: probably integral promotion
235 Primitive::Type GetType() const OVERRIDE { return GetPackedType(); }
236
237 DECLARE_INSTRUCTION(VecSumReduce);
238 private:
239 DISALLOW_COPY_AND_ASSIGN(HVecSumReduce);
240};
241
242// Converts every component in the vector,
243// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
244class HVecCnv FINAL : public HVecUnaryOperation {
245 public:
246 HVecCnv(ArenaAllocator* arena,
247 HInstruction* input,
248 Primitive::Type packed_type,
249 size_t vector_length,
250 uint32_t dex_pc = kNoDexPc)
251 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
252 DCHECK(input->IsVecOperation());
253 DCHECK_NE(input->AsVecOperation()->GetPackedType(), packed_type); // actual convert
254 SetRawInputAt(0, input);
255 }
256
257 Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
258 Primitive::Type GetResultType() const { return GetPackedType(); }
259
260 DECLARE_INSTRUCTION(VecCnv);
261
262 private:
263 DISALLOW_COPY_AND_ASSIGN(HVecCnv);
264};
265
266// Negates every component in the vector,
267// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
268class HVecNeg FINAL : public HVecUnaryOperation {
269 public:
270 HVecNeg(ArenaAllocator* arena,
271 HInstruction* input,
272 Primitive::Type packed_type,
273 size_t vector_length,
274 uint32_t dex_pc = kNoDexPc)
275 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
276 DCHECK(input->IsVecOperation());
277 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
278 SetRawInputAt(0, input);
279 }
280 DECLARE_INSTRUCTION(VecNeg);
281 private:
282 DISALLOW_COPY_AND_ASSIGN(HVecNeg);
283};
284
Aart Bik6daebeb2017-04-03 14:35:41 -0700285// Takes absolute value of every component in the vector,
286// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ].
287class HVecAbs FINAL : public HVecUnaryOperation {
288 public:
289 HVecAbs(ArenaAllocator* arena,
290 HInstruction* input,
291 Primitive::Type packed_type,
292 size_t vector_length,
293 uint32_t dex_pc = kNoDexPc)
294 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
295 DCHECK(input->IsVecOperation());
296 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
297 SetRawInputAt(0, input);
298 }
299 DECLARE_INSTRUCTION(VecAbs);
300 private:
301 DISALLOW_COPY_AND_ASSIGN(HVecAbs);
302};
303
Aart Bikf8f5a162017-02-06 15:35:29 -0800304// Bitwise- or boolean-nots every component in the vector,
305// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
306// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
307class HVecNot FINAL : public HVecUnaryOperation {
308 public:
309 HVecNot(ArenaAllocator* arena,
310 HInstruction* input,
311 Primitive::Type packed_type,
312 size_t vector_length,
313 uint32_t dex_pc = kNoDexPc)
314 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
315 DCHECK(input->IsVecOperation());
316 SetRawInputAt(0, input);
317 }
318 DECLARE_INSTRUCTION(VecNot);
319 private:
320 DISALLOW_COPY_AND_ASSIGN(HVecNot);
321};
322
323// Adds every component in the two vectors,
324// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
325class HVecAdd FINAL : public HVecBinaryOperation {
326 public:
327 HVecAdd(ArenaAllocator* arena,
328 HInstruction* left,
329 HInstruction* right,
330 Primitive::Type packed_type,
331 size_t vector_length,
332 uint32_t dex_pc = kNoDexPc)
333 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
334 DCHECK(left->IsVecOperation() && right->IsVecOperation());
335 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
336 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
337 SetRawInputAt(0, left);
338 SetRawInputAt(1, right);
339 }
340 DECLARE_INSTRUCTION(VecAdd);
341 private:
342 DISALLOW_COPY_AND_ASSIGN(HVecAdd);
343};
344
Aart Bikf3e61ee2017-04-12 17:09:20 -0700345// Performs halving add on every component in the two vectors, viz.
346// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
347// or [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ]
348// for signed operands x, y (sign extension) or unsigned operands x, y (zero extension).
349class HVecHalvingAdd FINAL : public HVecBinaryOperation {
350 public:
351 HVecHalvingAdd(ArenaAllocator* arena,
352 HInstruction* left,
353 HInstruction* right,
354 Primitive::Type packed_type,
355 size_t vector_length,
356 bool is_unsigned,
357 bool is_rounded,
358 uint32_t dex_pc = kNoDexPc)
359 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc),
360 is_unsigned_(is_unsigned),
361 is_rounded_(is_rounded) {
362 DCHECK(left->IsVecOperation() && right->IsVecOperation());
363 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
364 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
365 SetRawInputAt(0, left);
366 SetRawInputAt(1, right);
367 }
368
369 bool IsUnsigned() const { return is_unsigned_; }
370 bool IsRounded() const { return is_rounded_; }
371
372 DECLARE_INSTRUCTION(VecHalvingAdd);
373
374 private:
375 bool is_unsigned_;
376 bool is_rounded_;
377
378 DISALLOW_COPY_AND_ASSIGN(HVecHalvingAdd);
379};
380
Aart Bikf8f5a162017-02-06 15:35:29 -0800381// Subtracts every component in the two vectors,
382// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
383class HVecSub FINAL : public HVecBinaryOperation {
384 public:
385 HVecSub(ArenaAllocator* arena,
386 HInstruction* left,
387 HInstruction* right,
388 Primitive::Type packed_type,
389 size_t vector_length,
390 uint32_t dex_pc = kNoDexPc)
391 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
392 DCHECK(left->IsVecOperation() && right->IsVecOperation());
393 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
394 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
395 SetRawInputAt(0, left);
396 SetRawInputAt(1, right);
397 }
398 DECLARE_INSTRUCTION(VecSub);
399 private:
400 DISALLOW_COPY_AND_ASSIGN(HVecSub);
401};
402
403// Multiplies every component in the two vectors,
404// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
405class HVecMul FINAL : public HVecBinaryOperation {
406 public:
407 HVecMul(ArenaAllocator* arena,
408 HInstruction* left,
409 HInstruction* right,
410 Primitive::Type packed_type,
411 size_t vector_length,
412 uint32_t dex_pc = kNoDexPc)
413 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
414 DCHECK(left->IsVecOperation() && right->IsVecOperation());
415 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
416 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
417 SetRawInputAt(0, left);
418 SetRawInputAt(1, right);
419 }
420 DECLARE_INSTRUCTION(VecMul);
421 private:
422 DISALLOW_COPY_AND_ASSIGN(HVecMul);
423};
424
425// Divides every component in the two vectors,
426// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
427class HVecDiv FINAL : public HVecBinaryOperation {
428 public:
429 HVecDiv(ArenaAllocator* arena,
430 HInstruction* left,
431 HInstruction* right,
432 Primitive::Type packed_type,
433 size_t vector_length,
434 uint32_t dex_pc = kNoDexPc)
435 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
436 DCHECK(left->IsVecOperation() && right->IsVecOperation());
437 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
438 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
439 SetRawInputAt(0, left);
440 SetRawInputAt(1, right);
441 }
442 DECLARE_INSTRUCTION(VecDiv);
443 private:
444 DISALLOW_COPY_AND_ASSIGN(HVecDiv);
445};
446
Aart Bikf3e61ee2017-04-12 17:09:20 -0700447// Takes minimum of every component in the two vectors,
448// viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ].
449class HVecMin FINAL : public HVecBinaryOperation {
450 public:
451 HVecMin(ArenaAllocator* arena,
452 HInstruction* left,
453 HInstruction* right,
454 Primitive::Type packed_type,
455 size_t vector_length,
456 uint32_t dex_pc = kNoDexPc)
457 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
458 DCHECK(left->IsVecOperation() && right->IsVecOperation());
459 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
460 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
461 SetRawInputAt(0, left);
462 SetRawInputAt(1, right);
463 }
464 DECLARE_INSTRUCTION(VecMin);
465 private:
466 DISALLOW_COPY_AND_ASSIGN(HVecMin);
467};
468
469// Takes maximum of every component in the two vectors,
470// viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ].
471class HVecMax FINAL : public HVecBinaryOperation {
472 public:
473 HVecMax(ArenaAllocator* arena,
474 HInstruction* left,
475 HInstruction* right,
476 Primitive::Type packed_type,
477 size_t vector_length,
478 uint32_t dex_pc = kNoDexPc)
479 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
480 DCHECK(left->IsVecOperation() && right->IsVecOperation());
481 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
482 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
483 SetRawInputAt(0, left);
484 SetRawInputAt(1, right);
485 }
486 DECLARE_INSTRUCTION(VecMax);
487 private:
488 DISALLOW_COPY_AND_ASSIGN(HVecMax);
489};
490
Aart Bikf8f5a162017-02-06 15:35:29 -0800491// Bitwise-ands every component in the two vectors,
492// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
493class HVecAnd FINAL : public HVecBinaryOperation {
494 public:
495 HVecAnd(ArenaAllocator* arena,
496 HInstruction* left,
497 HInstruction* right,
498 Primitive::Type packed_type,
499 size_t vector_length,
500 uint32_t dex_pc = kNoDexPc)
501 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
502 DCHECK(left->IsVecOperation() && right->IsVecOperation());
503 SetRawInputAt(0, left);
504 SetRawInputAt(1, right);
505 }
506 DECLARE_INSTRUCTION(VecAnd);
507 private:
508 DISALLOW_COPY_AND_ASSIGN(HVecAnd);
509};
510
511// Bitwise-and-nots every component in the two vectors,
512// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
513class HVecAndNot FINAL : public HVecBinaryOperation {
514 public:
515 HVecAndNot(ArenaAllocator* arena,
516 HInstruction* left,
517 HInstruction* right,
518 Primitive::Type packed_type,
519 size_t vector_length,
520 uint32_t dex_pc = kNoDexPc)
521 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
522 DCHECK(left->IsVecOperation() && right->IsVecOperation());
523 SetRawInputAt(0, left);
524 SetRawInputAt(1, right);
525 }
526 DECLARE_INSTRUCTION(VecAndNot);
527 private:
528 DISALLOW_COPY_AND_ASSIGN(HVecAndNot);
529};
530
531// Bitwise-ors every component in the two vectors,
532// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
533class HVecOr FINAL : public HVecBinaryOperation {
534 public:
535 HVecOr(ArenaAllocator* arena,
536 HInstruction* left,
537 HInstruction* right,
538 Primitive::Type packed_type,
539 size_t vector_length,
540 uint32_t dex_pc = kNoDexPc)
541 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
542 DCHECK(left->IsVecOperation() && right->IsVecOperation());
543 SetRawInputAt(0, left);
544 SetRawInputAt(1, right);
545 }
546 DECLARE_INSTRUCTION(VecOr);
547 private:
548 DISALLOW_COPY_AND_ASSIGN(HVecOr);
549};
550
551// Bitwise-xors every component in the two vectors,
552// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
553class HVecXor FINAL : public HVecBinaryOperation {
554 public:
555 HVecXor(ArenaAllocator* arena,
556 HInstruction* left,
557 HInstruction* right,
558 Primitive::Type packed_type,
559 size_t vector_length,
560 uint32_t dex_pc = kNoDexPc)
561 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
562 DCHECK(left->IsVecOperation() && right->IsVecOperation());
563 SetRawInputAt(0, left);
564 SetRawInputAt(1, right);
565 }
566 DECLARE_INSTRUCTION(VecXor);
567 private:
568 DISALLOW_COPY_AND_ASSIGN(HVecXor);
569};
570
571// Logically shifts every component in the vector left by the given distance,
572// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
573class HVecShl FINAL : public HVecBinaryOperation {
574 public:
575 HVecShl(ArenaAllocator* arena,
576 HInstruction* left,
577 HInstruction* right,
578 Primitive::Type packed_type,
579 size_t vector_length,
580 uint32_t dex_pc = kNoDexPc)
581 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
582 DCHECK(left->IsVecOperation());
583 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
584 SetRawInputAt(0, left);
585 SetRawInputAt(1, right);
586 }
587 DECLARE_INSTRUCTION(VecShl);
588 private:
589 DISALLOW_COPY_AND_ASSIGN(HVecShl);
590};
591
592// Arithmetically shifts every component in the vector right by the given distance,
593// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
594class HVecShr FINAL : public HVecBinaryOperation {
595 public:
596 HVecShr(ArenaAllocator* arena,
597 HInstruction* left,
598 HInstruction* right,
599 Primitive::Type packed_type,
600 size_t vector_length,
601 uint32_t dex_pc = kNoDexPc)
602 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
603 DCHECK(left->IsVecOperation());
604 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
605 SetRawInputAt(0, left);
606 SetRawInputAt(1, right);
607 }
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)
623 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
624 DCHECK(left->IsVecOperation());
625 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
626 SetRawInputAt(0, left);
627 SetRawInputAt(1, right);
628 }
629 DECLARE_INSTRUCTION(VecUShr);
630 private:
631 DISALLOW_COPY_AND_ASSIGN(HVecUShr);
632};
633
Artem Serovf34dd202017-04-10 17:41:46 +0100634// Multiplies every component in the two vectors, adds the result vector to the accumulator vector.
635// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] =
636// [ acc1 + x1 * y1, .. , accn + xn * yn ].
637class HVecMultiplyAccumulate FINAL : public HVecOperation {
638 public:
639 HVecMultiplyAccumulate(ArenaAllocator* arena,
640 InstructionKind op,
641 HInstruction* accumulator,
642 HInstruction* mul_left,
643 HInstruction* mul_right,
644 Primitive::Type packed_type,
645 size_t vector_length,
646 uint32_t dex_pc = kNoDexPc)
647 : HVecOperation(arena,
648 packed_type,
649 SideEffects::None(),
650 /*number_of_inputs*/ 3,
651 vector_length,
652 dex_pc),
653 op_kind_(op) {
654 DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
655 DCHECK(accumulator->IsVecOperation());
656 DCHECK(mul_left->IsVecOperation() && mul_right->IsVecOperation());
657 DCHECK_EQ(accumulator->AsVecOperation()->GetPackedType(), packed_type);
658 DCHECK_EQ(mul_left->AsVecOperation()->GetPackedType(), packed_type);
659 DCHECK_EQ(mul_right->AsVecOperation()->GetPackedType(), packed_type);
660
661 SetRawInputAt(kInputAccumulatorIndex, accumulator);
662 SetRawInputAt(kInputMulLeftIndex, mul_left);
663 SetRawInputAt(kInputMulRightIndex, mul_right);
664 }
665
666 static constexpr int kInputAccumulatorIndex = 0;
667 static constexpr int kInputMulLeftIndex = 1;
668 static constexpr int kInputMulRightIndex = 2;
669
670 bool CanBeMoved() const OVERRIDE { return true; }
671
672 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
673 return op_kind_ == other->AsVecMultiplyAccumulate()->op_kind_;
674 }
675
676 InstructionKind GetOpKind() const { return op_kind_; }
677
678 DECLARE_INSTRUCTION(VecMultiplyAccumulate);
679
680 private:
681 // Indicates if this is a MADD or MSUB.
682 const InstructionKind op_kind_;
683
684 DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate);
685};
686
Aart Bikf8f5a162017-02-06 15:35:29 -0800687// Loads a vector from memory, viz. load(mem, 1)
688// yield the vector [ mem(1), .. , mem(n) ].
689class HVecLoad FINAL : public HVecMemoryOperation {
690 public:
691 HVecLoad(ArenaAllocator* arena,
692 HInstruction* base,
693 HInstruction* index,
694 Primitive::Type packed_type,
695 size_t vector_length,
696 uint32_t dex_pc = kNoDexPc)
697 : HVecMemoryOperation(arena,
698 packed_type,
699 SideEffects::ArrayReadOfType(packed_type),
700 /*number_of_inputs*/ 2,
701 vector_length,
702 dex_pc) {
703 SetRawInputAt(0, base);
704 SetRawInputAt(1, index);
705 }
706 DECLARE_INSTRUCTION(VecLoad);
707 private:
708 DISALLOW_COPY_AND_ASSIGN(HVecLoad);
709};
710
711// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
712// sets mem(1) = x1, .. , mem(n) = xn.
713class HVecStore FINAL : public HVecMemoryOperation {
714 public:
715 HVecStore(ArenaAllocator* arena,
716 HInstruction* base,
717 HInstruction* index,
718 HInstruction* value,
719 Primitive::Type packed_type,
720 size_t vector_length,
721 uint32_t dex_pc = kNoDexPc)
722 : HVecMemoryOperation(arena,
723 packed_type,
724 SideEffects::ArrayWriteOfType(packed_type),
725 /*number_of_inputs*/ 3,
726 vector_length,
727 dex_pc) {
728 DCHECK(value->IsVecOperation());
729 DCHECK_EQ(value->AsVecOperation()->GetPackedType(), packed_type);
730 SetRawInputAt(0, base);
731 SetRawInputAt(1, index);
732 SetRawInputAt(2, value);
733 }
734 DECLARE_INSTRUCTION(VecStore);
735 private:
736 DISALLOW_COPY_AND_ASSIGN(HVecStore);
737};
738
739} // namespace art
740
741#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_