blob: c5e9a8d036f4fc59f7f00e621fc066f13decc66c [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
Aart Bik46b6dbc2017-10-03 11:37:37 -070037 // Returns true if memory is at least aligned at the given boundary.
Aart Bikf8f5a162017-02-06 15:35:29 -080038 // 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
Aart Bik46b6dbc2017-10-03 11:37:37 -070045 size_t Base() const { return base_; }
46
47 size_t Offset() const { return offset_; }
48
Aart Bikf8f5a162017-02-06 15:35:29 -080049 std::string ToString() const {
50 return "ALIGN(" + std::to_string(base_) + "," + std::to_string(offset_) + ")";
51 }
52
Aart Bikb79f4ac2017-07-10 10:10:37 -070053 bool operator==(const Alignment& other) const {
54 return base_ == other.base_ && offset_ == other.offset_;
55 }
56
Aart Bikf8f5a162017-02-06 15:35:29 -080057 private:
58 size_t base_;
59 size_t offset_;
60};
61
62//
63// Definitions of abstract vector operations in HIR.
64//
65
66// Abstraction of a vector operation, i.e., an operation that performs
67// GetVectorLength() x GetPackedType() operations simultaneously.
68class HVecOperation : public HVariableInputSizeInstruction {
69 public:
Aart Bik0148de42017-09-05 09:25:01 -070070 // A SIMD operation looks like a FPU location.
71 // TODO: we could introduce SIMD types in HIR.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010072 static constexpr DataType::Type kSIMDType = DataType::Type::kFloat64;
Aart Bik0148de42017-09-05 09:25:01 -070073
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +053074 HVecOperation(InstructionKind kind,
75 ArenaAllocator* allocator,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010076 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -080077 SideEffects side_effects,
78 size_t number_of_inputs,
79 size_t vector_length,
80 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +053081 : HVariableInputSizeInstruction(kind,
Vladimir Markobd785672018-05-03 17:09:09 +010082 kSIMDType,
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +053083 side_effects,
Aart Bikf8f5a162017-02-06 15:35:29 -080084 dex_pc,
Vladimir Markoe764d2e2017-10-05 14:35:55 +010085 allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -080086 number_of_inputs,
87 kArenaAllocVectorNode),
88 vector_length_(vector_length) {
Vladimir Markobd785672018-05-03 17:09:09 +010089 SetPackedField<PackedTypeField>(packed_type);
Aart Bikf8f5a162017-02-06 15:35:29 -080090 DCHECK_LT(1u, vector_length);
91 }
92
93 // Returns the number of elements packed in a vector.
94 size_t GetVectorLength() const {
95 return vector_length_;
96 }
97
98 // Returns the number of bytes in a full vector.
99 size_t GetVectorNumberOfBytes() const {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100100 return vector_length_ * DataType::Size(GetPackedType());
Aart Bikf8f5a162017-02-06 15:35:29 -0800101 }
102
Aart Bikf8f5a162017-02-06 15:35:29 -0800103 // Returns the true component type packed in a vector.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100104 DataType::Type GetPackedType() const {
Vladimir Markobd785672018-05-03 17:09:09 +0100105 return GetPackedField<PackedTypeField>();
Aart Bikf8f5a162017-02-06 15:35:29 -0800106 }
107
Aart Bikb79f4ac2017-07-10 10:10:37 -0700108 // Assumes vector nodes cannot be moved by default. Each concrete implementation
109 // that can be moved should override this method and return true.
Artem Serov89ff8b22017-11-20 11:51:05 +0000110 //
111 // Note: similar approach is used for instruction scheduling (if it is turned on for the target):
112 // by default HScheduler::IsSchedulable returns false for a particular HVecOperation.
113 // HScheduler${ARCH}::IsSchedulable can be overridden to return true for an instruction (see
114 // scheduler_arm64.h for example) if it is safe to schedule it; in this case one *must* also
115 // look at/update HScheduler${ARCH}::IsSchedulingBarrier for this instruction.
116 //
117 // Note: For newly introduced vector instructions HScheduler${ARCH}::IsSchedulingBarrier must be
118 // altered to return true if the instruction might reside outside the SIMD loop body since SIMD
119 // registers are not kept alive across vector loop boundaries (yet).
Aart Bikb79f4ac2017-07-10 10:10:37 -0700120 bool CanBeMoved() const OVERRIDE { return false; }
121
122 // Tests if all data of a vector node (vector length and packed type) is equal.
123 // Each concrete implementation that adds more fields should test equality of
124 // those fields in its own method *and* call all super methods.
125 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
126 DCHECK(other->IsVecOperation());
127 const HVecOperation* o = other->AsVecOperation();
128 return GetVectorLength() == o->GetVectorLength() && GetPackedType() == o->GetPackedType();
129 }
130
Aart Bik46b6dbc2017-10-03 11:37:37 -0700131 // Maps an integral type to the same-size signed type and leaves other types alone.
Aart Bik46b6dbc2017-10-03 11:37:37 -0700132 static DataType::Type ToSignedType(DataType::Type type) {
133 switch (type) {
134 case DataType::Type::kBool: // 1-byte storage unit
135 case DataType::Type::kUint8:
136 return DataType::Type::kInt8;
137 case DataType::Type::kUint16:
138 return DataType::Type::kInt16;
139 default:
140 DCHECK(type != DataType::Type::kVoid && type != DataType::Type::kReference) << type;
141 return type;
142 }
143 }
144
Aart Bik4d1a9d42017-10-19 14:40:55 -0700145 // Maps an integral type to the same-size unsigned type and leaves other types alone.
146 static DataType::Type ToUnsignedType(DataType::Type type) {
147 switch (type) {
148 case DataType::Type::kBool: // 1-byte storage unit
149 case DataType::Type::kInt8:
150 return DataType::Type::kUint8;
151 case DataType::Type::kInt16:
152 return DataType::Type::kUint16;
153 default:
154 DCHECK(type != DataType::Type::kVoid && type != DataType::Type::kReference) << type;
155 return type;
156 }
157 }
158
Aart Bik66c158e2018-01-31 12:55:04 -0800159 // Maps an integral type to the same-size (un)signed type. Leaves other types alone.
160 static DataType::Type ToProperType(DataType::Type type, bool is_unsigned) {
161 return is_unsigned ? ToUnsignedType(type) : ToSignedType(type);
162 }
163
Aart Bik2dd7b672017-12-07 11:11:22 -0800164 // Helper method to determine if an instruction returns a SIMD value.
165 // TODO: This method is needed until we introduce SIMD as proper type.
166 static bool ReturnsSIMDValue(HInstruction* instruction) {
167 if (instruction->IsVecOperation()) {
168 return !instruction->IsVecExtractScalar(); // only scalar returning vec op
169 } else if (instruction->IsPhi()) {
Aart Bik3f8e02c2018-04-10 11:55:00 -0700170 // Vectorizer only uses Phis in reductions, so checking for a 2-way phi
171 // with a direct vector operand as second argument suffices.
Aart Bik2dd7b672017-12-07 11:11:22 -0800172 return
173 instruction->GetType() == kSIMDType &&
Aart Bik3f8e02c2018-04-10 11:55:00 -0700174 instruction->InputCount() == 2 &&
175 instruction->InputAt(1)->IsVecOperation();
Aart Bik2dd7b672017-12-07 11:11:22 -0800176 }
177 return false;
178 }
179
Aart Bikf8f5a162017-02-06 15:35:29 -0800180 DECLARE_ABSTRACT_INSTRUCTION(VecOperation);
181
Aart Bikdb14fcf2017-04-25 15:53:58 -0700182 protected:
Aart Bikf8f5a162017-02-06 15:35:29 -0800183 // Additional packed bits.
Vladimir Markobd785672018-05-03 17:09:09 +0100184 static constexpr size_t kFieldPackedType = HInstruction::kNumberOfGenericPackedBits;
185 static constexpr size_t kFieldPackedTypeSize =
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100186 MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
Vladimir Markobd785672018-05-03 17:09:09 +0100187 static constexpr size_t kNumberOfVectorOpPackedBits = kFieldPackedType + kFieldPackedTypeSize;
Aart Bikf8f5a162017-02-06 15:35:29 -0800188 static_assert(kNumberOfVectorOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Vladimir Markobd785672018-05-03 17:09:09 +0100189 using PackedTypeField = BitField<DataType::Type, kFieldPackedType, kFieldPackedTypeSize>;
Aart Bikf8f5a162017-02-06 15:35:29 -0800190
Artem Serovcced8ba2017-07-19 18:18:09 +0100191 DEFAULT_COPY_CONSTRUCTOR(VecOperation);
192
Aart Bikdb14fcf2017-04-25 15:53:58 -0700193 private:
Aart Bikf8f5a162017-02-06 15:35:29 -0800194 const size_t vector_length_;
Aart Bikf8f5a162017-02-06 15:35:29 -0800195};
196
197// Abstraction of a unary vector operation.
198class HVecUnaryOperation : public HVecOperation {
199 public:
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530200 HVecUnaryOperation(InstructionKind kind,
201 ArenaAllocator* allocator,
Aart Bik8de59162017-04-21 09:42:01 -0700202 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100203 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800204 size_t vector_length,
205 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530206 : HVecOperation(kind,
207 allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800208 packed_type,
209 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700210 /* number_of_inputs */ 1,
Aart Bikf8f5a162017-02-06 15:35:29 -0800211 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700212 dex_pc) {
213 SetRawInputAt(0, input);
214 }
215
216 HInstruction* GetInput() const { return InputAt(0); }
217
Aart Bikf8f5a162017-02-06 15:35:29 -0800218 DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700219
Artem Serovcced8ba2017-07-19 18:18:09 +0100220 protected:
221 DEFAULT_COPY_CONSTRUCTOR(VecUnaryOperation);
Aart Bikf8f5a162017-02-06 15:35:29 -0800222};
223
224// Abstraction of a binary vector operation.
225class HVecBinaryOperation : public HVecOperation {
226 public:
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530227 HVecBinaryOperation(InstructionKind kind,
228 ArenaAllocator* allocator,
Aart Bik8de59162017-04-21 09:42:01 -0700229 HInstruction* left,
230 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100231 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800232 size_t vector_length,
233 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530234 : HVecOperation(kind,
235 allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800236 packed_type,
237 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700238 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -0800239 vector_length,
Aart Bik8de59162017-04-21 09:42:01 -0700240 dex_pc) {
241 SetRawInputAt(0, left);
242 SetRawInputAt(1, right);
243 }
Artem Serovf34dd202017-04-10 17:41:46 +0100244
245 HInstruction* GetLeft() const { return InputAt(0); }
246 HInstruction* GetRight() const { return InputAt(1); }
247
Aart Bikf8f5a162017-02-06 15:35:29 -0800248 DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
Aart Bik8de59162017-04-21 09:42:01 -0700249
Artem Serovcced8ba2017-07-19 18:18:09 +0100250 protected:
251 DEFAULT_COPY_CONSTRUCTOR(VecBinaryOperation);
Aart Bikf8f5a162017-02-06 15:35:29 -0800252};
253
254// Abstraction of a vector operation that references memory, with an alignment.
Aart Bik46b6dbc2017-10-03 11:37:37 -0700255// The Android runtime guarantees elements have at least natural alignment.
Aart Bikf8f5a162017-02-06 15:35:29 -0800256class HVecMemoryOperation : public HVecOperation {
257 public:
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530258 HVecMemoryOperation(InstructionKind kind,
259 ArenaAllocator* allocator,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100260 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800261 SideEffects side_effects,
262 size_t number_of_inputs,
263 size_t vector_length,
264 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530265 : HVecOperation(kind,
266 allocator,
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100267 packed_type,
268 side_effects,
269 number_of_inputs,
270 vector_length,
271 dex_pc),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100272 alignment_(DataType::Size(packed_type), 0) {
Artem Serove1811ed2017-04-27 16:50:47 +0100273 DCHECK_GE(number_of_inputs, 2u);
274 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800275
276 void SetAlignment(Alignment alignment) { alignment_ = alignment; }
277
278 Alignment GetAlignment() const { return alignment_; }
279
Artem Serove1811ed2017-04-27 16:50:47 +0100280 HInstruction* GetArray() const { return InputAt(0); }
281 HInstruction* GetIndex() const { return InputAt(1); }
282
Aart Bikb79f4ac2017-07-10 10:10:37 -0700283 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
284 DCHECK(other->IsVecMemoryOperation());
285 const HVecMemoryOperation* o = other->AsVecMemoryOperation();
286 return HVecOperation::InstructionDataEquals(o) && GetAlignment() == o->GetAlignment();
287 }
288
Aart Bikf8f5a162017-02-06 15:35:29 -0800289 DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
290
Artem Serovcced8ba2017-07-19 18:18:09 +0100291 protected:
292 DEFAULT_COPY_CONSTRUCTOR(VecMemoryOperation);
293
Aart Bikf8f5a162017-02-06 15:35:29 -0800294 private:
295 Alignment alignment_;
Aart Bikf8f5a162017-02-06 15:35:29 -0800296};
297
Aart Bik0148de42017-09-05 09:25:01 -0700298// Packed type consistency checker ("same vector length" integral types may mix freely).
Aart Bik66c158e2018-01-31 12:55:04 -0800299// Tests relaxed type consistency in which packed same-size integral types can co-exist,
300// but other type mixes are an error.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100301inline static bool HasConsistentPackedTypes(HInstruction* input, DataType::Type type) {
Aart Bik0148de42017-09-05 09:25:01 -0700302 if (input->IsPhi()) {
303 return input->GetType() == HVecOperation::kSIMDType; // carries SIMD
304 }
Aart Bikd58bc322017-05-01 14:49:18 -0700305 DCHECK(input->IsVecOperation());
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100306 DataType::Type input_type = input->AsVecOperation()->GetPackedType();
Aart Bik4d1a9d42017-10-19 14:40:55 -0700307 DCHECK_EQ(HVecOperation::ToUnsignedType(input_type) == HVecOperation::ToUnsignedType(type),
308 HVecOperation::ToSignedType(input_type) == HVecOperation::ToSignedType(type));
Aart Bik46b6dbc2017-10-03 11:37:37 -0700309 return HVecOperation::ToSignedType(input_type) == HVecOperation::ToSignedType(type);
Aart Bikd58bc322017-05-01 14:49:18 -0700310}
311
Aart Bikf8f5a162017-02-06 15:35:29 -0800312//
Aart Bik8de59162017-04-21 09:42:01 -0700313// Definitions of concrete unary vector operations in HIR.
Aart Bikf8f5a162017-02-06 15:35:29 -0800314//
315
316// Replicates the given scalar into a vector,
317// viz. replicate(x) = [ x, .. , x ].
318class HVecReplicateScalar FINAL : public HVecUnaryOperation {
319 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100320 HVecReplicateScalar(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800321 HInstruction* scalar,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100322 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800323 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700324 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530325 : HVecUnaryOperation(
326 kVecReplicateScalar, allocator, scalar, packed_type, vector_length, dex_pc) {
Aart Bik5a0eb0c2018-03-16 15:00:19 -0700327 DCHECK(!ReturnsSIMDValue(scalar));
Aart Bikf8f5a162017-02-06 15:35:29 -0800328 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700329
330 // A replicate needs to stay in place, since SIMD registers are not
331 // kept alive across vector loop boundaries (yet).
332 bool CanBeMoved() const OVERRIDE { return false; }
333
Aart Bikf8f5a162017-02-06 15:35:29 -0800334 DECLARE_INSTRUCTION(VecReplicateScalar);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700335
Artem Serovcced8ba2017-07-19 18:18:09 +0100336 protected:
337 DEFAULT_COPY_CONSTRUCTOR(VecReplicateScalar);
Aart Bikf8f5a162017-02-06 15:35:29 -0800338};
339
Aart Bik0148de42017-09-05 09:25:01 -0700340// Extracts a particular scalar from the given vector,
341// viz. extract[ x1, .. , xn ] = x_i.
342//
343// TODO: for now only i == 1 case supported.
344class HVecExtractScalar FINAL : public HVecUnaryOperation {
345 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100346 HVecExtractScalar(ArenaAllocator* allocator,
Aart Bik0148de42017-09-05 09:25:01 -0700347 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100348 DataType::Type packed_type,
Aart Bik0148de42017-09-05 09:25:01 -0700349 size_t vector_length,
350 size_t index,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700351 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530352 : HVecUnaryOperation(
353 kVecExtractScalar, allocator, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700354 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik0148de42017-09-05 09:25:01 -0700355 DCHECK_LT(index, vector_length);
356 DCHECK_EQ(index, 0u);
Vladimir Markobd785672018-05-03 17:09:09 +0100357 // Yields a single component in the vector.
358 // Overrides the kSIMDType set by the VecOperation constructor.
359 SetPackedField<TypeField>(packed_type);
Aart Bik0148de42017-09-05 09:25:01 -0700360 }
361
362 // An extract needs to stay in place, since SIMD registers are not
363 // kept alive across vector loop boundaries (yet).
364 bool CanBeMoved() const OVERRIDE { return false; }
365
366 DECLARE_INSTRUCTION(VecExtractScalar);
367
Artem Serovcced8ba2017-07-19 18:18:09 +0100368 protected:
369 DEFAULT_COPY_CONSTRUCTOR(VecExtractScalar);
Aart Bik0148de42017-09-05 09:25:01 -0700370};
371
372// Reduces the given vector into the first element as sum/min/max,
373// viz. sum-reduce[ x1, .. , xn ] = [ y, ---- ], where y = sum xi
374// and the "-" denotes "don't care" (implementation dependent).
375class HVecReduce FINAL : public HVecUnaryOperation {
376 public:
377 enum ReductionKind {
378 kSum = 1,
379 kMin = 2,
380 kMax = 3
381 };
382
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100383 HVecReduce(ArenaAllocator* allocator,
Aart Bik0148de42017-09-05 09:25:01 -0700384 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100385 DataType::Type packed_type,
Aart Bik0148de42017-09-05 09:25:01 -0700386 size_t vector_length,
387 ReductionKind kind,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700388 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530389 : HVecUnaryOperation(kVecReduce, allocator, input, packed_type, vector_length, dex_pc),
Aart Bik0148de42017-09-05 09:25:01 -0700390 kind_(kind) {
391 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikcfa59b42017-08-31 09:08:13 -0700392 }
393
Aart Bik0148de42017-09-05 09:25:01 -0700394 ReductionKind GetKind() const { return kind_; }
Aart Bikf8f5a162017-02-06 15:35:29 -0800395
Aart Bikb79f4ac2017-07-10 10:10:37 -0700396 bool CanBeMoved() const OVERRIDE { return true; }
397
Aart Bik0148de42017-09-05 09:25:01 -0700398 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
399 DCHECK(other->IsVecReduce());
400 const HVecReduce* o = other->AsVecReduce();
401 return HVecOperation::InstructionDataEquals(o) && GetKind() == o->GetKind();
402 }
403
404 DECLARE_INSTRUCTION(VecReduce);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700405
Artem Serovcced8ba2017-07-19 18:18:09 +0100406 protected:
407 DEFAULT_COPY_CONSTRUCTOR(VecReduce);
408
Aart Bikf8f5a162017-02-06 15:35:29 -0800409 private:
Aart Bik0148de42017-09-05 09:25:01 -0700410 const ReductionKind kind_;
Aart Bikf8f5a162017-02-06 15:35:29 -0800411};
412
413// Converts every component in the vector,
414// viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ].
415class HVecCnv FINAL : public HVecUnaryOperation {
416 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100417 HVecCnv(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800418 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100419 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800420 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700421 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530422 : HVecUnaryOperation(kVecCnv, allocator, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800423 DCHECK(input->IsVecOperation());
Aart Bikd58bc322017-05-01 14:49:18 -0700424 DCHECK_NE(GetInputType(), GetResultType()); // actual convert
Aart Bikf8f5a162017-02-06 15:35:29 -0800425 }
426
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100427 DataType::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
428 DataType::Type GetResultType() const { return GetPackedType(); }
Aart Bikf8f5a162017-02-06 15:35:29 -0800429
Aart Bikb79f4ac2017-07-10 10:10:37 -0700430 bool CanBeMoved() const OVERRIDE { return true; }
431
Aart Bikf8f5a162017-02-06 15:35:29 -0800432 DECLARE_INSTRUCTION(VecCnv);
433
Artem Serovcced8ba2017-07-19 18:18:09 +0100434 protected:
435 DEFAULT_COPY_CONSTRUCTOR(VecCnv);
Aart Bikf8f5a162017-02-06 15:35:29 -0800436};
437
438// Negates every component in the vector,
439// viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ].
440class HVecNeg FINAL : public HVecUnaryOperation {
441 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100442 HVecNeg(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800443 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100444 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800445 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700446 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530447 : HVecUnaryOperation(kVecNeg, allocator, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700448 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800449 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700450
451 bool CanBeMoved() const OVERRIDE { return true; }
452
Aart Bikf8f5a162017-02-06 15:35:29 -0800453 DECLARE_INSTRUCTION(VecNeg);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700454
Artem Serovcced8ba2017-07-19 18:18:09 +0100455 protected:
456 DEFAULT_COPY_CONSTRUCTOR(VecNeg);
Aart Bikf8f5a162017-02-06 15:35:29 -0800457};
458
Aart Bik6daebeb2017-04-03 14:35:41 -0700459// Takes absolute value of every component in the vector,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700460// viz. abs[ x1, .. , xn ] = [ |x1|, .. , |xn| ]
461// for signed operand x.
Aart Bik6daebeb2017-04-03 14:35:41 -0700462class HVecAbs FINAL : public HVecUnaryOperation {
463 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100464 HVecAbs(ArenaAllocator* allocator,
Aart Bik6daebeb2017-04-03 14:35:41 -0700465 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100466 DataType::Type packed_type,
Aart Bik6daebeb2017-04-03 14:35:41 -0700467 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700468 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530469 : HVecUnaryOperation(kVecAbs, allocator, input, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700470 DCHECK(HasConsistentPackedTypes(input, packed_type));
Aart Bik6daebeb2017-04-03 14:35:41 -0700471 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700472
473 bool CanBeMoved() const OVERRIDE { return true; }
474
Aart Bik6daebeb2017-04-03 14:35:41 -0700475 DECLARE_INSTRUCTION(VecAbs);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700476
Artem Serovcced8ba2017-07-19 18:18:09 +0100477 protected:
478 DEFAULT_COPY_CONSTRUCTOR(VecAbs);
Aart Bik6daebeb2017-04-03 14:35:41 -0700479};
480
Aart Bikf8f5a162017-02-06 15:35:29 -0800481// Bitwise- or boolean-nots every component in the vector,
482// viz. not[ x1, .. , xn ] = [ ~x1, .. , ~xn ], or
483// not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean.
484class HVecNot FINAL : public HVecUnaryOperation {
485 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100486 HVecNot(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800487 HInstruction* input,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100488 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800489 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700490 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530491 : HVecUnaryOperation(kVecNot, allocator, input, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800492 DCHECK(input->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800493 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700494
495 bool CanBeMoved() const OVERRIDE { return true; }
496
Aart Bikf8f5a162017-02-06 15:35:29 -0800497 DECLARE_INSTRUCTION(VecNot);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700498
Artem Serovcced8ba2017-07-19 18:18:09 +0100499 protected:
500 DEFAULT_COPY_CONSTRUCTOR(VecNot);
Aart Bikf8f5a162017-02-06 15:35:29 -0800501};
502
Aart Bik8de59162017-04-21 09:42:01 -0700503//
504// Definitions of concrete binary vector operations in HIR.
505//
506
Aart Bikf8f5a162017-02-06 15:35:29 -0800507// Adds every component in the two vectors,
508// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
509class HVecAdd FINAL : public HVecBinaryOperation {
510 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100511 HVecAdd(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800512 HInstruction* left,
513 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100514 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800515 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700516 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530517 : HVecBinaryOperation(kVecAdd, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700518 DCHECK(HasConsistentPackedTypes(left, packed_type));
519 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800520 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700521
522 bool CanBeMoved() const OVERRIDE { return true; }
523
Aart Bikf8f5a162017-02-06 15:35:29 -0800524 DECLARE_INSTRUCTION(VecAdd);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700525
Artem Serovcced8ba2017-07-19 18:18:09 +0100526 protected:
527 DEFAULT_COPY_CONSTRUCTOR(VecAdd);
Aart Bikf8f5a162017-02-06 15:35:29 -0800528};
529
Aart Bik29aa0822018-03-08 11:28:00 -0800530// Adds every component in the two vectors using saturation arithmetic,
531// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 +_sat y1, .. , xn +_sat yn ]
532// for either both signed or both unsigned operands x, y (reflected in packed_type).
533class HVecSaturationAdd FINAL : public HVecBinaryOperation {
534 public:
535 HVecSaturationAdd(ArenaAllocator* allocator,
536 HInstruction* left,
537 HInstruction* right,
538 DataType::Type packed_type,
539 size_t vector_length,
540 uint32_t dex_pc)
541 : HVecBinaryOperation(
542 kVecSaturationAdd, allocator, left, right, packed_type, vector_length, dex_pc) {
543 DCHECK(HasConsistentPackedTypes(left, packed_type));
544 DCHECK(HasConsistentPackedTypes(right, packed_type));
545 }
546
547 bool CanBeMoved() const OVERRIDE { return true; }
548
549 DECLARE_INSTRUCTION(VecSaturationAdd);
550
551 protected:
552 DEFAULT_COPY_CONSTRUCTOR(VecSaturationAdd);
553};
554
Aart Bikf3e61ee2017-04-12 17:09:20 -0700555// Performs halving add on every component in the two vectors, viz.
Aart Bikdbbac8f2017-09-01 13:06:08 -0700556// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
557// truncated [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ]
Aart Bik66c158e2018-01-31 12:55:04 -0800558// for either both signed or both unsigned operands x, y (reflected in packed_type).
Aart Bikf3e61ee2017-04-12 17:09:20 -0700559class HVecHalvingAdd FINAL : public HVecBinaryOperation {
560 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100561 HVecHalvingAdd(ArenaAllocator* allocator,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700562 HInstruction* left,
563 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100564 DataType::Type packed_type,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700565 size_t vector_length,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700566 bool is_rounded,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700567 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530568 : HVecBinaryOperation(
569 kVecHalvingAdd, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700570 DCHECK(HasConsistentPackedTypes(left, packed_type));
571 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikdb14fcf2017-04-25 15:53:58 -0700572 SetPackedFlag<kFieldHAddIsRounded>(is_rounded);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700573 }
574
Aart Bikdb14fcf2017-04-25 15:53:58 -0700575 bool IsRounded() const { return GetPackedFlag<kFieldHAddIsRounded>(); }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700576
Aart Bikb79f4ac2017-07-10 10:10:37 -0700577 bool CanBeMoved() const OVERRIDE { return true; }
578
579 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
580 DCHECK(other->IsVecHalvingAdd());
581 const HVecHalvingAdd* o = other->AsVecHalvingAdd();
Aart Bik66c158e2018-01-31 12:55:04 -0800582 return HVecOperation::InstructionDataEquals(o) && IsRounded() == o->IsRounded();
Aart Bikb79f4ac2017-07-10 10:10:37 -0700583 }
584
Aart Bikf3e61ee2017-04-12 17:09:20 -0700585 DECLARE_INSTRUCTION(VecHalvingAdd);
586
Artem Serovcced8ba2017-07-19 18:18:09 +0100587 protected:
588 DEFAULT_COPY_CONSTRUCTOR(VecHalvingAdd);
589
Aart Bikf3e61ee2017-04-12 17:09:20 -0700590 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -0700591 // Additional packed bits.
Aart Bik66c158e2018-01-31 12:55:04 -0800592 static constexpr size_t kFieldHAddIsRounded = HVecOperation::kNumberOfVectorOpPackedBits;
Aart Bikdb14fcf2017-04-25 15:53:58 -0700593 static constexpr size_t kNumberOfHAddPackedBits = kFieldHAddIsRounded + 1;
594 static_assert(kNumberOfHAddPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Aart Bikf3e61ee2017-04-12 17:09:20 -0700595};
596
Aart Bikf8f5a162017-02-06 15:35:29 -0800597// Subtracts every component in the two vectors,
598// viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
599class HVecSub FINAL : public HVecBinaryOperation {
600 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100601 HVecSub(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800602 HInstruction* left,
603 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100604 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800605 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700606 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530607 : HVecBinaryOperation(kVecSub, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700608 DCHECK(HasConsistentPackedTypes(left, packed_type));
609 DCHECK(HasConsistentPackedTypes(right, packed_type));
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(VecSub);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700615
Artem Serovcced8ba2017-07-19 18:18:09 +0100616 protected:
617 DEFAULT_COPY_CONSTRUCTOR(VecSub);
Aart Bikf8f5a162017-02-06 15:35:29 -0800618};
619
Aart Bik29aa0822018-03-08 11:28:00 -0800620// Subtracts every component in the two vectors using saturation arithmetic,
621// viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 -_sat y1, .. , xn -_sat yn ]
622// for either both signed or both unsigned operands x, y (reflected in packed_type).
623class HVecSaturationSub FINAL : public HVecBinaryOperation {
624 public:
625 HVecSaturationSub(ArenaAllocator* allocator,
626 HInstruction* left,
627 HInstruction* right,
628 DataType::Type packed_type,
629 size_t vector_length,
630 uint32_t dex_pc)
631 : HVecBinaryOperation(
632 kVecSaturationSub, allocator, left, right, packed_type, vector_length, dex_pc) {
633 DCHECK(HasConsistentPackedTypes(left, packed_type));
634 DCHECK(HasConsistentPackedTypes(right, packed_type));
635 }
636
637 bool CanBeMoved() const OVERRIDE { return true; }
638
639 DECLARE_INSTRUCTION(VecSaturationSub);
640
641 protected:
642 DEFAULT_COPY_CONSTRUCTOR(VecSaturationSub);
643};
644
Aart Bikf8f5a162017-02-06 15:35:29 -0800645// Multiplies every component in the two vectors,
646// viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
647class HVecMul FINAL : public HVecBinaryOperation {
648 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100649 HVecMul(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800650 HInstruction* left,
651 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100652 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800653 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700654 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530655 : HVecBinaryOperation(kVecMul, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700656 DCHECK(HasConsistentPackedTypes(left, packed_type));
657 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800658 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700659
660 bool CanBeMoved() const OVERRIDE { return true; }
661
Aart Bikf8f5a162017-02-06 15:35:29 -0800662 DECLARE_INSTRUCTION(VecMul);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700663
Artem Serovcced8ba2017-07-19 18:18:09 +0100664 protected:
665 DEFAULT_COPY_CONSTRUCTOR(VecMul);
Aart Bikf8f5a162017-02-06 15:35:29 -0800666};
667
668// Divides every component in the two vectors,
669// viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
670class HVecDiv FINAL : public HVecBinaryOperation {
671 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100672 HVecDiv(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800673 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,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700677 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530678 : HVecBinaryOperation(kVecDiv, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700679 DCHECK(HasConsistentPackedTypes(left, packed_type));
680 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800681 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700682
683 bool CanBeMoved() const OVERRIDE { return true; }
684
Aart Bikf8f5a162017-02-06 15:35:29 -0800685 DECLARE_INSTRUCTION(VecDiv);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700686
Artem Serovcced8ba2017-07-19 18:18:09 +0100687 protected:
688 DEFAULT_COPY_CONSTRUCTOR(VecDiv);
Aart Bikf8f5a162017-02-06 15:35:29 -0800689};
690
Aart Bikf3e61ee2017-04-12 17:09:20 -0700691// Takes minimum of every component in the two vectors,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700692// viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ]
Aart Bik66c158e2018-01-31 12:55:04 -0800693// for either both signed or both unsigned operands x, y (reflected in packed_type).
Aart Bikf3e61ee2017-04-12 17:09:20 -0700694class HVecMin FINAL : public HVecBinaryOperation {
695 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100696 HVecMin(ArenaAllocator* allocator,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700697 HInstruction* left,
698 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100699 DataType::Type packed_type,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700700 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700701 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530702 : HVecBinaryOperation(kVecMin, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700703 DCHECK(HasConsistentPackedTypes(left, packed_type));
704 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf3e61ee2017-04-12 17:09:20 -0700705 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700706
Aart Bikb79f4ac2017-07-10 10:10:37 -0700707 bool CanBeMoved() const OVERRIDE { return true; }
708
Aart Bikf3e61ee2017-04-12 17:09:20 -0700709 DECLARE_INSTRUCTION(VecMin);
Aart Bikc8e93c72017-05-10 10:49:22 -0700710
Artem Serovcced8ba2017-07-19 18:18:09 +0100711 protected:
712 DEFAULT_COPY_CONSTRUCTOR(VecMin);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700713};
714
715// Takes maximum of every component in the two vectors,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700716// viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ]
Aart Bik66c158e2018-01-31 12:55:04 -0800717// for either both signed or both unsigned operands x, y (reflected in packed_type).
Aart Bikf3e61ee2017-04-12 17:09:20 -0700718class HVecMax FINAL : public HVecBinaryOperation {
719 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100720 HVecMax(ArenaAllocator* allocator,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700721 HInstruction* left,
722 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100723 DataType::Type packed_type,
Aart Bikf3e61ee2017-04-12 17:09:20 -0700724 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700725 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530726 : HVecBinaryOperation(kVecMax, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700727 DCHECK(HasConsistentPackedTypes(left, packed_type));
728 DCHECK(HasConsistentPackedTypes(right, packed_type));
Aart Bikf3e61ee2017-04-12 17:09:20 -0700729 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700730
Aart Bikb79f4ac2017-07-10 10:10:37 -0700731 bool CanBeMoved() const OVERRIDE { return true; }
732
Aart Bikf3e61ee2017-04-12 17:09:20 -0700733 DECLARE_INSTRUCTION(VecMax);
Aart Bikc8e93c72017-05-10 10:49:22 -0700734
Artem Serovcced8ba2017-07-19 18:18:09 +0100735 protected:
736 DEFAULT_COPY_CONSTRUCTOR(VecMax);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700737};
738
Aart Bikf8f5a162017-02-06 15:35:29 -0800739// Bitwise-ands every component in the two vectors,
740// viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
741class HVecAnd FINAL : public HVecBinaryOperation {
742 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100743 HVecAnd(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800744 HInstruction* left,
745 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100746 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800747 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700748 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530749 : HVecBinaryOperation(kVecAnd, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800750 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800751 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700752
753 bool CanBeMoved() const OVERRIDE { return true; }
754
Aart Bikf8f5a162017-02-06 15:35:29 -0800755 DECLARE_INSTRUCTION(VecAnd);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700756
Artem Serovcced8ba2017-07-19 18:18:09 +0100757 protected:
758 DEFAULT_COPY_CONSTRUCTOR(VecAnd);
Aart Bikf8f5a162017-02-06 15:35:29 -0800759};
760
761// Bitwise-and-nots every component in the two vectors,
762// viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
763class HVecAndNot FINAL : public HVecBinaryOperation {
764 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100765 HVecAndNot(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800766 HInstruction* left,
767 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100768 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800769 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700770 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530771 : HVecBinaryOperation(
772 kVecAndNot, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800773 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800774 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700775
776 bool CanBeMoved() const OVERRIDE { return true; }
777
Aart Bikf8f5a162017-02-06 15:35:29 -0800778 DECLARE_INSTRUCTION(VecAndNot);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700779
Artem Serovcced8ba2017-07-19 18:18:09 +0100780 protected:
781 DEFAULT_COPY_CONSTRUCTOR(VecAndNot);
Aart Bikf8f5a162017-02-06 15:35:29 -0800782};
783
784// Bitwise-ors every component in the two vectors,
785// viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
786class HVecOr FINAL : public HVecBinaryOperation {
787 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100788 HVecOr(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800789 HInstruction* left,
790 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100791 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800792 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700793 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530794 : HVecBinaryOperation(kVecOr, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800795 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800796 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700797
798 bool CanBeMoved() const OVERRIDE { return true; }
799
Aart Bikf8f5a162017-02-06 15:35:29 -0800800 DECLARE_INSTRUCTION(VecOr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700801
Artem Serovcced8ba2017-07-19 18:18:09 +0100802 protected:
803 DEFAULT_COPY_CONSTRUCTOR(VecOr);
Aart Bikf8f5a162017-02-06 15:35:29 -0800804};
805
806// Bitwise-xors every component in the two vectors,
807// viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
808class HVecXor FINAL : public HVecBinaryOperation {
809 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100810 HVecXor(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800811 HInstruction* left,
812 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100813 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800814 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700815 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530816 : HVecBinaryOperation(kVecXor, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800817 DCHECK(left->IsVecOperation() && right->IsVecOperation());
Aart Bikf8f5a162017-02-06 15:35:29 -0800818 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700819
820 bool CanBeMoved() const OVERRIDE { return true; }
821
Aart Bikf8f5a162017-02-06 15:35:29 -0800822 DECLARE_INSTRUCTION(VecXor);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700823
Artem Serovcced8ba2017-07-19 18:18:09 +0100824 protected:
825 DEFAULT_COPY_CONSTRUCTOR(VecXor);
Aart Bikf8f5a162017-02-06 15:35:29 -0800826};
827
828// Logically shifts every component in the vector left by the given distance,
829// viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
830class HVecShl FINAL : public HVecBinaryOperation {
831 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100832 HVecShl(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800833 HInstruction* left,
834 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100835 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800836 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700837 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530838 : HVecBinaryOperation(kVecShl, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700839 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800840 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700841
842 bool CanBeMoved() const OVERRIDE { return true; }
843
Aart Bikf8f5a162017-02-06 15:35:29 -0800844 DECLARE_INSTRUCTION(VecShl);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700845
Artem Serovcced8ba2017-07-19 18:18:09 +0100846 protected:
847 DEFAULT_COPY_CONSTRUCTOR(VecShl);
Aart Bikf8f5a162017-02-06 15:35:29 -0800848};
849
850// Arithmetically shifts every component in the vector right by the given distance,
851// viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
852class HVecShr FINAL : public HVecBinaryOperation {
853 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100854 HVecShr(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800855 HInstruction* left,
856 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100857 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800858 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700859 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530860 : HVecBinaryOperation(kVecShr, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700861 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800862 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700863
864 bool CanBeMoved() const OVERRIDE { return true; }
865
Aart Bikf8f5a162017-02-06 15:35:29 -0800866 DECLARE_INSTRUCTION(VecShr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700867
Artem Serovcced8ba2017-07-19 18:18:09 +0100868 protected:
869 DEFAULT_COPY_CONSTRUCTOR(VecShr);
Aart Bikf8f5a162017-02-06 15:35:29 -0800870};
871
872// Logically shifts every component in the vector right by the given distance,
873// viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
874class HVecUShr FINAL : public HVecBinaryOperation {
875 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100876 HVecUShr(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -0800877 HInstruction* left,
878 HInstruction* right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100879 DataType::Type packed_type,
Aart Bikf8f5a162017-02-06 15:35:29 -0800880 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700881 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530882 : HVecBinaryOperation(kVecUShr, allocator, left, right, packed_type, vector_length, dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -0700883 DCHECK(HasConsistentPackedTypes(left, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -0800884 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700885
886 bool CanBeMoved() const OVERRIDE { return true; }
887
Aart Bikf8f5a162017-02-06 15:35:29 -0800888 DECLARE_INSTRUCTION(VecUShr);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700889
Artem Serovcced8ba2017-07-19 18:18:09 +0100890 protected:
891 DEFAULT_COPY_CONSTRUCTOR(VecUShr);
Aart Bikf8f5a162017-02-06 15:35:29 -0800892};
893
Aart Bik8de59162017-04-21 09:42:01 -0700894//
895// Definitions of concrete miscellaneous vector operations in HIR.
896//
897
898// Assigns the given scalar elements to a vector,
Aart Bikdbbac8f2017-09-01 13:06:08 -0700899// viz. set( array(x1, .. , xn) ) = [ x1, .. , xn ] if n == m,
900// set( array(x1, .. , xm) ) = [ x1, .. , xm, 0, .. , 0 ] if m < n.
Aart Bik8de59162017-04-21 09:42:01 -0700901class HVecSetScalars FINAL : public HVecOperation {
Aart Bik0148de42017-09-05 09:25:01 -0700902 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100903 HVecSetScalars(ArenaAllocator* allocator,
Aart Bik5e3afa92017-09-20 14:11:11 -0700904 HInstruction* scalars[],
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100905 DataType::Type packed_type,
Aart Bik8de59162017-04-21 09:42:01 -0700906 size_t vector_length,
Aart Bik0148de42017-09-05 09:25:01 -0700907 size_t number_of_scalars,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700908 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530909 : HVecOperation(kVecSetScalars,
910 allocator,
Aart Bik8de59162017-04-21 09:42:01 -0700911 packed_type,
912 SideEffects::None(),
Aart Bik0148de42017-09-05 09:25:01 -0700913 number_of_scalars,
Aart Bik8de59162017-04-21 09:42:01 -0700914 vector_length,
915 dex_pc) {
Aart Bik0148de42017-09-05 09:25:01 -0700916 for (size_t i = 0; i < number_of_scalars; i++) {
Aart Bik2dd7b672017-12-07 11:11:22 -0800917 DCHECK(!ReturnsSIMDValue(scalars[i]));
Aart Bik8de59162017-04-21 09:42:01 -0700918 SetRawInputAt(0, scalars[i]);
919 }
920 }
Aart Bikb79f4ac2017-07-10 10:10:37 -0700921
922 // Setting scalars needs to stay in place, since SIMD registers are not
923 // kept alive across vector loop boundaries (yet).
924 bool CanBeMoved() const OVERRIDE { return false; }
925
Aart Bik8de59162017-04-21 09:42:01 -0700926 DECLARE_INSTRUCTION(VecSetScalars);
Aart Bikb79f4ac2017-07-10 10:10:37 -0700927
Artem Serovcced8ba2017-07-19 18:18:09 +0100928 protected:
929 DEFAULT_COPY_CONSTRUCTOR(VecSetScalars);
Aart Bik8de59162017-04-21 09:42:01 -0700930};
931
Aart Bikdbbac8f2017-09-01 13:06:08 -0700932// Multiplies every component in the two vectors, adds the result vector to the accumulator vector,
933// viz. [ a1, .. , an ] + [ x1, .. , xn ] * [ y1, .. , yn ] = [ a1 + x1 * y1, .. , an + xn * yn ].
Artem Serovf34dd202017-04-10 17:41:46 +0100934class HVecMultiplyAccumulate FINAL : public HVecOperation {
935 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100936 HVecMultiplyAccumulate(ArenaAllocator* allocator,
Artem Serovf34dd202017-04-10 17:41:46 +0100937 InstructionKind op,
938 HInstruction* accumulator,
939 HInstruction* mul_left,
940 HInstruction* mul_right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100941 DataType::Type packed_type,
Artem Serovf34dd202017-04-10 17:41:46 +0100942 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700943 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530944 : HVecOperation(kVecMultiplyAccumulate,
945 allocator,
Artem Serovf34dd202017-04-10 17:41:46 +0100946 packed_type,
947 SideEffects::None(),
Aart Bik8de59162017-04-21 09:42:01 -0700948 /* number_of_inputs */ 3,
Artem Serovf34dd202017-04-10 17:41:46 +0100949 vector_length,
950 dex_pc),
951 op_kind_(op) {
952 DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
Aart Bikd58bc322017-05-01 14:49:18 -0700953 DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
954 DCHECK(HasConsistentPackedTypes(mul_left, packed_type));
955 DCHECK(HasConsistentPackedTypes(mul_right, packed_type));
Aart Bikdbbac8f2017-09-01 13:06:08 -0700956 SetRawInputAt(0, accumulator);
957 SetRawInputAt(1, mul_left);
958 SetRawInputAt(2, mul_right);
Artem Serovf34dd202017-04-10 17:41:46 +0100959 }
960
Nicolas Geoffray9858bf72017-07-08 12:34:55 +0000961 bool CanBeMoved() const OVERRIDE { return true; }
962
Artem Serovf34dd202017-04-10 17:41:46 +0100963 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
Aart Bikb79f4ac2017-07-10 10:10:37 -0700964 DCHECK(other->IsVecMultiplyAccumulate());
965 const HVecMultiplyAccumulate* o = other->AsVecMultiplyAccumulate();
966 return HVecOperation::InstructionDataEquals(o) && GetOpKind() == o->GetOpKind();
Artem Serovf34dd202017-04-10 17:41:46 +0100967 }
968
969 InstructionKind GetOpKind() const { return op_kind_; }
970
971 DECLARE_INSTRUCTION(VecMultiplyAccumulate);
972
Artem Serovcced8ba2017-07-19 18:18:09 +0100973 protected:
974 DEFAULT_COPY_CONSTRUCTOR(VecMultiplyAccumulate);
975
Artem Serovf34dd202017-04-10 17:41:46 +0100976 private:
977 // Indicates if this is a MADD or MSUB.
978 const InstructionKind op_kind_;
Artem Serovf34dd202017-04-10 17:41:46 +0100979};
980
Aart Bikdbbac8f2017-09-01 13:06:08 -0700981// Takes the absolute difference of two vectors, and adds the results to
982// same-precision or wider-precision components in the accumulator,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700983// viz. SAD([ a1, .. , am ], [ x1, .. , xn ], [ y1, .. , yn ]) =
Aart Bikdbbac8f2017-09-01 13:06:08 -0700984// [ a1 + sum abs(xi-yi), .. , am + sum abs(xj-yj) ],
Aart Bik46b6dbc2017-10-03 11:37:37 -0700985// for m <= n, non-overlapping sums, and signed operands x, y.
Aart Bikdbbac8f2017-09-01 13:06:08 -0700986class HVecSADAccumulate FINAL : public HVecOperation {
987 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100988 HVecSADAccumulate(ArenaAllocator* allocator,
Aart Bikdbbac8f2017-09-01 13:06:08 -0700989 HInstruction* accumulator,
990 HInstruction* sad_left,
991 HInstruction* sad_right,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100992 DataType::Type packed_type,
Aart Bikdbbac8f2017-09-01 13:06:08 -0700993 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -0700994 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +0530995 : HVecOperation(kVecSADAccumulate,
996 allocator,
Aart Bikdbbac8f2017-09-01 13:06:08 -0700997 packed_type,
998 SideEffects::None(),
999 /* number_of_inputs */ 3,
1000 vector_length,
1001 dex_pc) {
1002 DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
1003 DCHECK(sad_left->IsVecOperation());
1004 DCHECK(sad_right->IsVecOperation());
Vladimir Marko61b92282017-10-11 13:23:17 +01001005 DCHECK_EQ(ToSignedType(sad_left->AsVecOperation()->GetPackedType()),
1006 ToSignedType(sad_right->AsVecOperation()->GetPackedType()));
Aart Bikdbbac8f2017-09-01 13:06:08 -07001007 SetRawInputAt(0, accumulator);
1008 SetRawInputAt(1, sad_left);
1009 SetRawInputAt(2, sad_right);
1010 }
1011
1012 DECLARE_INSTRUCTION(VecSADAccumulate);
1013
Artem Serovcced8ba2017-07-19 18:18:09 +01001014 protected:
1015 DEFAULT_COPY_CONSTRUCTOR(VecSADAccumulate);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001016};
1017
Aart Bikf8f5a162017-02-06 15:35:29 -08001018// Loads a vector from memory, viz. load(mem, 1)
1019// yield the vector [ mem(1), .. , mem(n) ].
1020class HVecLoad FINAL : public HVecMemoryOperation {
1021 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001022 HVecLoad(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001023 HInstruction* base,
1024 HInstruction* index,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001025 DataType::Type packed_type,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001026 SideEffects side_effects,
Aart Bikf8f5a162017-02-06 15:35:29 -08001027 size_t vector_length,
Aart Bikdb14fcf2017-04-25 15:53:58 -07001028 bool is_string_char_at,
Aart Bik46b6dbc2017-10-03 11:37:37 -07001029 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +05301030 : HVecMemoryOperation(kVecLoad,
1031 allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001032 packed_type,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001033 side_effects,
Aart Bik8de59162017-04-21 09:42:01 -07001034 /* number_of_inputs */ 2,
Aart Bikf8f5a162017-02-06 15:35:29 -08001035 vector_length,
1036 dex_pc) {
1037 SetRawInputAt(0, base);
1038 SetRawInputAt(1, index);
Aart Bikdb14fcf2017-04-25 15:53:58 -07001039 SetPackedFlag<kFieldIsStringCharAt>(is_string_char_at);
Aart Bikf8f5a162017-02-06 15:35:29 -08001040 }
Aart Bikdb14fcf2017-04-25 15:53:58 -07001041
1042 bool IsStringCharAt() const { return GetPackedFlag<kFieldIsStringCharAt>(); }
1043
Aart Bikb79f4ac2017-07-10 10:10:37 -07001044 bool CanBeMoved() const OVERRIDE { return true; }
1045
1046 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
1047 DCHECK(other->IsVecLoad());
1048 const HVecLoad* o = other->AsVecLoad();
1049 return HVecMemoryOperation::InstructionDataEquals(o) && IsStringCharAt() == o->IsStringCharAt();
1050 }
1051
1052 DECLARE_INSTRUCTION(VecLoad);
1053
Artem Serovcced8ba2017-07-19 18:18:09 +01001054 protected:
1055 DEFAULT_COPY_CONSTRUCTOR(VecLoad);
1056
Aart Bikf8f5a162017-02-06 15:35:29 -08001057 private:
Aart Bikdb14fcf2017-04-25 15:53:58 -07001058 // Additional packed bits.
1059 static constexpr size_t kFieldIsStringCharAt = HVecOperation::kNumberOfVectorOpPackedBits;
1060 static constexpr size_t kNumberOfVecLoadPackedBits = kFieldIsStringCharAt + 1;
1061 static_assert(kNumberOfVecLoadPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
Aart Bikf8f5a162017-02-06 15:35:29 -08001062};
1063
1064// Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
1065// sets mem(1) = x1, .. , mem(n) = xn.
1066class HVecStore FINAL : public HVecMemoryOperation {
1067 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001068 HVecStore(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001069 HInstruction* base,
1070 HInstruction* index,
1071 HInstruction* value,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001072 DataType::Type packed_type,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001073 SideEffects side_effects,
Aart Bikf8f5a162017-02-06 15:35:29 -08001074 size_t vector_length,
Aart Bik46b6dbc2017-10-03 11:37:37 -07001075 uint32_t dex_pc)
Gupta Kumar, Sanjivd9e4d732018-02-05 13:35:03 +05301076 : HVecMemoryOperation(kVecStore,
1077 allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001078 packed_type,
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001079 side_effects,
Aart Bik8de59162017-04-21 09:42:01 -07001080 /* number_of_inputs */ 3,
Aart Bikf8f5a162017-02-06 15:35:29 -08001081 vector_length,
1082 dex_pc) {
Aart Bikd58bc322017-05-01 14:49:18 -07001083 DCHECK(HasConsistentPackedTypes(value, packed_type));
Aart Bikf8f5a162017-02-06 15:35:29 -08001084 SetRawInputAt(0, base);
1085 SetRawInputAt(1, index);
1086 SetRawInputAt(2, value);
1087 }
Aart Bikb79f4ac2017-07-10 10:10:37 -07001088
1089 // A store needs to stay in place.
1090 bool CanBeMoved() const OVERRIDE { return false; }
1091
Aart Bikf8f5a162017-02-06 15:35:29 -08001092 DECLARE_INSTRUCTION(VecStore);
Aart Bikb79f4ac2017-07-10 10:10:37 -07001093
Artem Serovcced8ba2017-07-19 18:18:09 +01001094 protected:
1095 DEFAULT_COPY_CONSTRUCTOR(VecStore)
Aart Bikf8f5a162017-02-06 15:35:29 -08001096};
1097
1098} // namespace art
1099
1100#endif // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_