blob: d01f8c0289ea2d7eb60f39c90a29536679d220e2 [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:
Aart Bik0148de42017-09-05 09:25:01 -070066 // A SIMD operation looks like a FPU location.
67 // TODO: we could introduce SIMD types in HIR.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010068 static constexpr DataType::Type kSIMDType = DataType::Type::kFloat64;
Aart Bik0148de42017-09-05 09:25:01 -070069
Aart Bikf8f5a162017-02-06 15:35:29 -080070 HVecOperation(ArenaAllocator* arena,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010071 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -080072 SideEffects side_effects,
73 size_t number_of_inputs,
74 size_t vector_length,
75 uint32_t dex_pc)
76 : HVariableInputSizeInstruction(side_effects,
77 dex_pc,
78 arena,
79 number_of_inputs,
80 kArenaAllocVectorNode),
81 vector_length_(vector_length) {
82 SetPackedField<TypeField>(packed_type);
83 DCHECK_LT(1u, vector_length);
84 }
85
86 // Returns the number of elements packed in a vector.
87 size_t GetVectorLength() const {
88 return vector_length_;
89 }
90
91 // Returns the number of bytes in a full vector.
92 size_t GetVectorNumberOfBytes() const {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010093 return vector_length_ * DataType::Size(GetPackedType());
Aart Bikf8f5a162017-02-06 15:35:29 -080094 }
95
Aart Bik0148de42017-09-05 09:25:01 -070096 // Returns the type of the vector operation.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010097 DataType::Type GetType() const OVERRIDE {
Aart Bik0148de42017-09-05 09:25:01 -070098 return kSIMDType;
Aart Bikf8f5a162017-02-06 15:35:29 -080099 }
100
101 // Returns the true component type packed in a vector.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100102 DataType::Type GetPackedType() const {
Aart Bikf8f5a162017-02-06 15:35:29 -0800103 return GetPackedField<TypeField>();
104 }
105
Aart Bikb79f4ac2017-07-10 10:10:37 -0700106 // Assumes vector nodes cannot be moved by default. Each concrete implementation
107 // that can be moved should override this method and return true.
108 bool CanBeMoved() const OVERRIDE { return false; }
109
110 // Tests if all data of a vector node (vector length and packed type) is equal.
111 // Each concrete implementation that adds more fields should test equality of
112 // those fields in its own method *and* call all super methods.
113 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
114 DCHECK(other->IsVecOperation());
115 const HVecOperation* o = other->AsVecOperation();
116 return GetVectorLength() == o->GetVectorLength() && GetPackedType() == o->GetPackedType();
117 }
118
Aart Bikf8f5a162017-02-06 15:35:29 -0800119 DECLARE_ABSTRACT_INSTRUCTION(VecOperation);
120
Aart Bikdb14fcf2017-04-25 15:53:58 -0700121 protected:
Aart Bikf8f5a162017-02-06 15:35:29 -0800122 // Additional packed bits.
123 static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits;
124 static constexpr size_t kFieldTypeSize =
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100125 MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
Aart Bikf8f5a162017-02-06 15:35:29 -0800126 static constexpr size_t kNumberOfVectorOpPackedBits = kFieldType + kFieldTypeSize;
127 static_assert(kNumberOfVectorOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100128 using TypeField = BitField<DataType::Type, kFieldType, kFieldTypeSize>;
Aart Bikf8f5a162017-02-06 15:35:29 -0800129
Aart Bikdb14fcf2017-04-25 15:53:58 -0700130 private:
Aart Bikf8f5a162017-02-06 15:35:29 -0800131 const size_t vector_length_;
132
133 DISALLOW_COPY_AND_ASSIGN(HVecOperation);
134};
135
136// Abstraction of a unary vector operation.
137class HVecUnaryOperation : public HVecOperation {
138 public:
139 HVecUnaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700140 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100141 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800142 size_t vector_length,
143 uint32_t dex_pc)
144 : HVecOperation(arena,
145 packed_type,
146 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700147 /* number_of_inputs */ 1,
Aart Bikf8f5a162017-02-06 15:35:29 -0800148 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700149 dex_pc) {
150 SetRawInputAt(0, input);
151 }
152
153 HInstruction* GetInput() const { return InputAt(0); }
154
Aart Bikf8f5a162017-02-06 15:35:29 -0800155 DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700156
Aart Bikf8f5a162017-02-06 15:35:29 -0800157 private:
158 DISALLOW_COPY_AND_ASSIGN(HVecUnaryOperation);
159};
160
161// Abstraction of a binary vector operation.
162class HVecBinaryOperation : public HVecOperation {
163 public:
164 HVecBinaryOperation(ArenaAllocator* arena,
Aart Bik8de59162017-04-21 09:42:01 -0700165 HInstruction* left,
166 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100167 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800168 size_t vector_length,
169 uint32_t dex_pc)
170 : HVecOperation(arena,
171 packed_type,
172 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700173 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800174 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700175 dex_pc) {
176 SetRawInputAt(0, left);
177 SetRawInputAt(1, right);
178 }
Artem Serovf34dd202017-04-10 17:41:46 +0100179
180 HInstruction* GetLeft() const { return InputAt(0); }
181 HInstruction* GetRight() const { return InputAt(1); }
182
Aart Bikf8f5a162017-02-06 15:35:29 -0800183 DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700184
Aart Bikf8f5a162017-02-06 15:35:29 -0800185 private:
186 DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation);
187};
188
189// Abstraction of a vector operation that references memory, with an alignment.
190// The Android runtime guarantees at least "component size" alignment for array
191// elements and, thus, vectors.
192class HVecMemoryOperation : public HVecOperation {
193 public:
194 HVecMemoryOperation(ArenaAllocator* arena,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100195 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800196 SideEffects side_effects,
197 size_t number_of_inputs,
198 size_t vector_length,
199 uint32_t dex_pc)
200 : HVecOperation(arena, packed_type, side_effects, number_of_inputs, vector_length, dex_pc),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100201 alignment_(DataType::Size(packed_type), 0) {
Artem Serove1811ed2017-04-27 16:50:47 +0100202 DCHECK_GE(number_of_inputs, 2u);
203 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800204
205 void SetAlignment(Alignment alignment) { alignment_ = alignment; }
206
207 Alignment GetAlignment() const { return alignment_; }
208
Artem Serove1811ed2017-04-27 16:50:47 +0100209 HInstruction* GetArray() const { return InputAt(0); }
210 HInstruction* GetIndex() const { return InputAt(1); }
211
Aart Bikb79f4ac2017-07-10 10:10:37 -0700212 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
213 DCHECK(other->IsVecMemoryOperation());
214 const HVecMemoryOperation* o = other->AsVecMemoryOperation();
215 return HVecOperation::InstructionDataEquals(o) && GetAlignment() == o->GetAlignment();
216 }
217
Aart Bikf8f5a162017-02-06 15:35:29 -0800218 DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
219
220 private:
221 Alignment alignment_;
222
223 DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
224};
225
Aart Bik0148de42017-09-05 09:25:01 -0700226// Packed type consistency checker ("same vector length" integral types may mix freely).
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100227inline static bool HasConsistentPackedTypes(HInstruction* input, DataType::Type type) {
Aart Bik0148de42017-09-05 09:25:01 -0700228 if (input->IsPhi()) {
229 return input->GetType() == HVecOperation::kSIMDType; // carries SIMD
230 }
Aart Bikd58bc322017-05-01 14:49:18 -0700231 DCHECK(input->IsVecOperation());
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100232 DataType::Type input_type = input->AsVecOperation()->GetPackedType();
Aart Bikd58bc322017-05-01 14:49:18 -0700233 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100234 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100235 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100236 case DataType::Type::kInt8:
237 return type == DataType::Type::kBool ||
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100238 type == DataType::Type::kUint8 ||
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100239 type == DataType::Type::kInt8;
240 case DataType::Type::kUint16:
241 case DataType::Type::kInt16:
242 return type == DataType::Type::kUint16 ||
243 type == DataType::Type::kInt16;
Aart Bikd58bc322017-05-01 14:49:18 -0700244 default:
245 return type == input_type;
246 }
247}
248
Aart Bikf8f5a162017-02-06 15:35:29 -0800249//
Aart Bik8de59162017-04-21 09:42:01 -0700250// Definitions of concrete unary vector operations in HIR.
Aart Bikf8f5a162017-02-06 15:35:29 -0800251//
252
253// Replicates the given scalar into a vector,
254// viz. replicate(x) = [ x, .. , x ].
255class HVecReplicateScalar FINAL : public HVecUnaryOperation {
256 public:
257 HVecReplicateScalar(ArenaAllocator* arena,
258 HInstruction* scalar,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100259 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800260 size_t vector_length,
261 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700262 : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) {
263 DCHECK(!scalar->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800264 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700265
266 // A replicate needs to stay in place, since SIMD registers are not
267 // kept alive across vector loop boundaries (yet).
268 bool CanBeMoved() const OVERRIDE { return false; }
269
Aart Bikf8f5a162017-02-06 15:35:29 -0800270 DECLARE_INSTRUCTION(VecReplicateScalar);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700271
Aart Bikf8f5a162017-02-06 15:35:29 -0800272 private:
273 DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
274};
275
Aart Bik0148de42017-09-05 09:25:01 -0700276// Extracts a particular scalar from the given vector,
277// viz. extract[ x1, .. , xn ] = x_i.
278//
279// TODO: for now only i == 1 case supported.
280class HVecExtractScalar FINAL : public HVecUnaryOperation {
281 public:
282 HVecExtractScalar(ArenaAllocator* arena,
283 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100284 DataType::Type packed_type,
Aart Bik0148de42017-09-05 09:25:01 -0700285 size_t vector_length,
286 size_t index,
287 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700288 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700289 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik0148de42017-09-05 09:25:01 -0700290 DCHECK_LT(index, vector_length);
291 DCHECK_EQ(index, 0u);
292 }
293
294 // Yields a single component in the vector.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100295 DataType::Type GetType() const OVERRIDE {
Aart Bik0148de42017-09-05 09:25:01 -0700296 return GetPackedType();
297 }
298
299 // An extract needs to stay in place, since SIMD registers are not
300 // kept alive across vector loop boundaries (yet).
301 bool CanBeMoved() const OVERRIDE { return false; }
302
303 DECLARE_INSTRUCTION(VecExtractScalar);
304
305 private:
306 DISALLOW_COPY_AND_ASSIGN(HVecExtractScalar);
307};
308
309// Reduces the given vector into the first element as sum/min/max,
310// viz. sum-reduce[ x1, .. , xn ] = [ y, ---- ], where y = sum xi
311// and the "-" denotes "don't care" (implementation dependent).
312class HVecReduce FINAL : public HVecUnaryOperation {
313 public:
314 enum ReductionKind {
315 kSum = 1,
316 kMin = 2,
317 kMax = 3
318 };
319
320 HVecReduce(ArenaAllocator* arena,
321 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100322 DataType::Type packed_type,
Aart Bik0148de42017-09-05 09:25:01 -0700323 size_t vector_length,
324 ReductionKind kind,
325 uint32_t dex_pc = kNoDexPc)
326 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc),
327 kind_(kind) {
328 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikcfa59b42017-08-31 09:08:13 -0700329 }
330
Aart Bik0148de42017-09-05 09:25:01 -0700331 ReductionKind GetKind() const { return kind_; }
Aart Bikf8f5a162017-02-06 15:35:29 -0800332
Aart Bikb79f4ac2017-07-10 10:10:37 -0700333 bool CanBeMoved() const OVERRIDE { return true; }
334
Aart Bik0148de42017-09-05 09:25:01 -0700335 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
336 DCHECK(other->IsVecReduce());
337 const HVecReduce* o = other->AsVecReduce();
338 return HVecOperation::InstructionDataEquals(o) && GetKind() == o->GetKind();
339 }
340
341 DECLARE_INSTRUCTION(VecReduce);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700342
Aart Bikf8f5a162017-02-06 15:35:29 -0800343 private:
Aart Bik0148de42017-09-05 09:25:01 -0700344 const ReductionKind kind_;
345
346 DISALLOW_COPY_AND_ASSIGN(HVecReduce);
Aart Bikf8f5a162017-02-06 15:35:29 -0800347};
348
349// Converts every component in the vector,
350// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
351class HVecCnv FINAL : public HVecUnaryOperation {
352 public:
353 HVecCnv(ArenaAllocator* arena,
354 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100355 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800356 size_t vector_length,
357 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700358 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800359 DCHECK(input->IsVecOperation());
Aart Bikd58bc322017-05-01 14:49:18 -0700360 DCHECK_NE(GetInputType(), GetResultType()); // actual convert
Aart Bikf8f5a162017-02-06 15:35:29 -0800361 }
362
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100363 DataType::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
364 DataType::Type GetResultType() const { return GetPackedType(); }
Aart Bikf8f5a162017-02-06 15:35:29 -0800365
Aart Bikb79f4ac2017-07-10 10:10:37 -0700366 bool CanBeMoved() const OVERRIDE { return true; }
367
Aart Bikf8f5a162017-02-06 15:35:29 -0800368 DECLARE_INSTRUCTION(VecCnv);
369
370 private:
371 DISALLOW_COPY_AND_ASSIGN(HVecCnv);
372};
373
374// Negates every component in the vector,
375// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
376class HVecNeg FINAL : public HVecUnaryOperation {
377 public:
378 HVecNeg(ArenaAllocator* arena,
379 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100380 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800381 size_t vector_length,
382 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700383 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700384 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800385 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700386
387 bool CanBeMoved() const OVERRIDE { return true; }
388
Aart Bikf8f5a162017-02-06 15:35:29 -0800389 DECLARE_INSTRUCTION(VecNeg);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700390
Aart Bikf8f5a162017-02-06 15:35:29 -0800391 private:
392 DISALLOW_COPY_AND_ASSIGN(HVecNeg);
393};
394
Aart Bik6daebeb2017-04-03 14:35:41 -0700395// Takes absolute value of every component in the vector,
396// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ].
397class HVecAbs FINAL : public HVecUnaryOperation {
398 public:
399 HVecAbs(ArenaAllocator* arena,
400 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100401 DataType::Type packed_type,
Aart Bik6daebeb2017-04-03 14:35:41 -0700402 size_t vector_length,
403 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700404 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700405 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik6daebeb2017-04-03 14:35:41 -0700406 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700407
408 bool CanBeMoved() const OVERRIDE { return true; }
409
Aart Bik6daebeb2017-04-03 14:35:41 -0700410 DECLARE_INSTRUCTION(VecAbs);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700411
Aart Bik6daebeb2017-04-03 14:35:41 -0700412 private:
413 DISALLOW_COPY_AND_ASSIGN(HVecAbs);
414};
415
Aart Bikf8f5a162017-02-06 15:35:29 -0800416// Bitwise- or boolean-nots every component in the vector,
417// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
418// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
419class HVecNot FINAL : public HVecUnaryOperation {
420 public:
421 HVecNot(ArenaAllocator* arena,
422 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100423 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800424 size_t vector_length,
425 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700426 : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800427 DCHECK(input->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800428 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700429
430 bool CanBeMoved() const OVERRIDE { return true; }
431
Aart Bikf8f5a162017-02-06 15:35:29 -0800432 DECLARE_INSTRUCTION(VecNot);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700433
Aart Bikf8f5a162017-02-06 15:35:29 -0800434 private:
435 DISALLOW_COPY_AND_ASSIGN(HVecNot);
436};
437
Aart Bik8de59162017-04-21 09:42:01 -0700438//
439// Definitions of concrete binary vector operations in HIR.
440//
441
Aart Bikf8f5a162017-02-06 15:35:29 -0800442// Adds every component in the two vectors,
443// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
444class HVecAdd FINAL : public HVecBinaryOperation {
445 public:
446 HVecAdd(ArenaAllocator* arena,
447 HInstruction* left,
448 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100449 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800450 size_t vector_length,
451 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700452 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700453 DCHECK(HasConsistentPackedTypes(left, packed_type));
454 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800455 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700456
457 bool CanBeMoved() const OVERRIDE { return true; }
458
Aart Bikf8f5a162017-02-06 15:35:29 -0800459 DECLARE_INSTRUCTION(VecAdd);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700460
Aart Bikf8f5a162017-02-06 15:35:29 -0800461 private:
462 DISALLOW_COPY_AND_ASSIGN(HVecAdd);
463};
464
Aart Bikf3e61ee2017-04-12 17:09:20 -0700465// Performs halving add on every component in the two vectors, viz.
Aart Bikdbbac8f2017-09-01 13:06:08 -0700466// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
467// truncated [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ]
Aart Bikf3e61ee2017-04-12 17:09:20 -0700468// for signed operands x, y (sign extension) or unsigned operands x, y (zero extension).
469class HVecHalvingAdd FINAL : public HVecBinaryOperation {
470 public:
471 HVecHalvingAdd(ArenaAllocator* arena,
472 HInstruction* left,
473 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100474 DataType::Type packed_type,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700475 size_t vector_length,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700476 bool is_rounded,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100477 bool is_unsigned = false)
478 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, kNoDexPc) {
479 // The `is_unsigned` flag should be used exclusively with the Int32 or Int64.
480 // This flag is a temporary measure while we do not have the Uint32 and Uint64 data types.
481 DCHECK(!is_unsigned ||
482 packed_type == DataType::Type::kInt32 ||
483 packed_type == DataType::Type::kInt64) << packed_type;
Aart Bikd58bc322017-05-01 14:49:18 -0700484 DCHECK(HasConsistentPackedTypes(left, packed_type));
485 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikdb14fcf2017-04-25 15:53:58 -0700486 SetPackedFlag<kFieldHAddIsUnsigned>(is_unsigned);
487 SetPackedFlag<kFieldHAddIsRounded>(is_rounded);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700488 }
489
Aart Bikdb14fcf2017-04-25 15:53:58 -0700490 bool IsUnsigned() const { return GetPackedFlag<kFieldHAddIsUnsigned>(); }
491 bool IsRounded() const { return GetPackedFlag<kFieldHAddIsRounded>(); }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700492
Aart Bikb79f4ac2017-07-10 10:10:37 -0700493 bool CanBeMoved() const OVERRIDE { return true; }
494
495 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
496 DCHECK(other->IsVecHalvingAdd());
497 const HVecHalvingAdd* o = other->AsVecHalvingAdd();
498 return HVecOperation::InstructionDataEquals(o) &&
499 IsUnsigned() == o->IsUnsigned() &&
500 IsRounded() == o->IsRounded();
501 }
502
Aart Bikf3e61ee2017-04-12 17:09:20 -0700503 DECLARE_INSTRUCTION(VecHalvingAdd);
504
505 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700506 // Additional packed bits.
507 static constexpr size_t kFieldHAddIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
508 static constexpr size_t kFieldHAddIsRounded = kFieldHAddIsUnsigned + 1;
509 static constexpr size_t kNumberOfHAddPackedBits = kFieldHAddIsRounded + 1;
510 static_assert(kNumberOfHAddPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Aart Bikf3e61ee2017-04-12 17:09:20 -0700511
512 DISALLOW_COPY_AND_ASSIGN(HVecHalvingAdd);
513};
514
Aart Bikf8f5a162017-02-06 15:35:29 -0800515// Subtracts every component in the two vectors,
516// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
517class HVecSub FINAL : public HVecBinaryOperation {
518 public:
519 HVecSub(ArenaAllocator* arena,
520 HInstruction* left,
521 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100522 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800523 size_t vector_length,
524 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700525 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700526 DCHECK(HasConsistentPackedTypes(left, packed_type));
527 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800528 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700529
530 bool CanBeMoved() const OVERRIDE { return true; }
531
Aart Bikf8f5a162017-02-06 15:35:29 -0800532 DECLARE_INSTRUCTION(VecSub);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700533
Aart Bikf8f5a162017-02-06 15:35:29 -0800534 private:
535 DISALLOW_COPY_AND_ASSIGN(HVecSub);
536};
537
538// Multiplies every component in the two vectors,
539// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
540class HVecMul FINAL : public HVecBinaryOperation {
541 public:
542 HVecMul(ArenaAllocator* arena,
543 HInstruction* left,
544 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100545 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800546 size_t vector_length,
547 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700548 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700549 DCHECK(HasConsistentPackedTypes(left, packed_type));
550 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800551 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700552
553 bool CanBeMoved() const OVERRIDE { return true; }
554
Aart Bikf8f5a162017-02-06 15:35:29 -0800555 DECLARE_INSTRUCTION(VecMul);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700556
Aart Bikf8f5a162017-02-06 15:35:29 -0800557 private:
558 DISALLOW_COPY_AND_ASSIGN(HVecMul);
559};
560
561// Divides every component in the two vectors,
562// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
563class HVecDiv FINAL : public HVecBinaryOperation {
564 public:
565 HVecDiv(ArenaAllocator* arena,
566 HInstruction* left,
567 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100568 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800569 size_t vector_length,
570 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 Bikf8f5a162017-02-06 15:35:29 -0800574 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700575
576 bool CanBeMoved() const OVERRIDE { return true; }
577
Aart Bikf8f5a162017-02-06 15:35:29 -0800578 DECLARE_INSTRUCTION(VecDiv);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700579
Aart Bikf8f5a162017-02-06 15:35:29 -0800580 private:
581 DISALLOW_COPY_AND_ASSIGN(HVecDiv);
582};
583
Aart Bikf3e61ee2017-04-12 17:09:20 -0700584// Takes minimum of every component in the two vectors,
585// viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ].
586class HVecMin FINAL : public HVecBinaryOperation {
587 public:
588 HVecMin(ArenaAllocator* arena,
589 HInstruction* left,
590 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100591 DataType::Type packed_type,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700592 size_t vector_length,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100593 bool is_unsigned = false)
594 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, kNoDexPc) {
595 // The `is_unsigned` flag should be used exclusively with the Int32 or Int64.
596 // This flag is a temporary measure while we do not have the Uint32 and Uint64 data types.
597 DCHECK(!is_unsigned ||
598 packed_type == DataType::Type::kInt32 ||
599 packed_type == DataType::Type::kInt64) << packed_type;
Aart Bikd58bc322017-05-01 14:49:18 -0700600 DCHECK(HasConsistentPackedTypes(left, packed_type));
601 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700602 SetPackedFlag<kFieldMinOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700603 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700604
605 bool IsUnsigned() const { return GetPackedFlag<kFieldMinOpIsUnsigned>(); }
606
Aart Bikb79f4ac2017-07-10 10:10:37 -0700607 bool CanBeMoved() const OVERRIDE { return true; }
608
609 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
610 DCHECK(other->IsVecMin());
611 const HVecMin* o = other->AsVecMin();
612 return HVecOperation::InstructionDataEquals(o) && IsUnsigned() == o->IsUnsigned();
613 }
614
Aart Bikf3e61ee2017-04-12 17:09:20 -0700615 DECLARE_INSTRUCTION(VecMin);
Aart Bikc8e93c72017-05-10 10:49:22 -0700616
Aart Bikf3e61ee2017-04-12 17:09:20 -0700617 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700618 // Additional packed bits.
619 static constexpr size_t kFieldMinOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
620 static constexpr size_t kNumberOfMinOpPackedBits = kFieldMinOpIsUnsigned + 1;
621 static_assert(kNumberOfMinOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
622
Aart Bikf3e61ee2017-04-12 17:09:20 -0700623 DISALLOW_COPY_AND_ASSIGN(HVecMin);
624};
625
626// Takes maximum of every component in the two vectors,
627// viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ].
628class HVecMax FINAL : public HVecBinaryOperation {
629 public:
630 HVecMax(ArenaAllocator* arena,
631 HInstruction* left,
632 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100633 DataType::Type packed_type,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700634 size_t vector_length,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100635 bool is_unsigned = false)
636 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, kNoDexPc) {
637 // The `is_unsigned` flag should be used exclusively with the Int32 or Int64.
638 // This flag is a temporary measure while we do not have the Uint32 and Uint64 data types.
639 DCHECK(!is_unsigned ||
640 packed_type == DataType::Type::kInt32 ||
641 packed_type == DataType::Type::kInt64) << packed_type;
Aart Bikd58bc322017-05-01 14:49:18 -0700642 DCHECK(HasConsistentPackedTypes(left, packed_type));
643 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikc8e93c72017-05-10 10:49:22 -0700644 SetPackedFlag<kFieldMaxOpIsUnsigned>(is_unsigned);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700645 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700646
647 bool IsUnsigned() const { return GetPackedFlag<kFieldMaxOpIsUnsigned>(); }
648
Aart Bikb79f4ac2017-07-10 10:10:37 -0700649 bool CanBeMoved() const OVERRIDE { return true; }
650
651 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
652 DCHECK(other->IsVecMax());
653 const HVecMax* o = other->AsVecMax();
654 return HVecOperation::InstructionDataEquals(o) && IsUnsigned() == o->IsUnsigned();
655 }
656
Aart Bikf3e61ee2017-04-12 17:09:20 -0700657 DECLARE_INSTRUCTION(VecMax);
Aart Bikc8e93c72017-05-10 10:49:22 -0700658
Aart Bikf3e61ee2017-04-12 17:09:20 -0700659 private:
Aart Bikc8e93c72017-05-10 10:49:22 -0700660 // Additional packed bits.
661 static constexpr size_t kFieldMaxOpIsUnsigned = HVecOperation::kNumberOfVectorOpPackedBits;
662 static constexpr size_t kNumberOfMaxOpPackedBits = kFieldMaxOpIsUnsigned + 1;
663 static_assert(kNumberOfMaxOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
664
Aart Bikf3e61ee2017-04-12 17:09:20 -0700665 DISALLOW_COPY_AND_ASSIGN(HVecMax);
666};
667
Aart Bikf8f5a162017-02-06 15:35:29 -0800668// Bitwise-ands every component in the two vectors,
669// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
670class HVecAnd FINAL : public HVecBinaryOperation {
671 public:
672 HVecAnd(ArenaAllocator* arena,
673 HInstruction* left,
674 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100675 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800676 size_t vector_length,
677 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700678 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800679 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800680 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700681
682 bool CanBeMoved() const OVERRIDE { return true; }
683
Aart Bikf8f5a162017-02-06 15:35:29 -0800684 DECLARE_INSTRUCTION(VecAnd);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700685
Aart Bikf8f5a162017-02-06 15:35:29 -0800686 private:
687 DISALLOW_COPY_AND_ASSIGN(HVecAnd);
688};
689
690// Bitwise-and-nots every component in the two vectors,
691// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
692class HVecAndNot FINAL : public HVecBinaryOperation {
693 public:
694 HVecAndNot(ArenaAllocator* arena,
695 HInstruction* left,
696 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100697 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800698 size_t vector_length,
699 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700700 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800701 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800702 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700703
704 bool CanBeMoved() const OVERRIDE { return true; }
705
Aart Bikf8f5a162017-02-06 15:35:29 -0800706 DECLARE_INSTRUCTION(VecAndNot);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700707
Aart Bikf8f5a162017-02-06 15:35:29 -0800708 private:
709 DISALLOW_COPY_AND_ASSIGN(HVecAndNot);
710};
711
712// Bitwise-ors every component in the two vectors,
713// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
714class HVecOr FINAL : public HVecBinaryOperation {
715 public:
716 HVecOr(ArenaAllocator* arena,
717 HInstruction* left,
718 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100719 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800720 size_t vector_length,
721 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700722 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800723 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800724 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700725
726 bool CanBeMoved() const OVERRIDE { return true; }
727
Aart Bikf8f5a162017-02-06 15:35:29 -0800728 DECLARE_INSTRUCTION(VecOr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700729
Aart Bikf8f5a162017-02-06 15:35:29 -0800730 private:
731 DISALLOW_COPY_AND_ASSIGN(HVecOr);
732};
733
734// Bitwise-xors every component in the two vectors,
735// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
736class HVecXor FINAL : public HVecBinaryOperation {
737 public:
738 HVecXor(ArenaAllocator* arena,
739 HInstruction* left,
740 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100741 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800742 size_t vector_length,
743 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700744 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800745 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800746 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700747
748 bool CanBeMoved() const OVERRIDE { return true; }
749
Aart Bikf8f5a162017-02-06 15:35:29 -0800750 DECLARE_INSTRUCTION(VecXor);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700751
Aart Bikf8f5a162017-02-06 15:35:29 -0800752 private:
753 DISALLOW_COPY_AND_ASSIGN(HVecXor);
754};
755
756// Logically shifts every component in the vector left by the given distance,
757// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
758class HVecShl FINAL : public HVecBinaryOperation {
759 public:
760 HVecShl(ArenaAllocator* arena,
761 HInstruction* left,
762 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100763 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800764 size_t vector_length,
765 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700766 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700767 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800768 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700769
770 bool CanBeMoved() const OVERRIDE { return true; }
771
Aart Bikf8f5a162017-02-06 15:35:29 -0800772 DECLARE_INSTRUCTION(VecShl);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700773
Aart Bikf8f5a162017-02-06 15:35:29 -0800774 private:
775 DISALLOW_COPY_AND_ASSIGN(HVecShl);
776};
777
778// Arithmetically shifts every component in the vector right by the given distance,
779// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
780class HVecShr FINAL : public HVecBinaryOperation {
781 public:
782 HVecShr(ArenaAllocator* arena,
783 HInstruction* left,
784 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100785 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800786 size_t vector_length,
787 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700788 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700789 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800790 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700791
792 bool CanBeMoved() const OVERRIDE { return true; }
793
Aart Bikf8f5a162017-02-06 15:35:29 -0800794 DECLARE_INSTRUCTION(VecShr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700795
Aart Bikf8f5a162017-02-06 15:35:29 -0800796 private:
797 DISALLOW_COPY_AND_ASSIGN(HVecShr);
798};
799
800// Logically shifts every component in the vector right by the given distance,
801// viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
802class HVecUShr FINAL : public HVecBinaryOperation {
803 public:
804 HVecUShr(ArenaAllocator* arena,
805 HInstruction* left,
806 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100807 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800808 size_t vector_length,
809 uint32_t dex_pc = kNoDexPc)
Aart Bik8de59162017-04-21 09:42:01 -0700810 : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700811 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800812 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700813
814 bool CanBeMoved() const OVERRIDE { return true; }
815
Aart Bikf8f5a162017-02-06 15:35:29 -0800816 DECLARE_INSTRUCTION(VecUShr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700817
Aart Bikf8f5a162017-02-06 15:35:29 -0800818 private:
819 DISALLOW_COPY_AND_ASSIGN(HVecUShr);
820};
821
Aart Bik8de59162017-04-21 09:42:01 -0700822//
823// Definitions of concrete miscellaneous vector operations in HIR.
824//
825
826// Assigns the given scalar elements to a vector,
Aart Bikdbbac8f2017-09-01 13:06:08 -0700827// viz. set( array(x1, .. , xn) ) = [ x1, .. , xn ] if n == m,
828// set( array(x1, .. , xm) ) = [ x1, .. , xm, 0, .. , 0 ] if m < n.
Aart Bik8de59162017-04-21 09:42:01 -0700829class HVecSetScalars FINAL : public HVecOperation {
Aart Bik0148de42017-09-05 09:25:01 -0700830 public:
Aart Bik8de59162017-04-21 09:42:01 -0700831 HVecSetScalars(ArenaAllocator* arena,
Aart Bik5e3afa92017-09-20 14:11:11 -0700832 HInstruction* scalars[],
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100833 DataType::Type packed_type,
Aart Bik8de59162017-04-21 09:42:01 -0700834 size_t vector_length,
Aart Bik0148de42017-09-05 09:25:01 -0700835 size_t number_of_scalars,
Aart Bik8de59162017-04-21 09:42:01 -0700836 uint32_t dex_pc = kNoDexPc)
837 : HVecOperation(arena,
838 packed_type,
839 SideEffects::None(),
Aart Bik0148de42017-09-05 09:25:01 -0700840 number_of_scalars,
Aart Bik8de59162017-04-21 09:42:01 -0700841 vector_length,
842 dex_pc) {
Aart Bik0148de42017-09-05 09:25:01 -0700843 for (size_t i = 0; i < number_of_scalars; i++) {
Aart Bik5e3afa92017-09-20 14:11:11 -0700844 DCHECK(!scalars[i]->IsVecOperation() || scalars[i]->IsVecExtractScalar());
Aart Bik8de59162017-04-21 09:42:01 -0700845 SetRawInputAt(0, scalars[i]);
846 }
847 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700848
849 // Setting scalars needs to stay in place, since SIMD registers are not
850 // kept alive across vector loop boundaries (yet).
851 bool CanBeMoved() const OVERRIDE { return false; }
852
Aart Bik8de59162017-04-21 09:42:01 -0700853 DECLARE_INSTRUCTION(VecSetScalars);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700854
Aart Bik8de59162017-04-21 09:42:01 -0700855 private:
856 DISALLOW_COPY_AND_ASSIGN(HVecSetScalars);
857};
858
Aart Bikdbbac8f2017-09-01 13:06:08 -0700859// Multiplies every component in the two vectors, adds the result vector to the accumulator vector,
860// viz. [ a1, .. , an ] + [ x1, .. , xn ] * [ y1, .. , yn ] = [ a1 + x1 * y1, .. , an + xn * yn ].
Artem Serovf34dd202017-04-10 17:41:46 +0100861class HVecMultiplyAccumulate FINAL : public HVecOperation {
862 public:
863 HVecMultiplyAccumulate(ArenaAllocator* arena,
864 InstructionKind op,
865 HInstruction* accumulator,
866 HInstruction* mul_left,
867 HInstruction* mul_right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100868 DataType::Type packed_type,
Artem Serovf34dd202017-04-10 17:41:46 +0100869 size_t vector_length,
870 uint32_t dex_pc = kNoDexPc)
871 : HVecOperation(arena,
872 packed_type,
873 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700874 /* number_of_inputs */ 3,
Artem Serovf34dd202017-04-10 17:41:46 +0100875 vector_length,
876 dex_pc),
877 op_kind_(op) {
878 DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
Aart Bikd58bc322017-05-01 14:49:18 -0700879 DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
880 DCHECK(HasConsistentPackedTypes(mul_left, packed_type));
881 DCHECK(HasConsistentPackedTypes(mul_right, packed_type));
Aart Bikdbbac8f2017-09-01 13:06:08 -0700882 SetRawInputAt(0, accumulator);
883 SetRawInputAt(1, mul_left);
884 SetRawInputAt(2, mul_right);
Artem Serovf34dd202017-04-10 17:41:46 +0100885 }
886
Nicolas Geoffray9858bf72017-07-08 12:34:55 +0000887 bool CanBeMoved() const OVERRIDE { return true; }
888
Artem Serovf34dd202017-04-10 17:41:46 +0100889 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
Aart Bikb79f4ac2017-07-10 10:10:37 -0700890 DCHECK(other->IsVecMultiplyAccumulate());
891 const HVecMultiplyAccumulate* o = other->AsVecMultiplyAccumulate();
892 return HVecOperation::InstructionDataEquals(o) && GetOpKind() == o->GetOpKind();
Artem Serovf34dd202017-04-10 17:41:46 +0100893 }
894
895 InstructionKind GetOpKind() const { return op_kind_; }
896
897 DECLARE_INSTRUCTION(VecMultiplyAccumulate);
898
899 private:
900 // Indicates if this is a MADD or MSUB.
901 const InstructionKind op_kind_;
902
903 DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate);
904};
905
Aart Bikdbbac8f2017-09-01 13:06:08 -0700906// Takes the absolute difference of two vectors, and adds the results to
907// same-precision or wider-precision components in the accumulator,
908// viz. SAD([ a1, .. , am ], [ x1, .. , xn ], [ y1, .. , yn ] =
909// [ a1 + sum abs(xi-yi), .. , am + sum abs(xj-yj) ],
910// for m <= n and non-overlapping sums.
911class HVecSADAccumulate FINAL : public HVecOperation {
912 public:
913 HVecSADAccumulate(ArenaAllocator* arena,
914 HInstruction* accumulator,
915 HInstruction* sad_left,
916 HInstruction* sad_right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100917 DataType::Type packed_type,
Aart Bikdbbac8f2017-09-01 13:06:08 -0700918 size_t vector_length,
919 uint32_t dex_pc = kNoDexPc)
920 : HVecOperation(arena,
921 packed_type,
922 SideEffects::None(),
923 /* number_of_inputs */ 3,
924 vector_length,
925 dex_pc) {
926 DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
927 DCHECK(sad_left->IsVecOperation());
928 DCHECK(sad_right->IsVecOperation());
929 DCHECK_EQ(sad_left->AsVecOperation()->GetPackedType(),
930 sad_right->AsVecOperation()->GetPackedType());
931 SetRawInputAt(0, accumulator);
932 SetRawInputAt(1, sad_left);
933 SetRawInputAt(2, sad_right);
934 }
935
936 DECLARE_INSTRUCTION(VecSADAccumulate);
937
938 private:
939 DISALLOW_COPY_AND_ASSIGN(HVecSADAccumulate);
940};
941
Aart Bikf8f5a162017-02-06 15:35:29 -0800942// Loads a vector from memory, viz. load(mem, 1)
943// yield the vector [ mem(1), .. , mem(n) ].
944class HVecLoad FINAL : public HVecMemoryOperation {
945 public:
946 HVecLoad(ArenaAllocator* arena,
947 HInstruction* base,
948 HInstruction* index,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100949 DataType::Type packed_type,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100950 SideEffects side_effects,
Aart Bikf8f5a162017-02-06 15:35:29 -0800951 size_t vector_length,
Aart Bikdb14fcf2017-04-25 15:53:58 -0700952 bool is_string_char_at,
Aart Bikf8f5a162017-02-06 15:35:29 -0800953 uint32_t dex_pc = kNoDexPc)
954 : HVecMemoryOperation(arena,
955 packed_type,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100956 side_effects,
Aart Bik8de59162017-04-21 09:42:01 -0700957 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800958 vector_length,
959 dex_pc) {
960 SetRawInputAt(0, base);
961 SetRawInputAt(1, index);
Aart Bikdb14fcf2017-04-25 15:53:58 -0700962 SetPackedFlag<kFieldIsStringCharAt>(is_string_char_at);
Aart Bikf8f5a162017-02-06 15:35:29 -0800963 }
Aart Bikdb14fcf2017-04-25 15:53:58 -0700964
965 bool IsStringCharAt() const { return GetPackedFlag<kFieldIsStringCharAt>(); }
966
Aart Bikb79f4ac2017-07-10 10:10:37 -0700967 bool CanBeMoved() const OVERRIDE { return true; }
968
969 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
970 DCHECK(other->IsVecLoad());
971 const HVecLoad* o = other->AsVecLoad();
972 return HVecMemoryOperation::InstructionDataEquals(o) && IsStringCharAt() == o->IsStringCharAt();
973 }
974
975 DECLARE_INSTRUCTION(VecLoad);
976
Aart Bikf8f5a162017-02-06 15:35:29 -0800977 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700978 // Additional packed bits.
979 static constexpr size_t kFieldIsStringCharAt = HVecOperation::kNumberOfVectorOpPackedBits;
980 static constexpr size_t kNumberOfVecLoadPackedBits = kFieldIsStringCharAt + 1;
981 static_assert(kNumberOfVecLoadPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
982
Aart Bikf8f5a162017-02-06 15:35:29 -0800983 DISALLOW_COPY_AND_ASSIGN(HVecLoad);
984};
985
986// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
987// sets mem(1) = x1, .. , mem(n) = xn.
988class HVecStore FINAL : public HVecMemoryOperation {
989 public:
990 HVecStore(ArenaAllocator* arena,
991 HInstruction* base,
992 HInstruction* index,
993 HInstruction* value,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100994 DataType::Type packed_type,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100995 SideEffects side_effects,
Aart Bikf8f5a162017-02-06 15:35:29 -0800996 size_t vector_length,
997 uint32_t dex_pc = kNoDexPc)
998 : HVecMemoryOperation(arena,
999 packed_type,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001000 side_effects,
Aart Bik8de59162017-04-21 09:42:01 -07001001 /* number_of_inputs */ 3,
Aart Bikf8f5a162017-02-06 15:35:29 -08001002 vector_length,
1003 dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -07001004 DCHECK(HasConsistentPackedTypes(value, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -08001005 SetRawInputAt(0, base);
1006 SetRawInputAt(1, index);
1007 SetRawInputAt(2, value);
1008 }
Aart Bikb79f4ac2017-07-10 10:10:37 -07001009
1010 // A store needs to stay in place.
1011 bool CanBeMoved() const OVERRIDE { return false; }
1012
Aart Bikf8f5a162017-02-06 15:35:29 -08001013 DECLARE_INSTRUCTION(VecStore);
Aart Bikb79f4ac2017-07-10 10:10:37 -07001014
Aart Bikf8f5a162017-02-06 15:35:29 -08001015 private:
1016 DISALLOW_COPY_AND_ASSIGN(HVecStore);
1017};
1018
1019} // namespace art
1020
1021#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_