blob: 6261171a00a5e8f10e5a77414d09500b3172ca88 [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
Aart Bikb79f4ac2017-07-10 10:10:37 -070049 bool operator==(const Alignment& other) const {
50 return base_ == other.base_ && offset_ == other.offset_;
51 }
52
Aart Bikf8f5a162017-02-06 15:35:29 -080053 private:
54 size_t base_;
55 size_t offset_;
56};
57
58//
59// Definitions of abstract vector operations in HIR.
60//
61
62// Abstraction of a vector operation, i.e., an operation that performs
63// GetVectorLength() x GetPackedType() operations simultaneously.
64class HVecOperation : public HVariableInputSizeInstruction {
65 public:
66 HVecOperation(ArenaAllocator* arena,
67 Primitive::Type packed_type,
68 SideEffects side_effects,
69 size_t number_of_inputs,
70 size_t vector_length,
71 uint32_t dex_pc)
72 : HVariableInputSizeInstruction(side_effects,
73 dex_pc,
74 arena,
75 number_of_inputs,
76 kArenaAllocVectorNode),
77 vector_length_(vector_length) {
78 SetPackedField<TypeField>(packed_type);
79 DCHECK_LT(1u, vector_length);
80 }
81
82 // Returns the number of elements packed in a vector.
83 size_t GetVectorLength() const {
84 return vector_length_;
85 }
86
87 // Returns the number of bytes in a full vector.
88 size_t GetVectorNumberOfBytes() const {
89 return vector_length_ * Primitive::ComponentSize(GetPackedType());
90 }
91
Aart Bika57b4ee2017-08-30 21:21:41 +000092 // Returns the type of the vector operation: a SIMD operation looks like a FPU location.
93 // TODO: we could introduce SIMD types in HIR.
Aart Bikf8f5a162017-02-06 15:35:29 -080094 Primitive::Type GetType() const OVERRIDE {
Aart Bika57b4ee2017-08-30 21:21:41 +000095 return Primitive::kPrimDouble;
Aart Bikf8f5a162017-02-06 15:35:29 -080096 }
97
98 // Returns the true component type packed in a vector.
99 Primitive::Type GetPackedType() const {
100 return GetPackedField<TypeField>();
101 }
102
Aart Bikb79f4ac2017-07-10 10:10:37 -0700103 // Assumes vector nodes cannot be moved by default. Each concrete implementation
104 // that can be moved should override this method and return true.
105 bool CanBeMoved() const OVERRIDE { return false; }
106
107 // Tests if all data of a vector node (vector length and packed type) is equal.
108 // Each concrete implementation that adds more fields should test equality of
109 // those fields in its own method *and* call all super methods.
110 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
111 DCHECK(other->IsVecOperation());
112 const HVecOperation* o = other->AsVecOperation();
113 return GetVectorLength() == o->GetVectorLength() && GetPackedType() == o->GetPackedType();
114 }
115
Aart Bikf8f5a162017-02-06 15:35:29 -0800116 DECLARE_ABSTRACT_INSTRUCTION(VecOperation);
117
Aart Bikdb14fcf2017-04-25 15:53:58 -0700118 protected:
Aart Bikf8f5a162017-02-06 15:35:29 -0800119 // Additional packed bits.
120 static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits;
121 static constexpr size_t kFieldTypeSize =
122 MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast));
123 static constexpr size_t kNumberOfVectorOpPackedBits = kFieldType + kFieldTypeSize;
124 static_assert(kNumberOfVectorOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
125 using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>;
126
Aart Bikdb14fcf2017-04-25 15:53:58 -0700127 private:
Aart Bikf8f5a162017-02-06 15:35:29 -0800128 const size_t vector_length_;
129
130 DISALLOW_COPY_AND_ASSIGN(HVecOperation);
131};
132
133// Abstraction of a unary vector operation.
134class HVecUnaryOperation : public HVecOperation {
135 public:
136 HVecUnaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700137 HInstruction* input,
Aart Bikf8f5a162017-02-06 15:35:29 -0800138 Primitive::Type packed_type,
139 size_t vector_length,
140 uint32_t dex_pc)
141 : HVecOperation(arena,
142 packed_type,
143 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700144 /* number_of_inputs */ 1,
Aart Bikf8f5a162017-02-06 15:35:29 -0800145 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700146 dex_pc) {
147 SetRawInputAt(0, input);
148 }
149
150 HInstruction* GetInput() const { return InputAt(0); }
151
Aart Bikf8f5a162017-02-06 15:35:29 -0800152 DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700153
Aart Bikf8f5a162017-02-06 15:35:29 -0800154 private:
155 DISALLOW_COPY_AND_ASSIGN(HVecUnaryOperation);
156};
157
158// Abstraction of a binary vector operation.
159class HVecBinaryOperation : public HVecOperation {
160 public:
161 HVecBinaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700162 HInstruction* left,
163 HInstruction* right,
Aart Bikf8f5a162017-02-06 15:35:29 -0800164 Primitive::Type packed_type,
165 size_t vector_length,
166 uint32_t dex_pc)
167 : HVecOperation(arena,
168 packed_type,
169 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700170 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800171 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700172 dex_pc) {
173 SetRawInputAt(0, left);
174 SetRawInputAt(1, right);
175 }
Artem Serovf34dd202017-04-10 17:41:46 +0100176
177 HInstruction* GetLeft() const { return InputAt(0); }
178 HInstruction* GetRight() const { return InputAt(1); }
179
Aart Bikf8f5a162017-02-06 15:35:29 -0800180 DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700181
Aart Bikf8f5a162017-02-06 15:35:29 -0800182 private:
183 DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation);
184};
185
186// Abstraction of a vector operation that references memory, with an alignment.
187// The Android runtime guarantees at least "component size" alignment for array
188// elements and, thus, vectors.
189class HVecMemoryOperation : public HVecOperation {
190 public:
191 HVecMemoryOperation(ArenaAllocator* arena,
192 Primitive::Type packed_type,
193 SideEffects side_effects,
194 size_t number_of_inputs,
195 size_t vector_length,
196 uint32_t dex_pc)
197 : HVecOperation(arena, packed_type, side_effects, number_of_inputs, vector_length, dex_pc),
Artem Serove1811ed2017-04-27 16:50:47 +0100198 alignment_(Primitive::ComponentSize(packed_type), 0) {
199 DCHECK_GE(number_of_inputs, 2u);
200 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800201
202 void SetAlignment(Alignment alignment) { alignment_ = alignment; }
203
204 Alignment GetAlignment() const { return alignment_; }
205
Artem Serove1811ed2017-04-27 16:50:47 +0100206 HInstruction* GetArray() const { return InputAt(0); }
207 HInstruction* GetIndex() const { return InputAt(1); }
208
Aart Bikb79f4ac2017-07-10 10:10:37 -0700209 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
210 DCHECK(other->IsVecMemoryOperation());
211 const HVecMemoryOperation* o = other->AsVecMemoryOperation();
212 return HVecOperation::InstructionDataEquals(o) && GetAlignment() == o->GetAlignment();
213 }
214
Aart Bikf8f5a162017-02-06 15:35:29 -0800215 DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
216
217 private:
218 Alignment alignment_;
219
220 DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
221};
222
Aart Bika57b4ee2017-08-30 21:21:41 +0000223// Packed type consistency checker (same vector length integral types may mix freely).
Aart Bikd58bc322017-05-01 14:49:18 -0700224inline static bool HasConsistentPackedTypes(HInstruction* input, Primitive::Type type) {
225 DCHECK(input->IsVecOperation());
226 Primitive::Type input_type = input->AsVecOperation()->GetPackedType();
227 switch (input_type) {
228 case Primitive::kPrimBoolean:
229 case Primitive::kPrimByte:
230 return type == Primitive::kPrimBoolean ||
231 type == Primitive::kPrimByte;
232 case Primitive::kPrimChar:
233 case Primitive::kPrimShort:
234 return type == Primitive::kPrimChar ||
235 type == Primitive::kPrimShort;
236 default:
237 return type == input_type;
238 }
239}
240
Aart Bikf8f5a162017-02-06 15:35:29 -0800241//
Aart Bik8de59162017-04-21 09:42:01 -0700242// Definitions of concrete unary vector operations in HIR.
Aart Bikf8f5a162017-02-06 15:35:29 -0800243//
244
245// Replicates the given scalar into a vector,
246// viz. replicate(x) = [ x, .. , x ].
247class HVecReplicateScalar FINAL : public HVecUnaryOperation {
248 public:
249 HVecReplicateScalar(ArenaAllocator* arena,
250 HInstruction* scalar,
251 Primitive::Type packed_type,
252 size_t vector_length,
253 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700254 : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) {
255 DCHECK(!scalar->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800256 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700257
258 // A replicate needs to stay in place, since SIMD registers are not
259 // kept alive across vector loop boundaries (yet).
260 bool CanBeMoved() const OVERRIDE { return false; }
261
Aart Bikf8f5a162017-02-06 15:35:29 -0800262 DECLARE_INSTRUCTION(VecReplicateScalar);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700263
Aart Bikf8f5a162017-02-06 15:35:29 -0800264 private:
265 DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
266};
267
Aart Bika57b4ee2017-08-30 21:21:41 +0000268// Sum-reduces the given vector into a shorter vector (m < n) or scalar (m = 1),
269// viz. sum-reduce[ x1, .. , xn ] = [ y1, .., ym ], where yi = sum_j x_j.
270class HVecSumReduce FINAL : public HVecUnaryOperation {
271 HVecSumReduce(ArenaAllocator* arena,
272 HInstruction* input,
273 Primitive::Type packed_type,
274 size_t vector_length,
275 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700276 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700277 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik9879d0e2017-08-15 10:51:25 -0700278 }
279
Aart Bika57b4ee2017-08-30 21:21:41 +0000280 // TODO: probably integral promotion
281 Primitive::Type GetType() const OVERRIDE { return GetPackedType(); }
Aart Bikf8f5a162017-02-06 15:35:29 -0800282
Aart Bikb79f4ac2017-07-10 10:10:37 -0700283 bool CanBeMoved() const OVERRIDE { return true; }
284
Aart Bika57b4ee2017-08-30 21:21:41 +0000285 DECLARE_INSTRUCTION(VecSumReduce);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700286
Aart Bikf8f5a162017-02-06 15:35:29 -0800287 private:
Aart Bika57b4ee2017-08-30 21:21:41 +0000288 DISALLOW_COPY_AND_ASSIGN(HVecSumReduce);
Aart Bikf8f5a162017-02-06 15:35:29 -0800289};
290
291// Converts every component in the vector,
292// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
293class HVecCnv FINAL : public HVecUnaryOperation {
294 public:
295 HVecCnv(ArenaAllocator* arena,
296 HInstruction* input,
297 Primitive::Type packed_type,
298 size_t vector_length,
299 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700300 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800301 DCHECK(input->IsVecOperation());
Aart Bikd58bc322017-05-01 14:49:18 -0700302 DCHECK_NE(GetInputType(), GetResultType()); // actual convert
Aart Bikf8f5a162017-02-06 15:35:29 -0800303 }
304
305 Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
306 Primitive::Type GetResultType() const { return GetPackedType(); }
307
Aart Bikb79f4ac2017-07-10 10:10:37 -0700308 bool CanBeMoved() const OVERRIDE { return true; }
309
Aart Bikf8f5a162017-02-06 15:35:29 -0800310 DECLARE_INSTRUCTION(VecCnv);
311
312 private:
313 DISALLOW_COPY_AND_ASSIGN(HVecCnv);
314};
315
316// Negates every component in the vector,
317// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
318class HVecNeg FINAL : public HVecUnaryOperation {
319 public:
320 HVecNeg(ArenaAllocator* arena,
321 HInstruction* input,
322 Primitive::Type packed_type,
323 size_t vector_length,
324 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700325 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700326 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800327 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700328
329 bool CanBeMoved() const OVERRIDE { return true; }
330
Aart Bikf8f5a162017-02-06 15:35:29 -0800331 DECLARE_INSTRUCTION(VecNeg);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700332
Aart Bikf8f5a162017-02-06 15:35:29 -0800333 private:
334 DISALLOW_COPY_AND_ASSIGN(HVecNeg);
335};
336
Aart Bik6daebeb2017-04-03 14:35:41 -0700337// Takes absolute value of every component in the vector,
338// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ].
339class HVecAbs FINAL : public HVecUnaryOperation {
340 public:
341 HVecAbs(ArenaAllocator* arena,
342 HInstruction* input,
343 Primitive::Type packed_type,
344 size_t vector_length,
345 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700346 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700347 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik6daebeb2017-04-03 14:35:41 -0700348 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700349
350 bool CanBeMoved() const OVERRIDE { return true; }
351
Aart Bik6daebeb2017-04-03 14:35:41 -0700352 DECLARE_INSTRUCTION(VecAbs);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700353
Aart Bik6daebeb2017-04-03 14:35:41 -0700354 private:
355 DISALLOW_COPY_AND_ASSIGN(HVecAbs);
356};
357
Aart Bikf8f5a162017-02-06 15:35:29 -0800358// Bitwise- or boolean-nots every component in the vector,
359// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
360// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
361class HVecNot FINAL : public HVecUnaryOperation {
362 public:
363 HVecNot(ArenaAllocator* arena,
364 HInstruction* input,
365 Primitive::Type packed_type,
366 size_t vector_length,
367 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700368 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800369 DCHECK(input->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800370 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700371
372 bool CanBeMoved() const OVERRIDE { return true; }
373
Aart Bikf8f5a162017-02-06 15:35:29 -0800374 DECLARE_INSTRUCTION(VecNot);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700375
Aart Bikf8f5a162017-02-06 15:35:29 -0800376 private:
377 DISALLOW_COPY_AND_ASSIGN(HVecNot);
378};
379
Aart Bik8de59162017-04-21 09:42:01 -0700380//
381// Definitions of concrete binary vector operations in HIR.
382//
383
Aart Bikf8f5a162017-02-06 15:35:29 -0800384// Adds every component in the two vectors,
385// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
386class HVecAdd FINAL : public HVecBinaryOperation {
387 public:
388 HVecAdd(ArenaAllocator* arena,
389 HInstruction* left,
390 HInstruction* right,
391 Primitive::Type packed_type,
392 size_t vector_length,
393 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700394 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700395 DCHECK(HasConsistentPackedTypes(left, packed_type));
396 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800397 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700398
399 bool CanBeMoved() const OVERRIDE { return true; }
400
Aart Bikf8f5a162017-02-06 15:35:29 -0800401 DECLARE_INSTRUCTION(VecAdd);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700402
Aart Bikf8f5a162017-02-06 15:35:29 -0800403 private:
404 DISALLOW_COPY_AND_ASSIGN(HVecAdd);
405};
406
Aart Bikf3e61ee2017-04-12 17:09:20 -0700407// Performs halving add on every component in the two vectors, viz.
408// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
409// or [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ]
410// for signed operands x, y (sign extension) or unsigned operands x, y (zero extension).
411class HVecHalvingAdd FINAL : public HVecBinaryOperation {
412 public:
413 HVecHalvingAdd(ArenaAllocator* arena,
414 HInstruction* left,
415 HInstruction* right,
416 Primitive::Type packed_type,
417 size_t vector_length,
418 bool is_unsigned,
419 bool is_rounded,
420 uint32_t dex_pc = kNoDexPc)
Aart Bikdb14fcf2017-04-25 15:53:58 -0700421 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700422 DCHECK(HasConsistentPackedTypes(left, packed_type));
423 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikdb14fcf2017-04-25 15:53:58 -0700424 SetPackedFlag<kFieldHAddIsUnsigned>(is_unsigned);
425 SetPackedFlag<kFieldHAddIsRounded>(is_rounded);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700426 }
427
Aart Bikdb14fcf2017-04-25 15:53:58 -0700428 bool IsUnsigned() const { return GetPackedFlag<kFieldHAddIsUnsigned>(); }
429 bool IsRounded() const { return GetPackedFlag<kFieldHAddIsRounded>(); }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700430
Aart Bikb79f4ac2017-07-10 10:10:37 -0700431 bool CanBeMoved() const OVERRIDE { return true; }
432
433 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
434 DCHECK(other->IsVecHalvingAdd());
435 const HVecHalvingAdd* o = other->AsVecHalvingAdd();
436 return HVecOperation::InstructionDataEquals(o) &&
437 IsUnsigned() == o->IsUnsigned() &&
438 IsRounded() == o->IsRounded();
439 }
440
Aart Bikf3e61ee2017-04-12 17:09:20 -0700441 DECLARE_INSTRUCTION(VecHalvingAdd);
442
443 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700444 // Additional packed bits.
445 static constexpr size_t kFieldHAddIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
446 static constexpr size_t kFieldHAddIsRounded = kFieldHAddIsUnsigned + 1;
447 static constexpr size_t kNumberOfHAddPackedBits = kFieldHAddIsRounded + 1;
448 static_assert(kNumberOfHAddPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Aart Bikf3e61ee2017-04-12 17:09:20 -0700449
450 DISALLOW_COPY_AND_ASSIGN(HVecHalvingAdd);
451};
452
Aart Bikf8f5a162017-02-06 15:35:29 -0800453// Subtracts every component in the two vectors,
454// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
455class HVecSub FINAL : public HVecBinaryOperation {
456 public:
457 HVecSub(ArenaAllocator* arena,
458 HInstruction* left,
459 HInstruction* right,
460 Primitive::Type packed_type,
461 size_t vector_length,
462 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700463 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700464 DCHECK(HasConsistentPackedTypes(left, packed_type));
465 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800466 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700467
468 bool CanBeMoved() const OVERRIDE { return true; }
469
Aart Bikf8f5a162017-02-06 15:35:29 -0800470 DECLARE_INSTRUCTION(VecSub);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700471
Aart Bikf8f5a162017-02-06 15:35:29 -0800472 private:
473 DISALLOW_COPY_AND_ASSIGN(HVecSub);
474};
475
476// Multiplies every component in the two vectors,
477// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
478class HVecMul FINAL : public HVecBinaryOperation {
479 public:
480 HVecMul(ArenaAllocator* arena,
481 HInstruction* left,
482 HInstruction* right,
483 Primitive::Type packed_type,
484 size_t vector_length,
485 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700486 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700487 DCHECK(HasConsistentPackedTypes(left, packed_type));
488 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800489 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700490
491 bool CanBeMoved() const OVERRIDE { return true; }
492
Aart Bikf8f5a162017-02-06 15:35:29 -0800493 DECLARE_INSTRUCTION(VecMul);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700494
Aart Bikf8f5a162017-02-06 15:35:29 -0800495 private:
496 DISALLOW_COPY_AND_ASSIGN(HVecMul);
497};
498
499// Divides every component in the two vectors,
500// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
501class HVecDiv FINAL : public HVecBinaryOperation {
502 public:
503 HVecDiv(ArenaAllocator* arena,
504 HInstruction* left,
505 HInstruction* right,
506 Primitive::Type packed_type,
507 size_t vector_length,
508 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700509 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700510 DCHECK(HasConsistentPackedTypes(left, packed_type));
511 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800512 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700513
514 bool CanBeMoved() const OVERRIDE { return true; }
515
Aart Bikf8f5a162017-02-06 15:35:29 -0800516 DECLARE_INSTRUCTION(VecDiv);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700517
Aart Bikf8f5a162017-02-06 15:35:29 -0800518 private:
519 DISALLOW_COPY_AND_ASSIGN(HVecDiv);
520};
521
Aart Bikf3e61ee2017-04-12 17:09:20 -0700522// Takes minimum of every component in the two vectors,
523// viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ].
524class HVecMin FINAL : public HVecBinaryOperation {
525 public:
526 HVecMin(ArenaAllocator* arena,
527 HInstruction* left,
528 HInstruction* right,
529 Primitive::Type packed_type,
530 size_t vector_length,
Aart Bikc8e93c72017-05-10 10:49:22 -0700531 bool is_unsigned,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700532 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700533 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700534 DCHECK(HasConsistentPackedTypes(left, packed_type));
535 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700536 SetPackedFlag<kFieldMinOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700537 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700538
539 bool IsUnsigned() const { return GetPackedFlag<kFieldMinOpIsUnsigned>(); }
540
Aart Bikb79f4ac2017-07-10 10:10:37 -0700541 bool CanBeMoved() const OVERRIDE { return true; }
542
543 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
544 DCHECK(other->IsVecMin());
545 const HVecMin* o = other->AsVecMin();
546 return HVecOperation::InstructionDataEquals(o) && IsUnsigned() == o->IsUnsigned();
547 }
548
Aart Bikf3e61ee2017-04-12 17:09:20 -0700549 DECLARE_INSTRUCTION(VecMin);
Aart Bikc8e93c72017-05-10 10:49:22 -0700550
Aart Bikf3e61ee2017-04-12 17:09:20 -0700551 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700552 // Additional packed bits.
553 static constexpr size_t kFieldMinOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
554 static constexpr size_t kNumberOfMinOpPackedBits = kFieldMinOpIsUnsigned + 1;
555 static_assert(kNumberOfMinOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
556
Aart Bikf3e61ee2017-04-12 17:09:20 -0700557 DISALLOW_COPY_AND_ASSIGN(HVecMin);
558};
559
560// Takes maximum of every component in the two vectors,
561// viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ].
562class HVecMax FINAL : public HVecBinaryOperation {
563 public:
564 HVecMax(ArenaAllocator* arena,
565 HInstruction* left,
566 HInstruction* right,
567 Primitive::Type packed_type,
568 size_t vector_length,
Aart Bikc8e93c72017-05-10 10:49:22 -0700569 bool is_unsigned,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700570 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700571 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700572 DCHECK(HasConsistentPackedTypes(left, packed_type));
573 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700574 SetPackedFlag<kFieldMaxOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700575 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700576
577 bool IsUnsigned() const { return GetPackedFlag<kFieldMaxOpIsUnsigned>(); }
578
Aart Bikb79f4ac2017-07-10 10:10:37 -0700579 bool CanBeMoved() const OVERRIDE { return true; }
580
581 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
582 DCHECK(other->IsVecMax());
583 const HVecMax* o = other->AsVecMax();
584 return HVecOperation::InstructionDataEquals(o) && IsUnsigned() == o->IsUnsigned();
585 }
586
Aart Bikf3e61ee2017-04-12 17:09:20 -0700587 DECLARE_INSTRUCTION(VecMax);
Aart Bikc8e93c72017-05-10 10:49:22 -0700588
Aart Bikf3e61ee2017-04-12 17:09:20 -0700589 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700590 // Additional packed bits.
591 static constexpr size_t kFieldMaxOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
592 static constexpr size_t kNumberOfMaxOpPackedBits = kFieldMaxOpIsUnsigned + 1;
593 static_assert(kNumberOfMaxOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
594
Aart Bikf3e61ee2017-04-12 17:09:20 -0700595 DISALLOW_COPY_AND_ASSIGN(HVecMax);
596};
597
Aart Bikf8f5a162017-02-06 15:35:29 -0800598// Bitwise-ands every component in the two vectors,
599// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
600class HVecAnd FINAL : public HVecBinaryOperation {
601 public:
602 HVecAnd(ArenaAllocator* arena,
603 HInstruction* left,
604 HInstruction* right,
605 Primitive::Type packed_type,
606 size_t vector_length,
607 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700608 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800609 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800610 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700611
612 bool CanBeMoved() const OVERRIDE { return true; }
613
Aart Bikf8f5a162017-02-06 15:35:29 -0800614 DECLARE_INSTRUCTION(VecAnd);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700615
Aart Bikf8f5a162017-02-06 15:35:29 -0800616 private:
617 DISALLOW_COPY_AND_ASSIGN(HVecAnd);
618};
619
620// Bitwise-and-nots every component in the two vectors,
621// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
622class HVecAndNot FINAL : public HVecBinaryOperation {
623 public:
624 HVecAndNot(ArenaAllocator* arena,
625 HInstruction* left,
626 HInstruction* right,
627 Primitive::Type packed_type,
628 size_t vector_length,
629 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700630 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800631 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800632 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700633
634 bool CanBeMoved() const OVERRIDE { return true; }
635
Aart Bikf8f5a162017-02-06 15:35:29 -0800636 DECLARE_INSTRUCTION(VecAndNot);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700637
Aart Bikf8f5a162017-02-06 15:35:29 -0800638 private:
639 DISALLOW_COPY_AND_ASSIGN(HVecAndNot);
640};
641
642// Bitwise-ors every component in the two vectors,
643// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
644class HVecOr FINAL : public HVecBinaryOperation {
645 public:
646 HVecOr(ArenaAllocator* arena,
647 HInstruction* left,
648 HInstruction* right,
649 Primitive::Type packed_type,
650 size_t vector_length,
651 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700652 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800653 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800654 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700655
656 bool CanBeMoved() const OVERRIDE { return true; }
657
Aart Bikf8f5a162017-02-06 15:35:29 -0800658 DECLARE_INSTRUCTION(VecOr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700659
Aart Bikf8f5a162017-02-06 15:35:29 -0800660 private:
661 DISALLOW_COPY_AND_ASSIGN(HVecOr);
662};
663
664// Bitwise-xors every component in the two vectors,
665// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
666class HVecXor FINAL : public HVecBinaryOperation {
667 public:
668 HVecXor(ArenaAllocator* arena,
669 HInstruction* left,
670 HInstruction* right,
671 Primitive::Type packed_type,
672 size_t vector_length,
673 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700674 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800675 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800676 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700677
678 bool CanBeMoved() const OVERRIDE { return true; }
679
Aart Bikf8f5a162017-02-06 15:35:29 -0800680 DECLARE_INSTRUCTION(VecXor);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700681
Aart Bikf8f5a162017-02-06 15:35:29 -0800682 private:
683 DISALLOW_COPY_AND_ASSIGN(HVecXor);
684};
685
686// Logically shifts every component in the vector left by the given distance,
687// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
688class HVecShl FINAL : public HVecBinaryOperation {
689 public:
690 HVecShl(ArenaAllocator* arena,
691 HInstruction* left,
692 HInstruction* right,
693 Primitive::Type packed_type,
694 size_t vector_length,
695 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700696 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700697 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800698 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700699
700 bool CanBeMoved() const OVERRIDE { return true; }
701
Aart Bikf8f5a162017-02-06 15:35:29 -0800702 DECLARE_INSTRUCTION(VecShl);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700703
Aart Bikf8f5a162017-02-06 15:35:29 -0800704 private:
705 DISALLOW_COPY_AND_ASSIGN(HVecShl);
706};
707
708// Arithmetically shifts every component in the vector right by the given distance,
709// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
710class HVecShr FINAL : public HVecBinaryOperation {
711 public:
712 HVecShr(ArenaAllocator* arena,
713 HInstruction* left,
714 HInstruction* right,
715 Primitive::Type packed_type,
716 size_t vector_length,
717 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700718 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700719 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800720 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700721
722 bool CanBeMoved() const OVERRIDE { return true; }
723
Aart Bikf8f5a162017-02-06 15:35:29 -0800724 DECLARE_INSTRUCTION(VecShr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700725
Aart Bikf8f5a162017-02-06 15:35:29 -0800726 private:
727 DISALLOW_COPY_AND_ASSIGN(HVecShr);
728};
729
730// Logically shifts every component in the vector right by the given distance,
731// viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
732class HVecUShr FINAL : public HVecBinaryOperation {
733 public:
734 HVecUShr(ArenaAllocator* arena,
735 HInstruction* left,
736 HInstruction* right,
737 Primitive::Type packed_type,
738 size_t vector_length,
739 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700740 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700741 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800742 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700743
744 bool CanBeMoved() const OVERRIDE { return true; }
745
Aart Bikf8f5a162017-02-06 15:35:29 -0800746 DECLARE_INSTRUCTION(VecUShr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700747
Aart Bikf8f5a162017-02-06 15:35:29 -0800748 private:
749 DISALLOW_COPY_AND_ASSIGN(HVecUShr);
750};
751
Aart Bik8de59162017-04-21 09:42:01 -0700752//
753// Definitions of concrete miscellaneous vector operations in HIR.
754//
755
756// Assigns the given scalar elements to a vector,
Aart Bika57b4ee2017-08-30 21:21:41 +0000757// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
Aart Bik8de59162017-04-21 09:42:01 -0700758class HVecSetScalars FINAL : public HVecOperation {
759 HVecSetScalars(ArenaAllocator* arena,
760 HInstruction** scalars, // array
761 Primitive::Type packed_type,
762 size_t vector_length,
763 uint32_t dex_pc = kNoDexPc)
764 : HVecOperation(arena,
765 packed_type,
766 SideEffects::None(),
Aart Bika57b4ee2017-08-30 21:21:41 +0000767 /* number_of_inputs */ vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700768 vector_length,
769 dex_pc) {
Aart Bika57b4ee2017-08-30 21:21:41 +0000770 for (size_t i = 0; i < vector_length; i++) {
Aart Bik8de59162017-04-21 09:42:01 -0700771 DCHECK(!scalars[i]->IsVecOperation());
772 SetRawInputAt(0, scalars[i]);
773 }
774 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700775
776 // Setting scalars needs to stay in place, since SIMD registers are not
777 // kept alive across vector loop boundaries (yet).
778 bool CanBeMoved() const OVERRIDE { return false; }
779
Aart Bik8de59162017-04-21 09:42:01 -0700780 DECLARE_INSTRUCTION(VecSetScalars);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700781
Aart Bik8de59162017-04-21 09:42:01 -0700782 private:
783 DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
784};
785
Artem Serovf34dd202017-04-10 17:41:46 +0100786// Multiplies every component in the two vectors, adds the result vector to the accumulator vector.
787// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] =
788// [ acc1 + x1 * y1, .. , accn + xn * yn ].
789class HVecMultiplyAccumulate FINAL : public HVecOperation {
790 public:
791 HVecMultiplyAccumulate(ArenaAllocator* arena,
792 InstructionKind op,
793 HInstruction* accumulator,
794 HInstruction* mul_left,
795 HInstruction* mul_right,
796 Primitive::Type packed_type,
797 size_t vector_length,
798 uint32_t dex_pc = kNoDexPc)
799 : HVecOperation(arena,
800 packed_type,
801 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700802 /* number_of_inputs */ 3,
Artem Serovf34dd202017-04-10 17:41:46 +0100803 vector_length,
804 dex_pc),
805 op_kind_(op) {
806 DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
Aart Bikd58bc322017-05-01 14:49:18 -0700807 DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
808 DCHECK(HasConsistentPackedTypes(mul_left, packed_type));
809 DCHECK(HasConsistentPackedTypes(mul_right, packed_type));
Artem Serovf34dd202017-04-10 17:41:46 +0100810 SetRawInputAt(kInputAccumulatorIndex, accumulator);
811 SetRawInputAt(kInputMulLeftIndex, mul_left);
812 SetRawInputAt(kInputMulRightIndex, mul_right);
813 }
814
815 static constexpr int kInputAccumulatorIndex = 0;
816 static constexpr int kInputMulLeftIndex = 1;
817 static constexpr int kInputMulRightIndex = 2;
818
Nicolas Geoffray9858bf72017-07-08 12:34:55 +0000819 bool CanBeMoved() const OVERRIDE { return true; }
820
Artem Serovf34dd202017-04-10 17:41:46 +0100821 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
Aart Bikb79f4ac2017-07-10 10:10:37 -0700822 DCHECK(other->IsVecMultiplyAccumulate());
823 const HVecMultiplyAccumulate* o = other->AsVecMultiplyAccumulate();
824 return HVecOperation::InstructionDataEquals(o) && GetOpKind() == o->GetOpKind();
Artem Serovf34dd202017-04-10 17:41:46 +0100825 }
826
827 InstructionKind GetOpKind() const { return op_kind_; }
828
829 DECLARE_INSTRUCTION(VecMultiplyAccumulate);
830
831 private:
832 // Indicates if this is a MADD or MSUB.
833 const InstructionKind op_kind_;
834
835 DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate);
836};
837
Aart Bikf8f5a162017-02-06 15:35:29 -0800838// Loads a vector from memory, viz. load(mem, 1)
839// yield the vector [ mem(1), .. , mem(n) ].
840class HVecLoad FINAL : public HVecMemoryOperation {
841 public:
842 HVecLoad(ArenaAllocator* arena,
843 HInstruction* base,
844 HInstruction* index,
845 Primitive::Type packed_type,
846 size_t vector_length,
Aart Bikdb14fcf2017-04-25 15:53:58 -0700847 bool is_string_char_at,
Aart Bikf8f5a162017-02-06 15:35:29 -0800848 uint32_t dex_pc = kNoDexPc)
849 : HVecMemoryOperation(arena,
850 packed_type,
851 SideEffects::ArrayReadOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700852 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800853 vector_length,
854 dex_pc) {
855 SetRawInputAt(0, base);
856 SetRawInputAt(1, index);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700857 SetPackedFlag<kFieldIsStringCharAt>(is_string_char_at);
Aart Bikf8f5a162017-02-06 15:35:29 -0800858 }
Aart Bikdb14fcf2017-04-25 15:53:58 -0700859
860 bool IsStringCharAt() const { return GetPackedFlag<kFieldIsStringCharAt>(); }
861
Aart Bikb79f4ac2017-07-10 10:10:37 -0700862 bool CanBeMoved() const OVERRIDE { return true; }
863
864 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
865 DCHECK(other->IsVecLoad());
866 const HVecLoad* o = other->AsVecLoad();
867 return HVecMemoryOperation::InstructionDataEquals(o) && IsStringCharAt() == o->IsStringCharAt();
868 }
869
870 DECLARE_INSTRUCTION(VecLoad);
871
Aart Bikf8f5a162017-02-06 15:35:29 -0800872 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700873 // Additional packed bits.
874 static constexpr size_t kFieldIsStringCharAt = HVecOperation::kNumberOfVectorOpPackedBits;
875 static constexpr size_t kNumberOfVecLoadPackedBits = kFieldIsStringCharAt + 1;
876 static_assert(kNumberOfVecLoadPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
877
Aart Bikf8f5a162017-02-06 15:35:29 -0800878 DISALLOW_COPY_AND_ASSIGN(HVecLoad);
879};
880
881// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
882// sets mem(1) = x1, .. , mem(n) = xn.
883class HVecStore FINAL : public HVecMemoryOperation {
884 public:
885 HVecStore(ArenaAllocator* arena,
886 HInstruction* base,
887 HInstruction* index,
888 HInstruction* value,
889 Primitive::Type packed_type,
890 size_t vector_length,
891 uint32_t dex_pc = kNoDexPc)
892 : HVecMemoryOperation(arena,
893 packed_type,
894 SideEffects::ArrayWriteOfType(packed_type),
Aart Bik8de59162017-04-21 09:42:01 -0700895 /* number_of_inputs */ 3,
Aart Bikf8f5a162017-02-06 15:35:29 -0800896 vector_length,
897 dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700898 DCHECK(HasConsistentPackedTypes(value, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800899 SetRawInputAt(0, base);
900 SetRawInputAt(1, index);
901 SetRawInputAt(2, value);
902 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700903
904 // A store needs to stay in place.
905 bool CanBeMoved() const OVERRIDE { return false; }
906
Aart Bikf8f5a162017-02-06 15:35:29 -0800907 DECLARE_INSTRUCTION(VecStore);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700908
Aart Bikf8f5a162017-02-06 15:35:29 -0800909 private:
910 DISALLOW_COPY_AND_ASSIGN(HVecStore);
911};
912
913} // namespace art
914
915#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_