blob: 0cbbf2a215090c8d7b1c608b14e67923d7f6f15d [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) { }
146 DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
147 private:
148 DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation);
149};
150
151// Abstraction of a vector operation that references memory, with an alignment.
152// The Android runtime guarantees at least "component size" alignment for array
153// elements and, thus, vectors.
154class HVecMemoryOperation : public HVecOperation {
155 public:
156 HVecMemoryOperation(ArenaAllocator* arena,
157 Primitive::Type packed_type,
158 SideEffects side_effects,
159 size_t number_of_inputs,
160 size_t vector_length,
161 uint32_t dex_pc)
162 : HVecOperation(arena, packed_type, side_effects, number_of_inputs, vector_length, dex_pc),
163 alignment_(Primitive::ComponentSize(packed_type), 0) { }
164
165 void SetAlignment(Alignment alignment) { alignment_ = alignment; }
166
167 Alignment GetAlignment() const { return alignment_; }
168
169 DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
170
171 private:
172 Alignment alignment_;
173
174 DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
175};
176
177//
178// Definitions of concrete vector operations in HIR.
179//
180
181// Replicates the given scalar into a vector,
182// viz. replicate(x) = [ x, .. , x ].
183class HVecReplicateScalar FINAL : public HVecUnaryOperation {
184 public:
185 HVecReplicateScalar(ArenaAllocator* arena,
186 HInstruction* scalar,
187 Primitive::Type packed_type,
188 size_t vector_length,
189 uint32_t dex_pc = kNoDexPc)
190 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
191 SetRawInputAt(0, scalar);
192 }
193 DECLARE_INSTRUCTION(VecReplicateScalar);
194 private:
195 DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
196};
197
198// Assigns the given scalar elements to a vector,
199// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
200class HVecSetScalars FINAL : public HVecUnaryOperation {
201 HVecSetScalars(ArenaAllocator* arena,
202 HInstruction** scalars, // array
203 Primitive::Type packed_type,
204 size_t vector_length,
205 uint32_t dex_pc = kNoDexPc)
206 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
207 for (size_t i = 0; i < vector_length; i++) {
208 SetRawInputAt(0, scalars[i]);
209 }
210 }
211 DECLARE_INSTRUCTION(VecSetScalars);
212 private:
213 DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
214};
215
216// 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)
224 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
225 DCHECK(input->IsVecOperation());
226 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
227 SetRawInputAt(0, input);
228 }
229
230 // TODO: probably integral promotion
231 Primitive::Type GetType() const OVERRIDE { return GetPackedType(); }
232
233 DECLARE_INSTRUCTION(VecSumReduce);
234 private:
235 DISALLOW_COPY_AND_ASSIGN(HVecSumReduce);
236};
237
238// Converts every component in the vector,
239// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
240class HVecCnv FINAL : public HVecUnaryOperation {
241 public:
242 HVecCnv(ArenaAllocator* arena,
243 HInstruction* input,
244 Primitive::Type packed_type,
245 size_t vector_length,
246 uint32_t dex_pc = kNoDexPc)
247 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
248 DCHECK(input->IsVecOperation());
249 DCHECK_NE(input->AsVecOperation()->GetPackedType(), packed_type); // actual convert
250 SetRawInputAt(0, input);
251 }
252
253 Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
254 Primitive::Type GetResultType() const { return GetPackedType(); }
255
256 DECLARE_INSTRUCTION(VecCnv);
257
258 private:
259 DISALLOW_COPY_AND_ASSIGN(HVecCnv);
260};
261
262// Negates every component in the vector,
263// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
264class HVecNeg FINAL : public HVecUnaryOperation {
265 public:
266 HVecNeg(ArenaAllocator* arena,
267 HInstruction* input,
268 Primitive::Type packed_type,
269 size_t vector_length,
270 uint32_t dex_pc = kNoDexPc)
271 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
272 DCHECK(input->IsVecOperation());
273 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
274 SetRawInputAt(0, input);
275 }
276 DECLARE_INSTRUCTION(VecNeg);
277 private:
278 DISALLOW_COPY_AND_ASSIGN(HVecNeg);
279};
280
Aart Bik6daebeb2017-04-03 14:35:41 -0700281// Takes absolute value of every component in the vector,
282// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ].
283class HVecAbs FINAL : public HVecUnaryOperation {
284 public:
285 HVecAbs(ArenaAllocator* arena,
286 HInstruction* input,
287 Primitive::Type packed_type,
288 size_t vector_length,
289 uint32_t dex_pc = kNoDexPc)
290 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
291 DCHECK(input->IsVecOperation());
292 DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
293 SetRawInputAt(0, input);
294 }
295 DECLARE_INSTRUCTION(VecAbs);
296 private:
297 DISALLOW_COPY_AND_ASSIGN(HVecAbs);
298};
299
Aart Bikf8f5a162017-02-06 15:35:29 -0800300// Bitwise- or boolean-nots every component in the vector,
301// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
302// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
303class HVecNot FINAL : public HVecUnaryOperation {
304 public:
305 HVecNot(ArenaAllocator* arena,
306 HInstruction* input,
307 Primitive::Type packed_type,
308 size_t vector_length,
309 uint32_t dex_pc = kNoDexPc)
310 : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) {
311 DCHECK(input->IsVecOperation());
312 SetRawInputAt(0, input);
313 }
314 DECLARE_INSTRUCTION(VecNot);
315 private:
316 DISALLOW_COPY_AND_ASSIGN(HVecNot);
317};
318
319// Adds every component in the two vectors,
320// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
321class HVecAdd FINAL : public HVecBinaryOperation {
322 public:
323 HVecAdd(ArenaAllocator* arena,
324 HInstruction* left,
325 HInstruction* right,
326 Primitive::Type packed_type,
327 size_t vector_length,
328 uint32_t dex_pc = kNoDexPc)
329 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
330 DCHECK(left->IsVecOperation() && right->IsVecOperation());
331 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
332 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
333 SetRawInputAt(0, left);
334 SetRawInputAt(1, right);
335 }
336 DECLARE_INSTRUCTION(VecAdd);
337 private:
338 DISALLOW_COPY_AND_ASSIGN(HVecAdd);
339};
340
341// Subtracts every component in the two vectors,
342// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
343class HVecSub FINAL : public HVecBinaryOperation {
344 public:
345 HVecSub(ArenaAllocator* arena,
346 HInstruction* left,
347 HInstruction* right,
348 Primitive::Type packed_type,
349 size_t vector_length,
350 uint32_t dex_pc = kNoDexPc)
351 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
352 DCHECK(left->IsVecOperation() && right->IsVecOperation());
353 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
354 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
355 SetRawInputAt(0, left);
356 SetRawInputAt(1, right);
357 }
358 DECLARE_INSTRUCTION(VecSub);
359 private:
360 DISALLOW_COPY_AND_ASSIGN(HVecSub);
361};
362
363// Multiplies every component in the two vectors,
364// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
365class HVecMul FINAL : public HVecBinaryOperation {
366 public:
367 HVecMul(ArenaAllocator* arena,
368 HInstruction* left,
369 HInstruction* right,
370 Primitive::Type packed_type,
371 size_t vector_length,
372 uint32_t dex_pc = kNoDexPc)
373 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
374 DCHECK(left->IsVecOperation() && right->IsVecOperation());
375 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
376 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
377 SetRawInputAt(0, left);
378 SetRawInputAt(1, right);
379 }
380 DECLARE_INSTRUCTION(VecMul);
381 private:
382 DISALLOW_COPY_AND_ASSIGN(HVecMul);
383};
384
385// Divides every component in the two vectors,
386// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
387class HVecDiv FINAL : public HVecBinaryOperation {
388 public:
389 HVecDiv(ArenaAllocator* arena,
390 HInstruction* left,
391 HInstruction* right,
392 Primitive::Type packed_type,
393 size_t vector_length,
394 uint32_t dex_pc = kNoDexPc)
395 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
396 DCHECK(left->IsVecOperation() && right->IsVecOperation());
397 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
398 DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
399 SetRawInputAt(0, left);
400 SetRawInputAt(1, right);
401 }
402 DECLARE_INSTRUCTION(VecDiv);
403 private:
404 DISALLOW_COPY_AND_ASSIGN(HVecDiv);
405};
406
407// Bitwise-ands every component in the two vectors,
408// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
409class HVecAnd FINAL : public HVecBinaryOperation {
410 public:
411 HVecAnd(ArenaAllocator* arena,
412 HInstruction* left,
413 HInstruction* right,
414 Primitive::Type packed_type,
415 size_t vector_length,
416 uint32_t dex_pc = kNoDexPc)
417 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
418 DCHECK(left->IsVecOperation() && right->IsVecOperation());
419 SetRawInputAt(0, left);
420 SetRawInputAt(1, right);
421 }
422 DECLARE_INSTRUCTION(VecAnd);
423 private:
424 DISALLOW_COPY_AND_ASSIGN(HVecAnd);
425};
426
427// Bitwise-and-nots every component in the two vectors,
428// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
429class HVecAndNot FINAL : public HVecBinaryOperation {
430 public:
431 HVecAndNot(ArenaAllocator* arena,
432 HInstruction* left,
433 HInstruction* right,
434 Primitive::Type packed_type,
435 size_t vector_length,
436 uint32_t dex_pc = kNoDexPc)
437 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
438 DCHECK(left->IsVecOperation() && right->IsVecOperation());
439 SetRawInputAt(0, left);
440 SetRawInputAt(1, right);
441 }
442 DECLARE_INSTRUCTION(VecAndNot);
443 private:
444 DISALLOW_COPY_AND_ASSIGN(HVecAndNot);
445};
446
447// Bitwise-ors every component in the two vectors,
448// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
449class HVecOr FINAL : public HVecBinaryOperation {
450 public:
451 HVecOr(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 SetRawInputAt(0, left);
460 SetRawInputAt(1, right);
461 }
462 DECLARE_INSTRUCTION(VecOr);
463 private:
464 DISALLOW_COPY_AND_ASSIGN(HVecOr);
465};
466
467// Bitwise-xors every component in the two vectors,
468// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
469class HVecXor FINAL : public HVecBinaryOperation {
470 public:
471 HVecXor(ArenaAllocator* arena,
472 HInstruction* left,
473 HInstruction* right,
474 Primitive::Type packed_type,
475 size_t vector_length,
476 uint32_t dex_pc = kNoDexPc)
477 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
478 DCHECK(left->IsVecOperation() && right->IsVecOperation());
479 SetRawInputAt(0, left);
480 SetRawInputAt(1, right);
481 }
482 DECLARE_INSTRUCTION(VecXor);
483 private:
484 DISALLOW_COPY_AND_ASSIGN(HVecXor);
485};
486
487// Logically shifts every component in the vector left by the given distance,
488// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
489class HVecShl FINAL : public HVecBinaryOperation {
490 public:
491 HVecShl(ArenaAllocator* arena,
492 HInstruction* left,
493 HInstruction* right,
494 Primitive::Type packed_type,
495 size_t vector_length,
496 uint32_t dex_pc = kNoDexPc)
497 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
498 DCHECK(left->IsVecOperation());
499 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
500 SetRawInputAt(0, left);
501 SetRawInputAt(1, right);
502 }
503 DECLARE_INSTRUCTION(VecShl);
504 private:
505 DISALLOW_COPY_AND_ASSIGN(HVecShl);
506};
507
508// Arithmetically shifts every component in the vector right by the given distance,
509// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
510class HVecShr FINAL : public HVecBinaryOperation {
511 public:
512 HVecShr(ArenaAllocator* arena,
513 HInstruction* left,
514 HInstruction* right,
515 Primitive::Type packed_type,
516 size_t vector_length,
517 uint32_t dex_pc = kNoDexPc)
518 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
519 DCHECK(left->IsVecOperation());
520 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
521 SetRawInputAt(0, left);
522 SetRawInputAt(1, right);
523 }
524 DECLARE_INSTRUCTION(VecShr);
525 private:
526 DISALLOW_COPY_AND_ASSIGN(HVecShr);
527};
528
529// Logically shifts every component in the vector right by the given distance,
530// viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
531class HVecUShr FINAL : public HVecBinaryOperation {
532 public:
533 HVecUShr(ArenaAllocator* arena,
534 HInstruction* left,
535 HInstruction* right,
536 Primitive::Type packed_type,
537 size_t vector_length,
538 uint32_t dex_pc = kNoDexPc)
539 : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) {
540 DCHECK(left->IsVecOperation());
541 DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
542 SetRawInputAt(0, left);
543 SetRawInputAt(1, right);
544 }
545 DECLARE_INSTRUCTION(VecUShr);
546 private:
547 DISALLOW_COPY_AND_ASSIGN(HVecUShr);
548};
549
550// Loads a vector from memory, viz. load(mem, 1)
551// yield the vector [ mem(1), .. , mem(n) ].
552class HVecLoad FINAL : public HVecMemoryOperation {
553 public:
554 HVecLoad(ArenaAllocator* arena,
555 HInstruction* base,
556 HInstruction* index,
557 Primitive::Type packed_type,
558 size_t vector_length,
559 uint32_t dex_pc = kNoDexPc)
560 : HVecMemoryOperation(arena,
561 packed_type,
562 SideEffects::ArrayReadOfType(packed_type),
563 /*number_of_inputs*/ 2,
564 vector_length,
565 dex_pc) {
566 SetRawInputAt(0, base);
567 SetRawInputAt(1, index);
568 }
569 DECLARE_INSTRUCTION(VecLoad);
570 private:
571 DISALLOW_COPY_AND_ASSIGN(HVecLoad);
572};
573
574// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
575// sets mem(1) = x1, .. , mem(n) = xn.
576class HVecStore FINAL : public HVecMemoryOperation {
577 public:
578 HVecStore(ArenaAllocator* arena,
579 HInstruction* base,
580 HInstruction* index,
581 HInstruction* value,
582 Primitive::Type packed_type,
583 size_t vector_length,
584 uint32_t dex_pc = kNoDexPc)
585 : HVecMemoryOperation(arena,
586 packed_type,
587 SideEffects::ArrayWriteOfType(packed_type),
588 /*number_of_inputs*/ 3,
589 vector_length,
590 dex_pc) {
591 DCHECK(value->IsVecOperation());
592 DCHECK_EQ(value->AsVecOperation()->GetPackedType(), packed_type);
593 SetRawInputAt(0, base);
594 SetRawInputAt(1, index);
595 SetRawInputAt(2, value);
596 }
597 DECLARE_INSTRUCTION(VecStore);
598 private:
599 DISALLOW_COPY_AND_ASSIGN(HVecStore);
600};
601
602} // namespace art
603
604#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_