xref: /aosp_15_r20/art/compiler/optimizing/nodes_vector.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker // This #include should never be used by compilation, because this header file (nodes_vector.h)
21*795d594fSAndroid Build Coastguard Worker // is included in the header file nodes.h itself. However it gives editing tools better context.
22*795d594fSAndroid Build Coastguard Worker #include "nodes.h"
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker // Memory alignment, represented as an offset relative to a base, where 0 <= offset < base,
27*795d594fSAndroid Build Coastguard Worker // and base is a power of two. For example, the value Alignment(16, 0) means memory is
28*795d594fSAndroid Build Coastguard Worker // perfectly aligned at a 16-byte boundary, whereas the value Alignment(16, 4) means
29*795d594fSAndroid Build Coastguard Worker // memory is always exactly 4 bytes above such a boundary.
30*795d594fSAndroid Build Coastguard Worker class Alignment {
31*795d594fSAndroid Build Coastguard Worker  public:
Alignment(size_t base,size_t offset)32*795d594fSAndroid Build Coastguard Worker   Alignment(size_t base, size_t offset) : base_(base), offset_(offset) {
33*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(offset, base);
34*795d594fSAndroid Build Coastguard Worker     DCHECK(IsPowerOfTwo(base));
35*795d594fSAndroid Build Coastguard Worker   }
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker   // Returns true if memory is at least aligned at the given boundary.
38*795d594fSAndroid Build Coastguard Worker   // Assumes requested base is power of two.
IsAlignedAt(size_t base)39*795d594fSAndroid Build Coastguard Worker   bool IsAlignedAt(size_t base) const {
40*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(0u, base);
41*795d594fSAndroid Build Coastguard Worker     DCHECK(IsPowerOfTwo(base));
42*795d594fSAndroid Build Coastguard Worker     return ((offset_ | base_) & (base - 1u)) == 0;
43*795d594fSAndroid Build Coastguard Worker   }
44*795d594fSAndroid Build Coastguard Worker 
Base()45*795d594fSAndroid Build Coastguard Worker   size_t Base() const { return base_; }
46*795d594fSAndroid Build Coastguard Worker 
Offset()47*795d594fSAndroid Build Coastguard Worker   size_t Offset() const { return offset_; }
48*795d594fSAndroid Build Coastguard Worker 
ToString()49*795d594fSAndroid Build Coastguard Worker   std::string ToString() const {
50*795d594fSAndroid Build Coastguard Worker     return "ALIGN(" + std::to_string(base_) + "," + std::to_string(offset_) + ")";
51*795d594fSAndroid Build Coastguard Worker   }
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker   bool operator==(const Alignment& other) const {
54*795d594fSAndroid Build Coastguard Worker     return base_ == other.base_ && offset_ == other.offset_;
55*795d594fSAndroid Build Coastguard Worker   }
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker  private:
58*795d594fSAndroid Build Coastguard Worker   size_t base_;
59*795d594fSAndroid Build Coastguard Worker   size_t offset_;
60*795d594fSAndroid Build Coastguard Worker };
61*795d594fSAndroid Build Coastguard Worker 
62*795d594fSAndroid Build Coastguard Worker //
63*795d594fSAndroid Build Coastguard Worker // Definitions of abstract vector operations in HIR.
64*795d594fSAndroid Build Coastguard Worker //
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker // Abstraction of a vector operation, i.e., an operation that performs
67*795d594fSAndroid Build Coastguard Worker // GetVectorLength() x GetPackedType() operations simultaneously.
68*795d594fSAndroid Build Coastguard Worker class HVecOperation : public HVariableInputSizeInstruction {
69*795d594fSAndroid Build Coastguard Worker  public:
70*795d594fSAndroid Build Coastguard Worker   // A SIMD operation looks like a FPU location.
71*795d594fSAndroid Build Coastguard Worker   // TODO: we could introduce SIMD types in HIR.
72*795d594fSAndroid Build Coastguard Worker   static constexpr DataType::Type kSIMDType = DataType::Type::kFloat64;
73*795d594fSAndroid Build Coastguard Worker 
HVecOperation(InstructionKind kind,ArenaAllocator * allocator,DataType::Type packed_type,SideEffects side_effects,size_t number_of_inputs,size_t vector_length,uint32_t dex_pc)74*795d594fSAndroid Build Coastguard Worker   HVecOperation(InstructionKind kind,
75*795d594fSAndroid Build Coastguard Worker                 ArenaAllocator* allocator,
76*795d594fSAndroid Build Coastguard Worker                 DataType::Type packed_type,
77*795d594fSAndroid Build Coastguard Worker                 SideEffects side_effects,
78*795d594fSAndroid Build Coastguard Worker                 size_t number_of_inputs,
79*795d594fSAndroid Build Coastguard Worker                 size_t vector_length,
80*795d594fSAndroid Build Coastguard Worker                 uint32_t dex_pc)
81*795d594fSAndroid Build Coastguard Worker       : HVariableInputSizeInstruction(kind,
82*795d594fSAndroid Build Coastguard Worker                                       kSIMDType,
83*795d594fSAndroid Build Coastguard Worker                                       side_effects,
84*795d594fSAndroid Build Coastguard Worker                                       dex_pc,
85*795d594fSAndroid Build Coastguard Worker                                       allocator,
86*795d594fSAndroid Build Coastguard Worker                                       number_of_inputs,
87*795d594fSAndroid Build Coastguard Worker                                       kArenaAllocVectorNode),
88*795d594fSAndroid Build Coastguard Worker         vector_length_(vector_length) {
89*795d594fSAndroid Build Coastguard Worker     SetPackedField<PackedTypeField>(packed_type);
90*795d594fSAndroid Build Coastguard Worker     // By default vector operations are not predicated.
91*795d594fSAndroid Build Coastguard Worker     SetPackedField<PredicationKindField>(PredicationKind::kNotPredicated);
92*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(1u, vector_length);
93*795d594fSAndroid Build Coastguard Worker   }
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker   // Predicated instructions execute a corresponding operation only on vector elements which are
96*795d594fSAndroid Build Coastguard Worker   // active (governing predicate is true for that element); the following modes determine what
97*795d594fSAndroid Build Coastguard Worker   // is happening with inactive elements.
98*795d594fSAndroid Build Coastguard Worker   //
99*795d594fSAndroid Build Coastguard Worker   // See HVecPredSetOperation.
100*795d594fSAndroid Build Coastguard Worker   enum class PredicationKind {
101*795d594fSAndroid Build Coastguard Worker     kNotPredicated,        // Instruction doesn't take any predicate as an input.
102*795d594fSAndroid Build Coastguard Worker     kZeroingForm,          // Inactive elements are reset to zero.
103*795d594fSAndroid Build Coastguard Worker     kMergingForm,          // Inactive elements keep their value.
104*795d594fSAndroid Build Coastguard Worker     kLast = kMergingForm,
105*795d594fSAndroid Build Coastguard Worker   };
106*795d594fSAndroid Build Coastguard Worker 
GetPredicationKind()107*795d594fSAndroid Build Coastguard Worker   PredicationKind GetPredicationKind() const { return GetPackedField<PredicationKindField>(); }
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker   // Returns whether the vector operation must be predicated in predicated SIMD mode
110*795d594fSAndroid Build Coastguard Worker   // (see CodeGenerator::SupportsPredicatedSIMD). The method reflects semantics of
111*795d594fSAndroid Build Coastguard Worker   // the instruction class rather than the state of a particular instruction instance.
112*795d594fSAndroid Build Coastguard Worker   //
113*795d594fSAndroid Build Coastguard Worker   // This property is introduced for robustness purpose - to maintain and check the invariant:
114*795d594fSAndroid Build Coastguard Worker   // all instructions of the same vector operation class must be either all predicated or all
115*795d594fSAndroid Build Coastguard Worker   // not predicated (depending on the predicated SIMD support) in a correct graph.
MustBePredicatedInPredicatedSIMDMode()116*795d594fSAndroid Build Coastguard Worker   virtual bool MustBePredicatedInPredicatedSIMDMode() {
117*795d594fSAndroid Build Coastguard Worker     return true;
118*795d594fSAndroid Build Coastguard Worker   }
119*795d594fSAndroid Build Coastguard Worker 
IsPredicated()120*795d594fSAndroid Build Coastguard Worker   bool IsPredicated() const {
121*795d594fSAndroid Build Coastguard Worker     return GetPredicationKind() != PredicationKind::kNotPredicated;
122*795d594fSAndroid Build Coastguard Worker   }
123*795d594fSAndroid Build Coastguard Worker 
124*795d594fSAndroid Build Coastguard Worker   // See HVecPredSetOperation.
SetGoverningPredicate(HInstruction * input,PredicationKind pred_kind)125*795d594fSAndroid Build Coastguard Worker   void SetGoverningPredicate(HInstruction* input, PredicationKind pred_kind) {
126*795d594fSAndroid Build Coastguard Worker     DCHECK(!IsPredicated());
127*795d594fSAndroid Build Coastguard Worker     DCHECK(input->IsVecPredSetOperation());
128*795d594fSAndroid Build Coastguard Worker     AddInput(input);
129*795d594fSAndroid Build Coastguard Worker     SetPackedField<PredicationKindField>(pred_kind);
130*795d594fSAndroid Build Coastguard Worker     DCHECK(IsPredicated());
131*795d594fSAndroid Build Coastguard Worker   }
132*795d594fSAndroid Build Coastguard Worker 
SetMergingGoverningPredicate(HInstruction * input)133*795d594fSAndroid Build Coastguard Worker   void SetMergingGoverningPredicate(HInstruction* input) {
134*795d594fSAndroid Build Coastguard Worker     SetGoverningPredicate(input, PredicationKind::kMergingForm);
135*795d594fSAndroid Build Coastguard Worker   }
SetZeroingGoverningPredicate(HInstruction * input)136*795d594fSAndroid Build Coastguard Worker   void SetZeroingGoverningPredicate(HInstruction* input) {
137*795d594fSAndroid Build Coastguard Worker     SetGoverningPredicate(input, PredicationKind::kZeroingForm);
138*795d594fSAndroid Build Coastguard Worker   }
139*795d594fSAndroid Build Coastguard Worker 
140*795d594fSAndroid Build Coastguard Worker   // See HVecPredSetOperation.
GetGoverningPredicate()141*795d594fSAndroid Build Coastguard Worker   HVecPredSetOperation* GetGoverningPredicate() const {
142*795d594fSAndroid Build Coastguard Worker     DCHECK(IsPredicated());
143*795d594fSAndroid Build Coastguard Worker     HInstruction* pred_input = InputAt(InputCount() - 1);
144*795d594fSAndroid Build Coastguard Worker     DCHECK(pred_input->IsVecPredSetOperation());
145*795d594fSAndroid Build Coastguard Worker     return pred_input->AsVecPredSetOperation();
146*795d594fSAndroid Build Coastguard Worker   }
147*795d594fSAndroid Build Coastguard Worker 
148*795d594fSAndroid Build Coastguard Worker   // Returns whether two vector operations are predicated by the same vector predicate
149*795d594fSAndroid Build Coastguard Worker   // with the same predication type.
HaveSamePredicate(HVecOperation * instr0,HVecOperation * instr1)150*795d594fSAndroid Build Coastguard Worker   static bool HaveSamePredicate(HVecOperation* instr0, HVecOperation* instr1) {
151*795d594fSAndroid Build Coastguard Worker     HVecPredSetOperation* instr0_predicate = instr0->GetGoverningPredicate();
152*795d594fSAndroid Build Coastguard Worker     HVecOperation::PredicationKind instr0_predicate_kind = instr0->GetPredicationKind();
153*795d594fSAndroid Build Coastguard Worker     return instr1->GetGoverningPredicate() == instr0_predicate &&
154*795d594fSAndroid Build Coastguard Worker            instr1->GetPredicationKind() == instr0_predicate_kind;
155*795d594fSAndroid Build Coastguard Worker   }
156*795d594fSAndroid Build Coastguard Worker 
157*795d594fSAndroid Build Coastguard Worker   // Returns the number of elements packed in a vector.
GetVectorLength()158*795d594fSAndroid Build Coastguard Worker   size_t GetVectorLength() const {
159*795d594fSAndroid Build Coastguard Worker     return vector_length_;
160*795d594fSAndroid Build Coastguard Worker   }
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker   // Returns the number of bytes in a full vector.
GetVectorNumberOfBytes()163*795d594fSAndroid Build Coastguard Worker   size_t GetVectorNumberOfBytes() const {
164*795d594fSAndroid Build Coastguard Worker     return vector_length_ * DataType::Size(GetPackedType());
165*795d594fSAndroid Build Coastguard Worker   }
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker   // Returns the true component type packed in a vector.
GetPackedType()168*795d594fSAndroid Build Coastguard Worker   DataType::Type GetPackedType() const {
169*795d594fSAndroid Build Coastguard Worker     return GetPackedField<PackedTypeField>();
170*795d594fSAndroid Build Coastguard Worker   }
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker   // Assumes vector nodes cannot be moved by default. Each concrete implementation
173*795d594fSAndroid Build Coastguard Worker   // that can be moved should override this method and return true.
174*795d594fSAndroid Build Coastguard Worker   //
175*795d594fSAndroid Build Coastguard Worker   // Note: similar approach is used for instruction scheduling (if it is turned on for the target):
176*795d594fSAndroid Build Coastguard Worker   // by default HScheduler::IsSchedulable returns false for a particular HVecOperation.
177*795d594fSAndroid Build Coastguard Worker   // HScheduler${ARCH}::IsSchedulable can be overridden to return true for an instruction (see
178*795d594fSAndroid Build Coastguard Worker   // scheduler_arm64.h for example) if it is safe to schedule it; in this case one *must* also
179*795d594fSAndroid Build Coastguard Worker   // look at/update HScheduler${ARCH}::IsSchedulingBarrier for this instruction.
180*795d594fSAndroid Build Coastguard Worker   //
181*795d594fSAndroid Build Coastguard Worker   // Note: For newly introduced vector instructions HScheduler${ARCH}::IsSchedulingBarrier must be
182*795d594fSAndroid Build Coastguard Worker   // altered to return true if the instruction might reside outside the SIMD loop body since SIMD
183*795d594fSAndroid Build Coastguard Worker   // registers are not kept alive across vector loop boundaries (yet).
CanBeMoved()184*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return false; }
185*795d594fSAndroid Build Coastguard Worker 
186*795d594fSAndroid Build Coastguard Worker   // Tests if all data of a vector node (vector length and packed type) is equal.
187*795d594fSAndroid Build Coastguard Worker   // Each concrete implementation that adds more fields should test equality of
188*795d594fSAndroid Build Coastguard Worker   // those fields in its own method *and* call all super methods.
InstructionDataEquals(const HInstruction * other)189*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
190*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsVecOperation());
191*795d594fSAndroid Build Coastguard Worker     const HVecOperation* o = other->AsVecOperation();
192*795d594fSAndroid Build Coastguard Worker     return GetVectorLength() == o->GetVectorLength() && GetPackedType() == o->GetPackedType();
193*795d594fSAndroid Build Coastguard Worker   }
194*795d594fSAndroid Build Coastguard Worker 
195*795d594fSAndroid Build Coastguard Worker   // Maps an integral type to the same-size signed type and leaves other types alone.
ToSignedType(DataType::Type type)196*795d594fSAndroid Build Coastguard Worker   static DataType::Type ToSignedType(DataType::Type type) {
197*795d594fSAndroid Build Coastguard Worker     switch (type) {
198*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kBool:  // 1-byte storage unit
199*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kUint8:
200*795d594fSAndroid Build Coastguard Worker         return DataType::Type::kInt8;
201*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kUint16:
202*795d594fSAndroid Build Coastguard Worker         return DataType::Type::kInt16;
203*795d594fSAndroid Build Coastguard Worker       default:
204*795d594fSAndroid Build Coastguard Worker         DCHECK(type != DataType::Type::kVoid && type != DataType::Type::kReference) << type;
205*795d594fSAndroid Build Coastguard Worker         return type;
206*795d594fSAndroid Build Coastguard Worker     }
207*795d594fSAndroid Build Coastguard Worker   }
208*795d594fSAndroid Build Coastguard Worker 
209*795d594fSAndroid Build Coastguard Worker   // Maps an integral type to the same-size unsigned type and leaves other types alone.
ToUnsignedType(DataType::Type type)210*795d594fSAndroid Build Coastguard Worker   static DataType::Type ToUnsignedType(DataType::Type type) {
211*795d594fSAndroid Build Coastguard Worker     switch (type) {
212*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kBool:  // 1-byte storage unit
213*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kInt8:
214*795d594fSAndroid Build Coastguard Worker         return DataType::Type::kUint8;
215*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kInt16:
216*795d594fSAndroid Build Coastguard Worker         return DataType::Type::kUint16;
217*795d594fSAndroid Build Coastguard Worker       default:
218*795d594fSAndroid Build Coastguard Worker         DCHECK(type != DataType::Type::kVoid && type != DataType::Type::kReference) << type;
219*795d594fSAndroid Build Coastguard Worker         return type;
220*795d594fSAndroid Build Coastguard Worker     }
221*795d594fSAndroid Build Coastguard Worker   }
222*795d594fSAndroid Build Coastguard Worker 
223*795d594fSAndroid Build Coastguard Worker   // Maps an integral type to the same-size (un)signed type. Leaves other types alone.
ToProperType(DataType::Type type,bool is_unsigned)224*795d594fSAndroid Build Coastguard Worker   static DataType::Type ToProperType(DataType::Type type, bool is_unsigned) {
225*795d594fSAndroid Build Coastguard Worker     return is_unsigned ? ToUnsignedType(type) : ToSignedType(type);
226*795d594fSAndroid Build Coastguard Worker   }
227*795d594fSAndroid Build Coastguard Worker 
228*795d594fSAndroid Build Coastguard Worker   // Helper method to determine if an instruction returns a SIMD value.
229*795d594fSAndroid Build Coastguard Worker   // TODO: This method is needed until we introduce SIMD as proper type.
ReturnsSIMDValue(HInstruction * instruction)230*795d594fSAndroid Build Coastguard Worker   static bool ReturnsSIMDValue(HInstruction* instruction) {
231*795d594fSAndroid Build Coastguard Worker     if (instruction->IsVecOperation()) {
232*795d594fSAndroid Build Coastguard Worker       return !instruction->IsVecExtractScalar();  // only scalar returning vec op
233*795d594fSAndroid Build Coastguard Worker     } else if (instruction->IsPhi()) {
234*795d594fSAndroid Build Coastguard Worker       // Vectorizer only uses Phis in reductions, so checking for a 2-way phi
235*795d594fSAndroid Build Coastguard Worker       // with a direct vector operand as second argument suffices.
236*795d594fSAndroid Build Coastguard Worker       return
237*795d594fSAndroid Build Coastguard Worker           instruction->GetType() == kSIMDType &&
238*795d594fSAndroid Build Coastguard Worker           instruction->InputCount() == 2 &&
239*795d594fSAndroid Build Coastguard Worker           instruction->InputAt(1)->IsVecOperation();
240*795d594fSAndroid Build Coastguard Worker     }
241*795d594fSAndroid Build Coastguard Worker     return false;
242*795d594fSAndroid Build Coastguard Worker   }
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(VecOperation);
245*795d594fSAndroid Build Coastguard Worker 
246*795d594fSAndroid Build Coastguard Worker  protected:
247*795d594fSAndroid Build Coastguard Worker   // Additional packed bits.
248*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kPredicationKind = HInstruction::kNumberOfGenericPackedBits;
249*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kPredicationKindSize =
250*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(PredicationKind::kLast));
251*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldPackedType = kPredicationKind + kPredicationKindSize;
252*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldPackedTypeSize =
253*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
254*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfVectorOpPackedBits = kFieldPackedType + kFieldPackedTypeSize;
255*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfVectorOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
256*795d594fSAndroid Build Coastguard Worker   using PackedTypeField = BitField<DataType::Type, kFieldPackedType, kFieldPackedTypeSize>;
257*795d594fSAndroid Build Coastguard Worker   using PredicationKindField = BitField<PredicationKind, kPredicationKind, kPredicationKindSize>;
258*795d594fSAndroid Build Coastguard Worker 
259*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecOperation);
260*795d594fSAndroid Build Coastguard Worker 
261*795d594fSAndroid Build Coastguard Worker  private:
262*795d594fSAndroid Build Coastguard Worker   const size_t vector_length_;
263*795d594fSAndroid Build Coastguard Worker };
264*795d594fSAndroid Build Coastguard Worker 
265*795d594fSAndroid Build Coastguard Worker // Abstraction of a unary vector operation.
266*795d594fSAndroid Build Coastguard Worker class HVecUnaryOperation : public HVecOperation {
267*795d594fSAndroid Build Coastguard Worker  public:
HVecUnaryOperation(InstructionKind kind,ArenaAllocator * allocator,HInstruction * input,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)268*795d594fSAndroid Build Coastguard Worker   HVecUnaryOperation(InstructionKind kind,
269*795d594fSAndroid Build Coastguard Worker                      ArenaAllocator* allocator,
270*795d594fSAndroid Build Coastguard Worker                      HInstruction* input,
271*795d594fSAndroid Build Coastguard Worker                      DataType::Type packed_type,
272*795d594fSAndroid Build Coastguard Worker                      size_t vector_length,
273*795d594fSAndroid Build Coastguard Worker                      uint32_t dex_pc)
274*795d594fSAndroid Build Coastguard Worker       : HVecOperation(kind,
275*795d594fSAndroid Build Coastguard Worker                       allocator,
276*795d594fSAndroid Build Coastguard Worker                       packed_type,
277*795d594fSAndroid Build Coastguard Worker                       SideEffects::None(),
278*795d594fSAndroid Build Coastguard Worker                       /* number_of_inputs= */ 1,
279*795d594fSAndroid Build Coastguard Worker                       vector_length,
280*795d594fSAndroid Build Coastguard Worker                       dex_pc) {
281*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, input);
282*795d594fSAndroid Build Coastguard Worker   }
283*795d594fSAndroid Build Coastguard Worker 
GetInput()284*795d594fSAndroid Build Coastguard Worker   HInstruction* GetInput() const { return InputAt(0); }
285*795d594fSAndroid Build Coastguard Worker 
286*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation);
287*795d594fSAndroid Build Coastguard Worker 
288*795d594fSAndroid Build Coastguard Worker  protected:
289*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecUnaryOperation);
290*795d594fSAndroid Build Coastguard Worker };
291*795d594fSAndroid Build Coastguard Worker 
292*795d594fSAndroid Build Coastguard Worker // Abstraction of a binary vector operation.
293*795d594fSAndroid Build Coastguard Worker class HVecBinaryOperation : public HVecOperation {
294*795d594fSAndroid Build Coastguard Worker  public:
HVecBinaryOperation(InstructionKind kind,ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)295*795d594fSAndroid Build Coastguard Worker   HVecBinaryOperation(InstructionKind kind,
296*795d594fSAndroid Build Coastguard Worker                       ArenaAllocator* allocator,
297*795d594fSAndroid Build Coastguard Worker                       HInstruction* left,
298*795d594fSAndroid Build Coastguard Worker                       HInstruction* right,
299*795d594fSAndroid Build Coastguard Worker                       DataType::Type packed_type,
300*795d594fSAndroid Build Coastguard Worker                       size_t vector_length,
301*795d594fSAndroid Build Coastguard Worker                       uint32_t dex_pc)
302*795d594fSAndroid Build Coastguard Worker       : HVecOperation(kind,
303*795d594fSAndroid Build Coastguard Worker                       allocator,
304*795d594fSAndroid Build Coastguard Worker                       packed_type,
305*795d594fSAndroid Build Coastguard Worker                       SideEffects::None(),
306*795d594fSAndroid Build Coastguard Worker                       /* number_of_inputs= */ 2,
307*795d594fSAndroid Build Coastguard Worker                       vector_length,
308*795d594fSAndroid Build Coastguard Worker                       dex_pc) {
309*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, left);
310*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, right);
311*795d594fSAndroid Build Coastguard Worker   }
312*795d594fSAndroid Build Coastguard Worker 
GetLeft()313*795d594fSAndroid Build Coastguard Worker   HInstruction* GetLeft() const { return InputAt(0); }
GetRight()314*795d594fSAndroid Build Coastguard Worker   HInstruction* GetRight() const { return InputAt(1); }
315*795d594fSAndroid Build Coastguard Worker 
316*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
317*795d594fSAndroid Build Coastguard Worker 
318*795d594fSAndroid Build Coastguard Worker  protected:
319*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecBinaryOperation);
320*795d594fSAndroid Build Coastguard Worker };
321*795d594fSAndroid Build Coastguard Worker 
322*795d594fSAndroid Build Coastguard Worker // Abstraction of a vector operation that references memory, with an alignment.
323*795d594fSAndroid Build Coastguard Worker // The Android runtime guarantees elements have at least natural alignment.
324*795d594fSAndroid Build Coastguard Worker class HVecMemoryOperation : public HVecOperation {
325*795d594fSAndroid Build Coastguard Worker  public:
HVecMemoryOperation(InstructionKind kind,ArenaAllocator * allocator,DataType::Type packed_type,SideEffects side_effects,size_t number_of_inputs,size_t vector_length,uint32_t dex_pc)326*795d594fSAndroid Build Coastguard Worker   HVecMemoryOperation(InstructionKind kind,
327*795d594fSAndroid Build Coastguard Worker                       ArenaAllocator* allocator,
328*795d594fSAndroid Build Coastguard Worker                       DataType::Type packed_type,
329*795d594fSAndroid Build Coastguard Worker                       SideEffects side_effects,
330*795d594fSAndroid Build Coastguard Worker                       size_t number_of_inputs,
331*795d594fSAndroid Build Coastguard Worker                       size_t vector_length,
332*795d594fSAndroid Build Coastguard Worker                       uint32_t dex_pc)
333*795d594fSAndroid Build Coastguard Worker       : HVecOperation(kind,
334*795d594fSAndroid Build Coastguard Worker                       allocator,
335*795d594fSAndroid Build Coastguard Worker                       packed_type,
336*795d594fSAndroid Build Coastguard Worker                       side_effects,
337*795d594fSAndroid Build Coastguard Worker                       number_of_inputs,
338*795d594fSAndroid Build Coastguard Worker                       vector_length,
339*795d594fSAndroid Build Coastguard Worker                       dex_pc),
340*795d594fSAndroid Build Coastguard Worker         alignment_(DataType::Size(packed_type), 0) {
341*795d594fSAndroid Build Coastguard Worker     DCHECK_GE(number_of_inputs, 2u);
342*795d594fSAndroid Build Coastguard Worker   }
343*795d594fSAndroid Build Coastguard Worker 
SetAlignment(Alignment alignment)344*795d594fSAndroid Build Coastguard Worker   void SetAlignment(Alignment alignment) { alignment_ = alignment; }
345*795d594fSAndroid Build Coastguard Worker 
GetAlignment()346*795d594fSAndroid Build Coastguard Worker   Alignment GetAlignment() const { return alignment_; }
347*795d594fSAndroid Build Coastguard Worker 
GetArray()348*795d594fSAndroid Build Coastguard Worker   HInstruction* GetArray() const { return InputAt(0); }
GetIndex()349*795d594fSAndroid Build Coastguard Worker   HInstruction* GetIndex() const { return InputAt(1); }
350*795d594fSAndroid Build Coastguard Worker 
InstructionDataEquals(const HInstruction * other)351*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
352*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsVecMemoryOperation());
353*795d594fSAndroid Build Coastguard Worker     const HVecMemoryOperation* o = other->AsVecMemoryOperation();
354*795d594fSAndroid Build Coastguard Worker     return HVecOperation::InstructionDataEquals(o) && GetAlignment() == o->GetAlignment();
355*795d594fSAndroid Build Coastguard Worker   }
356*795d594fSAndroid Build Coastguard Worker 
357*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(VecMemoryOperation);
358*795d594fSAndroid Build Coastguard Worker 
359*795d594fSAndroid Build Coastguard Worker  protected:
360*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecMemoryOperation);
361*795d594fSAndroid Build Coastguard Worker 
362*795d594fSAndroid Build Coastguard Worker  private:
363*795d594fSAndroid Build Coastguard Worker   Alignment alignment_;
364*795d594fSAndroid Build Coastguard Worker };
365*795d594fSAndroid Build Coastguard Worker 
366*795d594fSAndroid Build Coastguard Worker // Packed type consistency checker ("same vector length" integral types may mix freely).
367*795d594fSAndroid Build Coastguard Worker // Tests relaxed type consistency in which packed same-size integral types can co-exist,
368*795d594fSAndroid Build Coastguard Worker // but other type mixes are an error.
HasConsistentPackedTypes(HInstruction * input,DataType::Type type)369*795d594fSAndroid Build Coastguard Worker inline static bool HasConsistentPackedTypes(HInstruction* input, DataType::Type type) {
370*795d594fSAndroid Build Coastguard Worker   if (input->IsPhi()) {
371*795d594fSAndroid Build Coastguard Worker     return input->GetType() == HVecOperation::kSIMDType;  // carries SIMD
372*795d594fSAndroid Build Coastguard Worker   }
373*795d594fSAndroid Build Coastguard Worker   DCHECK(input->IsVecOperation());
374*795d594fSAndroid Build Coastguard Worker   DataType::Type input_type = input->AsVecOperation()->GetPackedType();
375*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(HVecOperation::ToUnsignedType(input_type) == HVecOperation::ToUnsignedType(type),
376*795d594fSAndroid Build Coastguard Worker             HVecOperation::ToSignedType(input_type) == HVecOperation::ToSignedType(type));
377*795d594fSAndroid Build Coastguard Worker   return HVecOperation::ToSignedType(input_type) == HVecOperation::ToSignedType(type);
378*795d594fSAndroid Build Coastguard Worker }
379*795d594fSAndroid Build Coastguard Worker 
380*795d594fSAndroid Build Coastguard Worker //
381*795d594fSAndroid Build Coastguard Worker // Definitions of concrete unary vector operations in HIR.
382*795d594fSAndroid Build Coastguard Worker //
383*795d594fSAndroid Build Coastguard Worker 
384*795d594fSAndroid Build Coastguard Worker // Replicates the given scalar into a vector,
385*795d594fSAndroid Build Coastguard Worker // viz. replicate(x) = [ x, .. , x ].
386*795d594fSAndroid Build Coastguard Worker class HVecReplicateScalar final : public HVecUnaryOperation {
387*795d594fSAndroid Build Coastguard Worker  public:
HVecReplicateScalar(ArenaAllocator * allocator,HInstruction * scalar,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)388*795d594fSAndroid Build Coastguard Worker   HVecReplicateScalar(ArenaAllocator* allocator,
389*795d594fSAndroid Build Coastguard Worker                       HInstruction* scalar,
390*795d594fSAndroid Build Coastguard Worker                       DataType::Type packed_type,
391*795d594fSAndroid Build Coastguard Worker                       size_t vector_length,
392*795d594fSAndroid Build Coastguard Worker                       uint32_t dex_pc)
393*795d594fSAndroid Build Coastguard Worker       : HVecUnaryOperation(
394*795d594fSAndroid Build Coastguard Worker             kVecReplicateScalar, allocator, scalar, packed_type, vector_length, dex_pc) {
395*795d594fSAndroid Build Coastguard Worker     DCHECK(!ReturnsSIMDValue(scalar));
396*795d594fSAndroid Build Coastguard Worker   }
397*795d594fSAndroid Build Coastguard Worker 
398*795d594fSAndroid Build Coastguard Worker   // A replicate needs to stay in place, since SIMD registers are not
399*795d594fSAndroid Build Coastguard Worker   // kept alive across vector loop boundaries (yet).
CanBeMoved()400*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return false; }
401*795d594fSAndroid Build Coastguard Worker 
402*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecReplicateScalar);
403*795d594fSAndroid Build Coastguard Worker 
404*795d594fSAndroid Build Coastguard Worker  protected:
405*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecReplicateScalar);
406*795d594fSAndroid Build Coastguard Worker };
407*795d594fSAndroid Build Coastguard Worker 
408*795d594fSAndroid Build Coastguard Worker // Extracts a particular scalar from the given vector,
409*795d594fSAndroid Build Coastguard Worker // viz. extract[ x1, .. , xn ] = x_i.
410*795d594fSAndroid Build Coastguard Worker //
411*795d594fSAndroid Build Coastguard Worker // TODO: for now only i == 1 case supported.
412*795d594fSAndroid Build Coastguard Worker class HVecExtractScalar final : public HVecUnaryOperation {
413*795d594fSAndroid Build Coastguard Worker  public:
HVecExtractScalar(ArenaAllocator * allocator,HInstruction * input,DataType::Type packed_type,size_t vector_length,size_t index,uint32_t dex_pc)414*795d594fSAndroid Build Coastguard Worker   HVecExtractScalar(ArenaAllocator* allocator,
415*795d594fSAndroid Build Coastguard Worker                     HInstruction* input,
416*795d594fSAndroid Build Coastguard Worker                     DataType::Type packed_type,
417*795d594fSAndroid Build Coastguard Worker                     size_t vector_length,
418*795d594fSAndroid Build Coastguard Worker                     size_t index,
419*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc)
420*795d594fSAndroid Build Coastguard Worker       : HVecUnaryOperation(
421*795d594fSAndroid Build Coastguard Worker             kVecExtractScalar, allocator, input, packed_type, vector_length, dex_pc) {
422*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(input, packed_type));
423*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(index, vector_length);
424*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(index, 0u);
425*795d594fSAndroid Build Coastguard Worker     // Yields a single component in the vector.
426*795d594fSAndroid Build Coastguard Worker     // Overrides the kSIMDType set by the VecOperation constructor.
427*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeField>(packed_type);
428*795d594fSAndroid Build Coastguard Worker   }
429*795d594fSAndroid Build Coastguard Worker 
430*795d594fSAndroid Build Coastguard Worker   // An extract needs to stay in place, since SIMD registers are not
431*795d594fSAndroid Build Coastguard Worker   // kept alive across vector loop boundaries (yet).
CanBeMoved()432*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return false; }
433*795d594fSAndroid Build Coastguard Worker 
434*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecExtractScalar);
435*795d594fSAndroid Build Coastguard Worker 
436*795d594fSAndroid Build Coastguard Worker  protected:
437*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecExtractScalar);
438*795d594fSAndroid Build Coastguard Worker };
439*795d594fSAndroid Build Coastguard Worker 
440*795d594fSAndroid Build Coastguard Worker // Reduces the given vector into the first element as sum/min/max,
441*795d594fSAndroid Build Coastguard Worker // viz. sum-reduce[ x1, .. , xn ] = [ y, ---- ], where y = sum xi
442*795d594fSAndroid Build Coastguard Worker // and the "-" denotes "don't care" (implementation dependent).
443*795d594fSAndroid Build Coastguard Worker class HVecReduce final : public HVecUnaryOperation {
444*795d594fSAndroid Build Coastguard Worker  public:
445*795d594fSAndroid Build Coastguard Worker   enum ReductionKind {
446*795d594fSAndroid Build Coastguard Worker     kSum = 1,
447*795d594fSAndroid Build Coastguard Worker     kMin = 2,
448*795d594fSAndroid Build Coastguard Worker     kMax = 3
449*795d594fSAndroid Build Coastguard Worker   };
450*795d594fSAndroid Build Coastguard Worker 
HVecReduce(ArenaAllocator * allocator,HInstruction * input,DataType::Type packed_type,size_t vector_length,ReductionKind reduction_kind,uint32_t dex_pc)451*795d594fSAndroid Build Coastguard Worker   HVecReduce(ArenaAllocator* allocator,
452*795d594fSAndroid Build Coastguard Worker              HInstruction* input,
453*795d594fSAndroid Build Coastguard Worker              DataType::Type packed_type,
454*795d594fSAndroid Build Coastguard Worker              size_t vector_length,
455*795d594fSAndroid Build Coastguard Worker              ReductionKind reduction_kind,
456*795d594fSAndroid Build Coastguard Worker              uint32_t dex_pc)
457*795d594fSAndroid Build Coastguard Worker       : HVecUnaryOperation(kVecReduce, allocator, input, packed_type, vector_length, dex_pc),
458*795d594fSAndroid Build Coastguard Worker         reduction_kind_(reduction_kind) {
459*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(input, packed_type));
460*795d594fSAndroid Build Coastguard Worker   }
461*795d594fSAndroid Build Coastguard Worker 
GetReductionKind()462*795d594fSAndroid Build Coastguard Worker   ReductionKind GetReductionKind() const { return reduction_kind_; }
463*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()464*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
465*795d594fSAndroid Build Coastguard Worker 
InstructionDataEquals(const HInstruction * other)466*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
467*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsVecReduce());
468*795d594fSAndroid Build Coastguard Worker     const HVecReduce* o = other->AsVecReduce();
469*795d594fSAndroid Build Coastguard Worker     return HVecOperation::InstructionDataEquals(o) && GetReductionKind() == o->GetReductionKind();
470*795d594fSAndroid Build Coastguard Worker   }
471*795d594fSAndroid Build Coastguard Worker 
472*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecReduce);
473*795d594fSAndroid Build Coastguard Worker 
474*795d594fSAndroid Build Coastguard Worker  protected:
475*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecReduce);
476*795d594fSAndroid Build Coastguard Worker 
477*795d594fSAndroid Build Coastguard Worker  private:
478*795d594fSAndroid Build Coastguard Worker   const ReductionKind reduction_kind_;
479*795d594fSAndroid Build Coastguard Worker };
480*795d594fSAndroid Build Coastguard Worker 
481*795d594fSAndroid Build Coastguard Worker // Converts every component in the vector,
482*795d594fSAndroid Build Coastguard Worker // viz. cnv[ x1, .. , xn ]  = [ cnv(x1), .. , cnv(xn) ].
483*795d594fSAndroid Build Coastguard Worker class HVecCnv final : public HVecUnaryOperation {
484*795d594fSAndroid Build Coastguard Worker  public:
HVecCnv(ArenaAllocator * allocator,HInstruction * input,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)485*795d594fSAndroid Build Coastguard Worker   HVecCnv(ArenaAllocator* allocator,
486*795d594fSAndroid Build Coastguard Worker           HInstruction* input,
487*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
488*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
489*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
490*795d594fSAndroid Build Coastguard Worker       : HVecUnaryOperation(kVecCnv, allocator, input, packed_type, vector_length, dex_pc) {
491*795d594fSAndroid Build Coastguard Worker     DCHECK(input->IsVecOperation());
492*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(GetInputType(), GetResultType());  // actual convert
493*795d594fSAndroid Build Coastguard Worker   }
494*795d594fSAndroid Build Coastguard Worker 
GetInputType()495*795d594fSAndroid Build Coastguard Worker   DataType::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
GetResultType()496*795d594fSAndroid Build Coastguard Worker   DataType::Type GetResultType() const { return GetPackedType(); }
497*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()498*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
499*795d594fSAndroid Build Coastguard Worker 
500*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecCnv);
501*795d594fSAndroid Build Coastguard Worker 
502*795d594fSAndroid Build Coastguard Worker  protected:
503*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecCnv);
504*795d594fSAndroid Build Coastguard Worker };
505*795d594fSAndroid Build Coastguard Worker 
506*795d594fSAndroid Build Coastguard Worker // Negates every component in the vector,
507*795d594fSAndroid Build Coastguard Worker // viz. neg[ x1, .. , xn ]  = [ -x1, .. , -xn ].
508*795d594fSAndroid Build Coastguard Worker class HVecNeg final : public HVecUnaryOperation {
509*795d594fSAndroid Build Coastguard Worker  public:
HVecNeg(ArenaAllocator * allocator,HInstruction * input,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)510*795d594fSAndroid Build Coastguard Worker   HVecNeg(ArenaAllocator* allocator,
511*795d594fSAndroid Build Coastguard Worker           HInstruction* input,
512*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
513*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
514*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
515*795d594fSAndroid Build Coastguard Worker       : HVecUnaryOperation(kVecNeg, allocator, input, packed_type, vector_length, dex_pc) {
516*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(input, packed_type));
517*795d594fSAndroid Build Coastguard Worker   }
518*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()519*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
520*795d594fSAndroid Build Coastguard Worker 
521*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecNeg);
522*795d594fSAndroid Build Coastguard Worker 
523*795d594fSAndroid Build Coastguard Worker  protected:
524*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecNeg);
525*795d594fSAndroid Build Coastguard Worker };
526*795d594fSAndroid Build Coastguard Worker 
527*795d594fSAndroid Build Coastguard Worker // Takes absolute value of every component in the vector,
528*795d594fSAndroid Build Coastguard Worker // viz. abs[ x1, .. , xn ]  = [ |x1|, .. , |xn| ]
529*795d594fSAndroid Build Coastguard Worker // for signed operand x.
530*795d594fSAndroid Build Coastguard Worker class HVecAbs final : public HVecUnaryOperation {
531*795d594fSAndroid Build Coastguard Worker  public:
HVecAbs(ArenaAllocator * allocator,HInstruction * input,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)532*795d594fSAndroid Build Coastguard Worker   HVecAbs(ArenaAllocator* allocator,
533*795d594fSAndroid Build Coastguard Worker           HInstruction* input,
534*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
535*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
536*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
537*795d594fSAndroid Build Coastguard Worker       : HVecUnaryOperation(kVecAbs, allocator, input, packed_type, vector_length, dex_pc) {
538*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(input, packed_type));
539*795d594fSAndroid Build Coastguard Worker   }
540*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()541*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
542*795d594fSAndroid Build Coastguard Worker 
543*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecAbs);
544*795d594fSAndroid Build Coastguard Worker 
545*795d594fSAndroid Build Coastguard Worker  protected:
546*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecAbs);
547*795d594fSAndroid Build Coastguard Worker };
548*795d594fSAndroid Build Coastguard Worker 
549*795d594fSAndroid Build Coastguard Worker // Bitwise- or boolean-nots every component in the vector,
550*795d594fSAndroid Build Coastguard Worker // viz. not[ x1, .. , xn ]  = [ ~x1, .. , ~xn ], or
551*795d594fSAndroid Build Coastguard Worker //      not[ x1, .. , xn ]  = [ !x1, .. , !xn ] for boolean.
552*795d594fSAndroid Build Coastguard Worker class HVecNot final : public HVecUnaryOperation {
553*795d594fSAndroid Build Coastguard Worker  public:
HVecNot(ArenaAllocator * allocator,HInstruction * input,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)554*795d594fSAndroid Build Coastguard Worker   HVecNot(ArenaAllocator* allocator,
555*795d594fSAndroid Build Coastguard Worker           HInstruction* input,
556*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
557*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
558*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
559*795d594fSAndroid Build Coastguard Worker       : HVecUnaryOperation(kVecNot, allocator, input, packed_type, vector_length, dex_pc) {
560*795d594fSAndroid Build Coastguard Worker     DCHECK(input->IsVecOperation());
561*795d594fSAndroid Build Coastguard Worker   }
562*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()563*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
564*795d594fSAndroid Build Coastguard Worker 
565*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecNot);
566*795d594fSAndroid Build Coastguard Worker 
567*795d594fSAndroid Build Coastguard Worker  protected:
568*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecNot);
569*795d594fSAndroid Build Coastguard Worker };
570*795d594fSAndroid Build Coastguard Worker 
571*795d594fSAndroid Build Coastguard Worker //
572*795d594fSAndroid Build Coastguard Worker // Definitions of concrete binary vector operations in HIR.
573*795d594fSAndroid Build Coastguard Worker //
574*795d594fSAndroid Build Coastguard Worker 
575*795d594fSAndroid Build Coastguard Worker // Adds every component in the two vectors,
576*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ].
577*795d594fSAndroid Build Coastguard Worker class HVecAdd final : public HVecBinaryOperation {
578*795d594fSAndroid Build Coastguard Worker  public:
HVecAdd(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)579*795d594fSAndroid Build Coastguard Worker   HVecAdd(ArenaAllocator* allocator,
580*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
581*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
582*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
583*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
584*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
585*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecAdd, allocator, left, right, packed_type, vector_length, dex_pc) {
586*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
587*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(right, packed_type));
588*795d594fSAndroid Build Coastguard Worker   }
589*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()590*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
591*795d594fSAndroid Build Coastguard Worker 
592*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecAdd);
593*795d594fSAndroid Build Coastguard Worker 
594*795d594fSAndroid Build Coastguard Worker  protected:
595*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecAdd);
596*795d594fSAndroid Build Coastguard Worker };
597*795d594fSAndroid Build Coastguard Worker 
598*795d594fSAndroid Build Coastguard Worker // Adds every component in the two vectors using saturation arithmetic,
599*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 +_sat y1, .. , xn +_sat yn ]
600*795d594fSAndroid Build Coastguard Worker // for either both signed or both unsigned operands x, y (reflected in packed_type).
601*795d594fSAndroid Build Coastguard Worker class HVecSaturationAdd final : public HVecBinaryOperation {
602*795d594fSAndroid Build Coastguard Worker  public:
HVecSaturationAdd(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)603*795d594fSAndroid Build Coastguard Worker   HVecSaturationAdd(ArenaAllocator* allocator,
604*795d594fSAndroid Build Coastguard Worker                     HInstruction* left,
605*795d594fSAndroid Build Coastguard Worker                     HInstruction* right,
606*795d594fSAndroid Build Coastguard Worker                     DataType::Type packed_type,
607*795d594fSAndroid Build Coastguard Worker                     size_t vector_length,
608*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc)
609*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(
610*795d594fSAndroid Build Coastguard Worker           kVecSaturationAdd, allocator, left, right, packed_type, vector_length, dex_pc) {
611*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
612*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(right, packed_type));
613*795d594fSAndroid Build Coastguard Worker   }
614*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()615*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
616*795d594fSAndroid Build Coastguard Worker 
617*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecSaturationAdd);
618*795d594fSAndroid Build Coastguard Worker 
619*795d594fSAndroid Build Coastguard Worker  protected:
620*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecSaturationAdd);
621*795d594fSAndroid Build Coastguard Worker };
622*795d594fSAndroid Build Coastguard Worker 
623*795d594fSAndroid Build Coastguard Worker // Performs halving add on every component in the two vectors, viz.
624*795d594fSAndroid Build Coastguard Worker // rounded   [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ]
625*795d594fSAndroid Build Coastguard Worker // truncated [ x1, .. , xn ] hadd  [ y1, .. , yn ] = [ (x1 + y1)     >> 1, .. , (xn + yn )    >> 1 ]
626*795d594fSAndroid Build Coastguard Worker // for either both signed or both unsigned operands x, y (reflected in packed_type).
627*795d594fSAndroid Build Coastguard Worker class HVecHalvingAdd final : public HVecBinaryOperation {
628*795d594fSAndroid Build Coastguard Worker  public:
HVecHalvingAdd(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,bool is_rounded,uint32_t dex_pc)629*795d594fSAndroid Build Coastguard Worker   HVecHalvingAdd(ArenaAllocator* allocator,
630*795d594fSAndroid Build Coastguard Worker                  HInstruction* left,
631*795d594fSAndroid Build Coastguard Worker                  HInstruction* right,
632*795d594fSAndroid Build Coastguard Worker                  DataType::Type packed_type,
633*795d594fSAndroid Build Coastguard Worker                  size_t vector_length,
634*795d594fSAndroid Build Coastguard Worker                  bool is_rounded,
635*795d594fSAndroid Build Coastguard Worker                  uint32_t dex_pc)
636*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(
637*795d594fSAndroid Build Coastguard Worker             kVecHalvingAdd, allocator, left, right, packed_type, vector_length, dex_pc) {
638*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
639*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(right, packed_type));
640*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFieldHAddIsRounded>(is_rounded);
641*795d594fSAndroid Build Coastguard Worker   }
642*795d594fSAndroid Build Coastguard Worker 
IsRounded()643*795d594fSAndroid Build Coastguard Worker   bool IsRounded() const { return GetPackedFlag<kFieldHAddIsRounded>(); }
644*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()645*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
646*795d594fSAndroid Build Coastguard Worker 
InstructionDataEquals(const HInstruction * other)647*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
648*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsVecHalvingAdd());
649*795d594fSAndroid Build Coastguard Worker     const HVecHalvingAdd* o = other->AsVecHalvingAdd();
650*795d594fSAndroid Build Coastguard Worker     return HVecOperation::InstructionDataEquals(o) && IsRounded() == o->IsRounded();
651*795d594fSAndroid Build Coastguard Worker   }
652*795d594fSAndroid Build Coastguard Worker 
653*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecHalvingAdd);
654*795d594fSAndroid Build Coastguard Worker 
655*795d594fSAndroid Build Coastguard Worker  protected:
656*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecHalvingAdd);
657*795d594fSAndroid Build Coastguard Worker 
658*795d594fSAndroid Build Coastguard Worker  private:
659*795d594fSAndroid Build Coastguard Worker   // Additional packed bits.
660*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldHAddIsRounded = HVecOperation::kNumberOfVectorOpPackedBits;
661*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfHAddPackedBits = kFieldHAddIsRounded + 1;
662*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfHAddPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
663*795d594fSAndroid Build Coastguard Worker };
664*795d594fSAndroid Build Coastguard Worker 
665*795d594fSAndroid Build Coastguard Worker // Subtracts every component in the two vectors,
666*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ].
667*795d594fSAndroid Build Coastguard Worker class HVecSub final : public HVecBinaryOperation {
668*795d594fSAndroid Build Coastguard Worker  public:
HVecSub(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)669*795d594fSAndroid Build Coastguard Worker   HVecSub(ArenaAllocator* allocator,
670*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
671*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
672*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
673*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
674*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
675*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecSub, allocator, left, right, packed_type, vector_length, dex_pc) {
676*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
677*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(right, packed_type));
678*795d594fSAndroid Build Coastguard Worker   }
679*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()680*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
681*795d594fSAndroid Build Coastguard Worker 
682*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecSub);
683*795d594fSAndroid Build Coastguard Worker 
684*795d594fSAndroid Build Coastguard Worker  protected:
685*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecSub);
686*795d594fSAndroid Build Coastguard Worker };
687*795d594fSAndroid Build Coastguard Worker 
688*795d594fSAndroid Build Coastguard Worker // Subtracts every component in the two vectors using saturation arithmetic,
689*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 -_sat y1, .. , xn -_sat yn ]
690*795d594fSAndroid Build Coastguard Worker // for either both signed or both unsigned operands x, y (reflected in packed_type).
691*795d594fSAndroid Build Coastguard Worker class HVecSaturationSub final : public HVecBinaryOperation {
692*795d594fSAndroid Build Coastguard Worker  public:
HVecSaturationSub(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)693*795d594fSAndroid Build Coastguard Worker   HVecSaturationSub(ArenaAllocator* allocator,
694*795d594fSAndroid Build Coastguard Worker                     HInstruction* left,
695*795d594fSAndroid Build Coastguard Worker                     HInstruction* right,
696*795d594fSAndroid Build Coastguard Worker                     DataType::Type packed_type,
697*795d594fSAndroid Build Coastguard Worker                     size_t vector_length,
698*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc)
699*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(
700*795d594fSAndroid Build Coastguard Worker           kVecSaturationSub, allocator, left, right, packed_type, vector_length, dex_pc) {
701*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
702*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(right, packed_type));
703*795d594fSAndroid Build Coastguard Worker   }
704*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()705*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
706*795d594fSAndroid Build Coastguard Worker 
707*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecSaturationSub);
708*795d594fSAndroid Build Coastguard Worker 
709*795d594fSAndroid Build Coastguard Worker  protected:
710*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecSaturationSub);
711*795d594fSAndroid Build Coastguard Worker };
712*795d594fSAndroid Build Coastguard Worker 
713*795d594fSAndroid Build Coastguard Worker // Multiplies every component in the two vectors,
714*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ].
715*795d594fSAndroid Build Coastguard Worker class HVecMul final : public HVecBinaryOperation {
716*795d594fSAndroid Build Coastguard Worker  public:
HVecMul(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)717*795d594fSAndroid Build Coastguard Worker   HVecMul(ArenaAllocator* allocator,
718*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
719*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
720*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
721*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
722*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
723*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecMul, allocator, left, right, packed_type, vector_length, dex_pc) {
724*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
725*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(right, packed_type));
726*795d594fSAndroid Build Coastguard Worker   }
727*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()728*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
729*795d594fSAndroid Build Coastguard Worker 
730*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecMul);
731*795d594fSAndroid Build Coastguard Worker 
732*795d594fSAndroid Build Coastguard Worker  protected:
733*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecMul);
734*795d594fSAndroid Build Coastguard Worker };
735*795d594fSAndroid Build Coastguard Worker 
736*795d594fSAndroid Build Coastguard Worker // Divides every component in the two vectors,
737*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ].
738*795d594fSAndroid Build Coastguard Worker class HVecDiv final : public HVecBinaryOperation {
739*795d594fSAndroid Build Coastguard Worker  public:
HVecDiv(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)740*795d594fSAndroid Build Coastguard Worker   HVecDiv(ArenaAllocator* allocator,
741*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
742*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
743*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
744*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
745*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
746*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecDiv, allocator, left, right, packed_type, vector_length, dex_pc) {
747*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
748*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(right, packed_type));
749*795d594fSAndroid Build Coastguard Worker   }
750*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()751*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
752*795d594fSAndroid Build Coastguard Worker 
753*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecDiv);
754*795d594fSAndroid Build Coastguard Worker 
755*795d594fSAndroid Build Coastguard Worker  protected:
756*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecDiv);
757*795d594fSAndroid Build Coastguard Worker };
758*795d594fSAndroid Build Coastguard Worker 
759*795d594fSAndroid Build Coastguard Worker // Takes minimum of every component in the two vectors,
760*795d594fSAndroid Build Coastguard Worker // viz. MIN( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ min(x1, y1), .. , min(xn, yn) ]
761*795d594fSAndroid Build Coastguard Worker // for either both signed or both unsigned operands x, y (reflected in packed_type).
762*795d594fSAndroid Build Coastguard Worker class HVecMin final : public HVecBinaryOperation {
763*795d594fSAndroid Build Coastguard Worker  public:
HVecMin(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)764*795d594fSAndroid Build Coastguard Worker   HVecMin(ArenaAllocator* allocator,
765*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
766*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
767*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
768*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
769*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
770*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecMin, allocator, left, right, packed_type, vector_length, dex_pc) {
771*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
772*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(right, packed_type));
773*795d594fSAndroid Build Coastguard Worker   }
774*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()775*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
776*795d594fSAndroid Build Coastguard Worker 
777*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecMin);
778*795d594fSAndroid Build Coastguard Worker 
779*795d594fSAndroid Build Coastguard Worker  protected:
780*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecMin);
781*795d594fSAndroid Build Coastguard Worker };
782*795d594fSAndroid Build Coastguard Worker 
783*795d594fSAndroid Build Coastguard Worker // Takes maximum of every component in the two vectors,
784*795d594fSAndroid Build Coastguard Worker // viz. MAX( [ x1, .. , xn ] , [ y1, .. , yn ]) = [ max(x1, y1), .. , max(xn, yn) ]
785*795d594fSAndroid Build Coastguard Worker // for either both signed or both unsigned operands x, y (reflected in packed_type).
786*795d594fSAndroid Build Coastguard Worker class HVecMax final : public HVecBinaryOperation {
787*795d594fSAndroid Build Coastguard Worker  public:
HVecMax(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)788*795d594fSAndroid Build Coastguard Worker   HVecMax(ArenaAllocator* allocator,
789*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
790*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
791*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
792*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
793*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
794*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecMax, allocator, left, right, packed_type, vector_length, dex_pc) {
795*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
796*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(right, packed_type));
797*795d594fSAndroid Build Coastguard Worker   }
798*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()799*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
800*795d594fSAndroid Build Coastguard Worker 
801*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecMax);
802*795d594fSAndroid Build Coastguard Worker 
803*795d594fSAndroid Build Coastguard Worker  protected:
804*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecMax);
805*795d594fSAndroid Build Coastguard Worker };
806*795d594fSAndroid Build Coastguard Worker 
807*795d594fSAndroid Build Coastguard Worker // Bitwise-ands every component in the two vectors,
808*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ].
809*795d594fSAndroid Build Coastguard Worker class HVecAnd final : public HVecBinaryOperation {
810*795d594fSAndroid Build Coastguard Worker  public:
HVecAnd(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)811*795d594fSAndroid Build Coastguard Worker   HVecAnd(ArenaAllocator* allocator,
812*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
813*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
814*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
815*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
816*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
817*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecAnd, allocator, left, right, packed_type, vector_length, dex_pc) {
818*795d594fSAndroid Build Coastguard Worker     DCHECK(left->IsVecOperation() && right->IsVecOperation());
819*795d594fSAndroid Build Coastguard Worker   }
820*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()821*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
822*795d594fSAndroid Build Coastguard Worker 
823*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecAnd);
824*795d594fSAndroid Build Coastguard Worker 
825*795d594fSAndroid Build Coastguard Worker  protected:
826*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecAnd);
827*795d594fSAndroid Build Coastguard Worker };
828*795d594fSAndroid Build Coastguard Worker 
829*795d594fSAndroid Build Coastguard Worker // Bitwise-and-nots every component in the two vectors,
830*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ].
831*795d594fSAndroid Build Coastguard Worker class HVecAndNot final : public HVecBinaryOperation {
832*795d594fSAndroid Build Coastguard Worker  public:
HVecAndNot(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)833*795d594fSAndroid Build Coastguard Worker   HVecAndNot(ArenaAllocator* allocator,
834*795d594fSAndroid Build Coastguard Worker              HInstruction* left,
835*795d594fSAndroid Build Coastguard Worker              HInstruction* right,
836*795d594fSAndroid Build Coastguard Worker              DataType::Type packed_type,
837*795d594fSAndroid Build Coastguard Worker              size_t vector_length,
838*795d594fSAndroid Build Coastguard Worker              uint32_t dex_pc)
839*795d594fSAndroid Build Coastguard Worker          : HVecBinaryOperation(
840*795d594fSAndroid Build Coastguard Worker                kVecAndNot, allocator, left, right, packed_type, vector_length, dex_pc) {
841*795d594fSAndroid Build Coastguard Worker     DCHECK(left->IsVecOperation() && right->IsVecOperation());
842*795d594fSAndroid Build Coastguard Worker   }
843*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()844*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
845*795d594fSAndroid Build Coastguard Worker 
846*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecAndNot);
847*795d594fSAndroid Build Coastguard Worker 
848*795d594fSAndroid Build Coastguard Worker  protected:
849*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecAndNot);
850*795d594fSAndroid Build Coastguard Worker };
851*795d594fSAndroid Build Coastguard Worker 
852*795d594fSAndroid Build Coastguard Worker // Bitwise-ors every component in the two vectors,
853*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ].
854*795d594fSAndroid Build Coastguard Worker class HVecOr final : public HVecBinaryOperation {
855*795d594fSAndroid Build Coastguard Worker  public:
HVecOr(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)856*795d594fSAndroid Build Coastguard Worker   HVecOr(ArenaAllocator* allocator,
857*795d594fSAndroid Build Coastguard Worker          HInstruction* left,
858*795d594fSAndroid Build Coastguard Worker          HInstruction* right,
859*795d594fSAndroid Build Coastguard Worker          DataType::Type packed_type,
860*795d594fSAndroid Build Coastguard Worker          size_t vector_length,
861*795d594fSAndroid Build Coastguard Worker          uint32_t dex_pc)
862*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecOr, allocator, left, right, packed_type, vector_length, dex_pc) {
863*795d594fSAndroid Build Coastguard Worker     DCHECK(left->IsVecOperation() && right->IsVecOperation());
864*795d594fSAndroid Build Coastguard Worker   }
865*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()866*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
867*795d594fSAndroid Build Coastguard Worker 
868*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecOr);
869*795d594fSAndroid Build Coastguard Worker 
870*795d594fSAndroid Build Coastguard Worker  protected:
871*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecOr);
872*795d594fSAndroid Build Coastguard Worker };
873*795d594fSAndroid Build Coastguard Worker 
874*795d594fSAndroid Build Coastguard Worker // Bitwise-xors every component in the two vectors,
875*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ].
876*795d594fSAndroid Build Coastguard Worker class HVecXor final : public HVecBinaryOperation {
877*795d594fSAndroid Build Coastguard Worker  public:
HVecXor(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)878*795d594fSAndroid Build Coastguard Worker   HVecXor(ArenaAllocator* allocator,
879*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
880*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
881*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
882*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
883*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
884*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecXor, allocator, left, right, packed_type, vector_length, dex_pc) {
885*795d594fSAndroid Build Coastguard Worker     DCHECK(left->IsVecOperation() && right->IsVecOperation());
886*795d594fSAndroid Build Coastguard Worker   }
887*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()888*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
889*795d594fSAndroid Build Coastguard Worker 
890*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecXor);
891*795d594fSAndroid Build Coastguard Worker 
892*795d594fSAndroid Build Coastguard Worker  protected:
893*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecXor);
894*795d594fSAndroid Build Coastguard Worker };
895*795d594fSAndroid Build Coastguard Worker 
896*795d594fSAndroid Build Coastguard Worker // Logically shifts every component in the vector left by the given distance,
897*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ].
898*795d594fSAndroid Build Coastguard Worker class HVecShl final : public HVecBinaryOperation {
899*795d594fSAndroid Build Coastguard Worker  public:
HVecShl(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)900*795d594fSAndroid Build Coastguard Worker   HVecShl(ArenaAllocator* allocator,
901*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
902*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
903*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
904*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
905*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
906*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecShl, allocator, left, right, packed_type, vector_length, dex_pc) {
907*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
908*795d594fSAndroid Build Coastguard Worker   }
909*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()910*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
911*795d594fSAndroid Build Coastguard Worker 
912*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecShl);
913*795d594fSAndroid Build Coastguard Worker 
914*795d594fSAndroid Build Coastguard Worker  protected:
915*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecShl);
916*795d594fSAndroid Build Coastguard Worker };
917*795d594fSAndroid Build Coastguard Worker 
918*795d594fSAndroid Build Coastguard Worker // Arithmetically shifts every component in the vector right by the given distance,
919*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ].
920*795d594fSAndroid Build Coastguard Worker class HVecShr final : public HVecBinaryOperation {
921*795d594fSAndroid Build Coastguard Worker  public:
HVecShr(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)922*795d594fSAndroid Build Coastguard Worker   HVecShr(ArenaAllocator* allocator,
923*795d594fSAndroid Build Coastguard Worker           HInstruction* left,
924*795d594fSAndroid Build Coastguard Worker           HInstruction* right,
925*795d594fSAndroid Build Coastguard Worker           DataType::Type packed_type,
926*795d594fSAndroid Build Coastguard Worker           size_t vector_length,
927*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
928*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecShr, allocator, left, right, packed_type, vector_length, dex_pc) {
929*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
930*795d594fSAndroid Build Coastguard Worker   }
931*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()932*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
933*795d594fSAndroid Build Coastguard Worker 
934*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecShr);
935*795d594fSAndroid Build Coastguard Worker 
936*795d594fSAndroid Build Coastguard Worker  protected:
937*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecShr);
938*795d594fSAndroid Build Coastguard Worker };
939*795d594fSAndroid Build Coastguard Worker 
940*795d594fSAndroid Build Coastguard Worker // Logically shifts every component in the vector right by the given distance,
941*795d594fSAndroid Build Coastguard Worker // viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ].
942*795d594fSAndroid Build Coastguard Worker class HVecUShr final : public HVecBinaryOperation {
943*795d594fSAndroid Build Coastguard Worker  public:
HVecUShr(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)944*795d594fSAndroid Build Coastguard Worker   HVecUShr(ArenaAllocator* allocator,
945*795d594fSAndroid Build Coastguard Worker            HInstruction* left,
946*795d594fSAndroid Build Coastguard Worker            HInstruction* right,
947*795d594fSAndroid Build Coastguard Worker            DataType::Type packed_type,
948*795d594fSAndroid Build Coastguard Worker            size_t vector_length,
949*795d594fSAndroid Build Coastguard Worker            uint32_t dex_pc)
950*795d594fSAndroid Build Coastguard Worker       : HVecBinaryOperation(kVecUShr, allocator, left, right, packed_type, vector_length, dex_pc) {
951*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(left, packed_type));
952*795d594fSAndroid Build Coastguard Worker   }
953*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()954*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
955*795d594fSAndroid Build Coastguard Worker 
956*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecUShr);
957*795d594fSAndroid Build Coastguard Worker 
958*795d594fSAndroid Build Coastguard Worker  protected:
959*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecUShr);
960*795d594fSAndroid Build Coastguard Worker };
961*795d594fSAndroid Build Coastguard Worker 
962*795d594fSAndroid Build Coastguard Worker //
963*795d594fSAndroid Build Coastguard Worker // Definitions of concrete miscellaneous vector operations in HIR.
964*795d594fSAndroid Build Coastguard Worker //
965*795d594fSAndroid Build Coastguard Worker 
966*795d594fSAndroid Build Coastguard Worker // Assigns the given scalar elements to a vector,
967*795d594fSAndroid Build Coastguard Worker // viz. set( array(x1, .. , xn) ) = [ x1, .. ,            xn ] if n == m,
968*795d594fSAndroid Build Coastguard Worker //      set( array(x1, .. , xm) ) = [ x1, .. , xm, 0, .. , 0 ] if m <  n.
969*795d594fSAndroid Build Coastguard Worker class HVecSetScalars final : public HVecOperation {
970*795d594fSAndroid Build Coastguard Worker  public:
HVecSetScalars(ArenaAllocator * allocator,HInstruction * scalars[],DataType::Type packed_type,size_t vector_length,size_t number_of_scalars,uint32_t dex_pc)971*795d594fSAndroid Build Coastguard Worker   HVecSetScalars(ArenaAllocator* allocator,
972*795d594fSAndroid Build Coastguard Worker                  HInstruction* scalars[],
973*795d594fSAndroid Build Coastguard Worker                  DataType::Type packed_type,
974*795d594fSAndroid Build Coastguard Worker                  size_t vector_length,
975*795d594fSAndroid Build Coastguard Worker                  size_t number_of_scalars,
976*795d594fSAndroid Build Coastguard Worker                  uint32_t dex_pc)
977*795d594fSAndroid Build Coastguard Worker       : HVecOperation(kVecSetScalars,
978*795d594fSAndroid Build Coastguard Worker                       allocator,
979*795d594fSAndroid Build Coastguard Worker                       packed_type,
980*795d594fSAndroid Build Coastguard Worker                       SideEffects::None(),
981*795d594fSAndroid Build Coastguard Worker                       number_of_scalars,
982*795d594fSAndroid Build Coastguard Worker                       vector_length,
983*795d594fSAndroid Build Coastguard Worker                       dex_pc) {
984*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < number_of_scalars; i++) {
985*795d594fSAndroid Build Coastguard Worker       DCHECK(!ReturnsSIMDValue(scalars[i]));
986*795d594fSAndroid Build Coastguard Worker       SetRawInputAt(0, scalars[i]);
987*795d594fSAndroid Build Coastguard Worker     }
988*795d594fSAndroid Build Coastguard Worker   }
989*795d594fSAndroid Build Coastguard Worker 
990*795d594fSAndroid Build Coastguard Worker   // Setting scalars needs to stay in place, since SIMD registers are not
991*795d594fSAndroid Build Coastguard Worker   // kept alive across vector loop boundaries (yet).
CanBeMoved()992*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return false; }
993*795d594fSAndroid Build Coastguard Worker 
994*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecSetScalars);
995*795d594fSAndroid Build Coastguard Worker 
996*795d594fSAndroid Build Coastguard Worker  protected:
997*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecSetScalars);
998*795d594fSAndroid Build Coastguard Worker };
999*795d594fSAndroid Build Coastguard Worker 
1000*795d594fSAndroid Build Coastguard Worker // Multiplies every component in the two vectors, adds the result vector to the accumulator vector,
1001*795d594fSAndroid Build Coastguard Worker // viz. [ a1, .. , an ] + [ x1, .. , xn ] * [ y1, .. , yn ] = [ a1 + x1 * y1, .. , an + xn * yn ].
1002*795d594fSAndroid Build Coastguard Worker // For floating point types, Java rounding behavior must be preserved; the products are rounded to
1003*795d594fSAndroid Build Coastguard Worker // the proper precision before being added. "Fused" multiply-add operations available on several
1004*795d594fSAndroid Build Coastguard Worker // architectures are not usable since they would violate Java language rules.
1005*795d594fSAndroid Build Coastguard Worker class HVecMultiplyAccumulate final : public HVecOperation {
1006*795d594fSAndroid Build Coastguard Worker  public:
HVecMultiplyAccumulate(ArenaAllocator * allocator,InstructionKind op,HInstruction * accumulator,HInstruction * mul_left,HInstruction * mul_right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)1007*795d594fSAndroid Build Coastguard Worker   HVecMultiplyAccumulate(ArenaAllocator* allocator,
1008*795d594fSAndroid Build Coastguard Worker                          InstructionKind op,
1009*795d594fSAndroid Build Coastguard Worker                          HInstruction* accumulator,
1010*795d594fSAndroid Build Coastguard Worker                          HInstruction* mul_left,
1011*795d594fSAndroid Build Coastguard Worker                          HInstruction* mul_right,
1012*795d594fSAndroid Build Coastguard Worker                          DataType::Type packed_type,
1013*795d594fSAndroid Build Coastguard Worker                          size_t vector_length,
1014*795d594fSAndroid Build Coastguard Worker                          uint32_t dex_pc)
1015*795d594fSAndroid Build Coastguard Worker       : HVecOperation(kVecMultiplyAccumulate,
1016*795d594fSAndroid Build Coastguard Worker                       allocator,
1017*795d594fSAndroid Build Coastguard Worker                       packed_type,
1018*795d594fSAndroid Build Coastguard Worker                       SideEffects::None(),
1019*795d594fSAndroid Build Coastguard Worker                       /* number_of_inputs= */ 3,
1020*795d594fSAndroid Build Coastguard Worker                       vector_length,
1021*795d594fSAndroid Build Coastguard Worker                       dex_pc),
1022*795d594fSAndroid Build Coastguard Worker         op_kind_(op) {
1023*795d594fSAndroid Build Coastguard Worker     DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
1024*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
1025*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(mul_left, packed_type));
1026*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(mul_right, packed_type));
1027*795d594fSAndroid Build Coastguard Worker     // Remove the following if we add an architecture that supports floating point multiply-add
1028*795d594fSAndroid Build Coastguard Worker     // with Java-compatible rounding.
1029*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(packed_type));
1030*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, accumulator);
1031*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, mul_left);
1032*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(2, mul_right);
1033*795d594fSAndroid Build Coastguard Worker   }
1034*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()1035*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
1036*795d594fSAndroid Build Coastguard Worker 
InstructionDataEquals(const HInstruction * other)1037*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
1038*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsVecMultiplyAccumulate());
1039*795d594fSAndroid Build Coastguard Worker     const HVecMultiplyAccumulate* o = other->AsVecMultiplyAccumulate();
1040*795d594fSAndroid Build Coastguard Worker     return HVecOperation::InstructionDataEquals(o) && GetOpKind() == o->GetOpKind();
1041*795d594fSAndroid Build Coastguard Worker   }
1042*795d594fSAndroid Build Coastguard Worker 
GetOpKind()1043*795d594fSAndroid Build Coastguard Worker   InstructionKind GetOpKind() const { return op_kind_; }
1044*795d594fSAndroid Build Coastguard Worker 
1045*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecMultiplyAccumulate);
1046*795d594fSAndroid Build Coastguard Worker 
1047*795d594fSAndroid Build Coastguard Worker  protected:
1048*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecMultiplyAccumulate);
1049*795d594fSAndroid Build Coastguard Worker 
1050*795d594fSAndroid Build Coastguard Worker  private:
1051*795d594fSAndroid Build Coastguard Worker   // Indicates if this is a MADD or MSUB.
1052*795d594fSAndroid Build Coastguard Worker   const InstructionKind op_kind_;
1053*795d594fSAndroid Build Coastguard Worker };
1054*795d594fSAndroid Build Coastguard Worker 
1055*795d594fSAndroid Build Coastguard Worker // Takes the absolute difference of two vectors, and adds the results to
1056*795d594fSAndroid Build Coastguard Worker // same-precision or wider-precision components in the accumulator,
1057*795d594fSAndroid Build Coastguard Worker // viz. SAD([ a1, .. , am ], [ x1, .. , xn ], [ y1, .. , yn ]) =
1058*795d594fSAndroid Build Coastguard Worker //          [ a1 + sum abs(xi-yi), .. , am + sum abs(xj-yj) ],
1059*795d594fSAndroid Build Coastguard Worker //      for m <= n, non-overlapping sums, and signed operands x, y.
1060*795d594fSAndroid Build Coastguard Worker class HVecSADAccumulate final : public HVecOperation {
1061*795d594fSAndroid Build Coastguard Worker  public:
HVecSADAccumulate(ArenaAllocator * allocator,HInstruction * accumulator,HInstruction * sad_left,HInstruction * sad_right,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)1062*795d594fSAndroid Build Coastguard Worker   HVecSADAccumulate(ArenaAllocator* allocator,
1063*795d594fSAndroid Build Coastguard Worker                     HInstruction* accumulator,
1064*795d594fSAndroid Build Coastguard Worker                     HInstruction* sad_left,
1065*795d594fSAndroid Build Coastguard Worker                     HInstruction* sad_right,
1066*795d594fSAndroid Build Coastguard Worker                     DataType::Type packed_type,
1067*795d594fSAndroid Build Coastguard Worker                     size_t vector_length,
1068*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc)
1069*795d594fSAndroid Build Coastguard Worker       : HVecOperation(kVecSADAccumulate,
1070*795d594fSAndroid Build Coastguard Worker                       allocator,
1071*795d594fSAndroid Build Coastguard Worker                       packed_type,
1072*795d594fSAndroid Build Coastguard Worker                       SideEffects::None(),
1073*795d594fSAndroid Build Coastguard Worker                       /* number_of_inputs= */ 3,
1074*795d594fSAndroid Build Coastguard Worker                       vector_length,
1075*795d594fSAndroid Build Coastguard Worker                       dex_pc) {
1076*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
1077*795d594fSAndroid Build Coastguard Worker     DCHECK(sad_left->IsVecOperation());
1078*795d594fSAndroid Build Coastguard Worker     DCHECK(sad_right->IsVecOperation());
1079*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(ToSignedType(sad_left->AsVecOperation()->GetPackedType()),
1080*795d594fSAndroid Build Coastguard Worker               ToSignedType(sad_right->AsVecOperation()->GetPackedType()));
1081*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, accumulator);
1082*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, sad_left);
1083*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(2, sad_right);
1084*795d594fSAndroid Build Coastguard Worker   }
1085*795d594fSAndroid Build Coastguard Worker 
1086*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecSADAccumulate);
1087*795d594fSAndroid Build Coastguard Worker 
1088*795d594fSAndroid Build Coastguard Worker  protected:
1089*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecSADAccumulate);
1090*795d594fSAndroid Build Coastguard Worker };
1091*795d594fSAndroid Build Coastguard Worker 
1092*795d594fSAndroid Build Coastguard Worker // Performs dot product of two vectors and adds the result to wider precision components in
1093*795d594fSAndroid Build Coastguard Worker // the accumulator.
1094*795d594fSAndroid Build Coastguard Worker //
1095*795d594fSAndroid Build Coastguard Worker // viz. DOT_PRODUCT([ a1, .. , am], [ x1, .. , xn ], [ y1, .. , yn ]) =
1096*795d594fSAndroid Build Coastguard Worker //                  [ a1 + sum(xi * yi), .. , am + sum(xj * yj) ],
1097*795d594fSAndroid Build Coastguard Worker //      for m <= n, non-overlapping sums,
1098*795d594fSAndroid Build Coastguard Worker //      for either both signed or both unsigned operands x, y.
1099*795d594fSAndroid Build Coastguard Worker //
1100*795d594fSAndroid Build Coastguard Worker // Notes:
1101*795d594fSAndroid Build Coastguard Worker //   - packed type reflects the type of sum reduction, not the type of the operands.
1102*795d594fSAndroid Build Coastguard Worker //   - IsZeroExtending() is used to determine the kind of signed/zero extension to be
1103*795d594fSAndroid Build Coastguard Worker //     performed for the operands.
1104*795d594fSAndroid Build Coastguard Worker //
1105*795d594fSAndroid Build Coastguard Worker // TODO: Support types other than kInt32 for packed type.
1106*795d594fSAndroid Build Coastguard Worker class HVecDotProd final : public HVecOperation {
1107*795d594fSAndroid Build Coastguard Worker  public:
HVecDotProd(ArenaAllocator * allocator,HInstruction * accumulator,HInstruction * left,HInstruction * right,DataType::Type packed_type,bool is_zero_extending,size_t vector_length,uint32_t dex_pc)1108*795d594fSAndroid Build Coastguard Worker   HVecDotProd(ArenaAllocator* allocator,
1109*795d594fSAndroid Build Coastguard Worker               HInstruction* accumulator,
1110*795d594fSAndroid Build Coastguard Worker               HInstruction* left,
1111*795d594fSAndroid Build Coastguard Worker               HInstruction* right,
1112*795d594fSAndroid Build Coastguard Worker               DataType::Type packed_type,
1113*795d594fSAndroid Build Coastguard Worker               bool is_zero_extending,
1114*795d594fSAndroid Build Coastguard Worker               size_t vector_length,
1115*795d594fSAndroid Build Coastguard Worker               uint32_t dex_pc)
1116*795d594fSAndroid Build Coastguard Worker     : HVecOperation(kVecDotProd,
1117*795d594fSAndroid Build Coastguard Worker                     allocator,
1118*795d594fSAndroid Build Coastguard Worker                     packed_type,
1119*795d594fSAndroid Build Coastguard Worker                     SideEffects::None(),
1120*795d594fSAndroid Build Coastguard Worker                     /* number_of_inputs= */ 3,
1121*795d594fSAndroid Build Coastguard Worker                     vector_length,
1122*795d594fSAndroid Build Coastguard Worker                     dex_pc) {
1123*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
1124*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(packed_type));
1125*795d594fSAndroid Build Coastguard Worker     DCHECK(left->IsVecOperation());
1126*795d594fSAndroid Build Coastguard Worker     DCHECK(right->IsVecOperation());
1127*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(ToSignedType(left->AsVecOperation()->GetPackedType()),
1128*795d594fSAndroid Build Coastguard Worker               ToSignedType(right->AsVecOperation()->GetPackedType()));
1129*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, accumulator);
1130*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, left);
1131*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(2, right);
1132*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFieldHDotProdIsZeroExtending>(is_zero_extending);
1133*795d594fSAndroid Build Coastguard Worker   }
1134*795d594fSAndroid Build Coastguard Worker 
IsZeroExtending()1135*795d594fSAndroid Build Coastguard Worker   bool IsZeroExtending() const { return GetPackedFlag<kFieldHDotProdIsZeroExtending>(); }
1136*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()1137*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
1138*795d594fSAndroid Build Coastguard Worker 
1139*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecDotProd);
1140*795d594fSAndroid Build Coastguard Worker 
1141*795d594fSAndroid Build Coastguard Worker  protected:
1142*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecDotProd);
1143*795d594fSAndroid Build Coastguard Worker 
1144*795d594fSAndroid Build Coastguard Worker  private:
1145*795d594fSAndroid Build Coastguard Worker   // Additional packed bits.
1146*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldHDotProdIsZeroExtending =
1147*795d594fSAndroid Build Coastguard Worker       HVecOperation::kNumberOfVectorOpPackedBits;
1148*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfHDotProdPackedBits = kFieldHDotProdIsZeroExtending + 1;
1149*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfHDotProdPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
1150*795d594fSAndroid Build Coastguard Worker };
1151*795d594fSAndroid Build Coastguard Worker 
1152*795d594fSAndroid Build Coastguard Worker // Loads a vector from memory, viz. load(mem, 1)
1153*795d594fSAndroid Build Coastguard Worker // yield the vector [ mem(1), .. , mem(n) ].
1154*795d594fSAndroid Build Coastguard Worker class HVecLoad final : public HVecMemoryOperation {
1155*795d594fSAndroid Build Coastguard Worker  public:
HVecLoad(ArenaAllocator * allocator,HInstruction * base,HInstruction * index,DataType::Type packed_type,SideEffects side_effects,size_t vector_length,bool is_string_char_at,uint32_t dex_pc)1156*795d594fSAndroid Build Coastguard Worker   HVecLoad(ArenaAllocator* allocator,
1157*795d594fSAndroid Build Coastguard Worker            HInstruction* base,
1158*795d594fSAndroid Build Coastguard Worker            HInstruction* index,
1159*795d594fSAndroid Build Coastguard Worker            DataType::Type packed_type,
1160*795d594fSAndroid Build Coastguard Worker            SideEffects side_effects,
1161*795d594fSAndroid Build Coastguard Worker            size_t vector_length,
1162*795d594fSAndroid Build Coastguard Worker            bool is_string_char_at,
1163*795d594fSAndroid Build Coastguard Worker            uint32_t dex_pc)
1164*795d594fSAndroid Build Coastguard Worker       : HVecMemoryOperation(kVecLoad,
1165*795d594fSAndroid Build Coastguard Worker                             allocator,
1166*795d594fSAndroid Build Coastguard Worker                             packed_type,
1167*795d594fSAndroid Build Coastguard Worker                             side_effects,
1168*795d594fSAndroid Build Coastguard Worker                             /* number_of_inputs= */ 2,
1169*795d594fSAndroid Build Coastguard Worker                             vector_length,
1170*795d594fSAndroid Build Coastguard Worker                             dex_pc) {
1171*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, base);
1172*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, index);
1173*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFieldIsStringCharAt>(is_string_char_at);
1174*795d594fSAndroid Build Coastguard Worker   }
1175*795d594fSAndroid Build Coastguard Worker 
IsStringCharAt()1176*795d594fSAndroid Build Coastguard Worker   bool IsStringCharAt() const { return GetPackedFlag<kFieldIsStringCharAt>(); }
1177*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()1178*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
1179*795d594fSAndroid Build Coastguard Worker 
InstructionDataEquals(const HInstruction * other)1180*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
1181*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsVecLoad());
1182*795d594fSAndroid Build Coastguard Worker     const HVecLoad* o = other->AsVecLoad();
1183*795d594fSAndroid Build Coastguard Worker     return HVecMemoryOperation::InstructionDataEquals(o) && IsStringCharAt() == o->IsStringCharAt();
1184*795d594fSAndroid Build Coastguard Worker   }
1185*795d594fSAndroid Build Coastguard Worker 
1186*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecLoad);
1187*795d594fSAndroid Build Coastguard Worker 
1188*795d594fSAndroid Build Coastguard Worker  protected:
1189*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecLoad);
1190*795d594fSAndroid Build Coastguard Worker 
1191*795d594fSAndroid Build Coastguard Worker  private:
1192*795d594fSAndroid Build Coastguard Worker   // Additional packed bits.
1193*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldIsStringCharAt = HVecOperation::kNumberOfVectorOpPackedBits;
1194*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfVecLoadPackedBits = kFieldIsStringCharAt + 1;
1195*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfVecLoadPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
1196*795d594fSAndroid Build Coastguard Worker };
1197*795d594fSAndroid Build Coastguard Worker 
1198*795d594fSAndroid Build Coastguard Worker // Stores a vector to memory, viz. store(m, 1, [x1, .. , xn] )
1199*795d594fSAndroid Build Coastguard Worker // sets mem(1) = x1, .. , mem(n) = xn.
1200*795d594fSAndroid Build Coastguard Worker class HVecStore final : public HVecMemoryOperation {
1201*795d594fSAndroid Build Coastguard Worker  public:
HVecStore(ArenaAllocator * allocator,HInstruction * base,HInstruction * index,HInstruction * value,DataType::Type packed_type,SideEffects side_effects,size_t vector_length,uint32_t dex_pc)1202*795d594fSAndroid Build Coastguard Worker   HVecStore(ArenaAllocator* allocator,
1203*795d594fSAndroid Build Coastguard Worker             HInstruction* base,
1204*795d594fSAndroid Build Coastguard Worker             HInstruction* index,
1205*795d594fSAndroid Build Coastguard Worker             HInstruction* value,
1206*795d594fSAndroid Build Coastguard Worker             DataType::Type packed_type,
1207*795d594fSAndroid Build Coastguard Worker             SideEffects side_effects,
1208*795d594fSAndroid Build Coastguard Worker             size_t vector_length,
1209*795d594fSAndroid Build Coastguard Worker             uint32_t dex_pc)
1210*795d594fSAndroid Build Coastguard Worker       : HVecMemoryOperation(kVecStore,
1211*795d594fSAndroid Build Coastguard Worker                             allocator,
1212*795d594fSAndroid Build Coastguard Worker                             packed_type,
1213*795d594fSAndroid Build Coastguard Worker                             side_effects,
1214*795d594fSAndroid Build Coastguard Worker                             /* number_of_inputs= */ 3,
1215*795d594fSAndroid Build Coastguard Worker                             vector_length,
1216*795d594fSAndroid Build Coastguard Worker                             dex_pc) {
1217*795d594fSAndroid Build Coastguard Worker     DCHECK(HasConsistentPackedTypes(value, packed_type));
1218*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, base);
1219*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, index);
1220*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(2, value);
1221*795d594fSAndroid Build Coastguard Worker   }
1222*795d594fSAndroid Build Coastguard Worker 
1223*795d594fSAndroid Build Coastguard Worker   // A store needs to stay in place.
CanBeMoved()1224*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return false; }
1225*795d594fSAndroid Build Coastguard Worker 
GetValue()1226*795d594fSAndroid Build Coastguard Worker   HInstruction* GetValue() const { return InputAt(2); }
1227*795d594fSAndroid Build Coastguard Worker 
1228*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecStore);
1229*795d594fSAndroid Build Coastguard Worker 
1230*795d594fSAndroid Build Coastguard Worker  protected:
1231*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecStore)
1232*795d594fSAndroid Build Coastguard Worker };
1233*795d594fSAndroid Build Coastguard Worker 
1234*795d594fSAndroid Build Coastguard Worker //
1235*795d594fSAndroid Build Coastguard Worker // 'Predicate-setting' instructions.
1236*795d594fSAndroid Build Coastguard Worker //
1237*795d594fSAndroid Build Coastguard Worker 
1238*795d594fSAndroid Build Coastguard Worker // An abstract class for instructions for which the output value is a vector predicate -
1239*795d594fSAndroid Build Coastguard Worker // a special kind of vector value:
1240*795d594fSAndroid Build Coastguard Worker //
1241*795d594fSAndroid Build Coastguard Worker //    viz. [ p1, .. , pn ], where p_i is from { 0, 1 }.
1242*795d594fSAndroid Build Coastguard Worker //
1243*795d594fSAndroid Build Coastguard Worker // A VecOperation OP executes the same operation (e.g. ADD) on multiple elements of the vector.
1244*795d594fSAndroid Build Coastguard Worker // It can be either unpredicated (operation is done on ALL of the elements) or predicated (only
1245*795d594fSAndroid Build Coastguard Worker // on SOME elements, determined by a special extra input - vector predicate).
1246*795d594fSAndroid Build Coastguard Worker // Implementations can vary depending on the ISA; the general idea is that for each element of the
1247*795d594fSAndroid Build Coastguard Worker // regular vector a vector predicate has a corresponding element with either 0 or 1.
1248*795d594fSAndroid Build Coastguard Worker // The value determines whether a vector element will be involved in OP calculations or not
1249*795d594fSAndroid Build Coastguard Worker // (active or inactive). A vector predicate is referred as governing one if it is used to
1250*795d594fSAndroid Build Coastguard Worker // control the execution of a predicated instruction.
1251*795d594fSAndroid Build Coastguard Worker //
1252*795d594fSAndroid Build Coastguard Worker // Note: vector predicate value type is introduced alongside existing vectors of booleans and
1253*795d594fSAndroid Build Coastguard Worker // vectors of bytes to reflect their special semantics.
1254*795d594fSAndroid Build Coastguard Worker //
1255*795d594fSAndroid Build Coastguard Worker // TODO: we could introduce SIMD types in HIR.
1256*795d594fSAndroid Build Coastguard Worker class HVecPredSetOperation : public HVecOperation {
1257*795d594fSAndroid Build Coastguard Worker  public:
1258*795d594fSAndroid Build Coastguard Worker   // A vector predicate-setting operation looks like a Int64 location.
1259*795d594fSAndroid Build Coastguard Worker   // TODO: we could introduce vector types in HIR.
1260*795d594fSAndroid Build Coastguard Worker   static constexpr DataType::Type kSIMDPredType = DataType::Type::kInt64;
1261*795d594fSAndroid Build Coastguard Worker 
HVecPredSetOperation(InstructionKind kind,ArenaAllocator * allocator,DataType::Type packed_type,SideEffects side_effects,size_t number_of_inputs,size_t vector_length,uint32_t dex_pc)1262*795d594fSAndroid Build Coastguard Worker   HVecPredSetOperation(InstructionKind kind,
1263*795d594fSAndroid Build Coastguard Worker                        ArenaAllocator* allocator,
1264*795d594fSAndroid Build Coastguard Worker                        DataType::Type packed_type,
1265*795d594fSAndroid Build Coastguard Worker                        SideEffects side_effects,
1266*795d594fSAndroid Build Coastguard Worker                        size_t number_of_inputs,
1267*795d594fSAndroid Build Coastguard Worker                        size_t vector_length,
1268*795d594fSAndroid Build Coastguard Worker                        uint32_t dex_pc)
1269*795d594fSAndroid Build Coastguard Worker       : HVecOperation(kind,
1270*795d594fSAndroid Build Coastguard Worker                       allocator,
1271*795d594fSAndroid Build Coastguard Worker                       packed_type,
1272*795d594fSAndroid Build Coastguard Worker                       side_effects,
1273*795d594fSAndroid Build Coastguard Worker                       number_of_inputs,
1274*795d594fSAndroid Build Coastguard Worker                       vector_length,
1275*795d594fSAndroid Build Coastguard Worker                       dex_pc) {
1276*795d594fSAndroid Build Coastguard Worker     // Overrides the kSIMDType set by the VecOperation constructor.
1277*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeField>(kSIMDPredType);
1278*795d594fSAndroid Build Coastguard Worker   }
1279*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()1280*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
1281*795d594fSAndroid Build Coastguard Worker 
1282*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(VecPredSetOperation);
1283*795d594fSAndroid Build Coastguard Worker 
1284*795d594fSAndroid Build Coastguard Worker  protected:
1285*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecPredSetOperation);
1286*795d594fSAndroid Build Coastguard Worker };
1287*795d594fSAndroid Build Coastguard Worker 
1288*795d594fSAndroid Build Coastguard Worker // Sets all the vector predicate elements as active or inactive.
1289*795d594fSAndroid Build Coastguard Worker //
1290*795d594fSAndroid Build Coastguard Worker // viz. [ p1, .. , pn ]  = [ val, .. , val ] where val is from { 1, 0 }.
1291*795d594fSAndroid Build Coastguard Worker class HVecPredSetAll final : public HVecPredSetOperation {
1292*795d594fSAndroid Build Coastguard Worker  public:
HVecPredSetAll(ArenaAllocator * allocator,HInstruction * input,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)1293*795d594fSAndroid Build Coastguard Worker   HVecPredSetAll(ArenaAllocator* allocator,
1294*795d594fSAndroid Build Coastguard Worker                  HInstruction* input,
1295*795d594fSAndroid Build Coastguard Worker                  DataType::Type packed_type,
1296*795d594fSAndroid Build Coastguard Worker                  size_t vector_length,
1297*795d594fSAndroid Build Coastguard Worker                  uint32_t dex_pc) :
1298*795d594fSAndroid Build Coastguard Worker       HVecPredSetOperation(kVecPredSetAll,
1299*795d594fSAndroid Build Coastguard Worker                            allocator,
1300*795d594fSAndroid Build Coastguard Worker                            packed_type,
1301*795d594fSAndroid Build Coastguard Worker                            SideEffects::None(),
1302*795d594fSAndroid Build Coastguard Worker                            /* number_of_inputs= */ 1,
1303*795d594fSAndroid Build Coastguard Worker                            vector_length,
1304*795d594fSAndroid Build Coastguard Worker                            dex_pc) {
1305*795d594fSAndroid Build Coastguard Worker     DCHECK(input->IsIntConstant());
1306*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, input);
1307*795d594fSAndroid Build Coastguard Worker     MarkEmittedAtUseSite();
1308*795d594fSAndroid Build Coastguard Worker   }
1309*795d594fSAndroid Build Coastguard Worker 
1310*795d594fSAndroid Build Coastguard Worker   // Having governing predicate doesn't make sense for set all TRUE/FALSE instruction.
MustBePredicatedInPredicatedSIMDMode()1311*795d594fSAndroid Build Coastguard Worker   bool MustBePredicatedInPredicatedSIMDMode() override { return false; }
1312*795d594fSAndroid Build Coastguard Worker 
IsSetTrue()1313*795d594fSAndroid Build Coastguard Worker   bool IsSetTrue() const { return InputAt(0)->AsIntConstant()->IsTrue(); }
1314*795d594fSAndroid Build Coastguard Worker 
1315*795d594fSAndroid Build Coastguard Worker   // Vector predicates are not kept alive across vector loop boundaries.
CanBeMoved()1316*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return false; }
1317*795d594fSAndroid Build Coastguard Worker 
1318*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecPredSetAll);
1319*795d594fSAndroid Build Coastguard Worker 
1320*795d594fSAndroid Build Coastguard Worker  protected:
1321*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecPredSetAll);
1322*795d594fSAndroid Build Coastguard Worker };
1323*795d594fSAndroid Build Coastguard Worker 
1324*795d594fSAndroid Build Coastguard Worker //
1325*795d594fSAndroid Build Coastguard Worker // Arm64 SVE-specific instructions.
1326*795d594fSAndroid Build Coastguard Worker //
1327*795d594fSAndroid Build Coastguard Worker // Classes of instructions which are specific to Arm64 SVE (though could be adopted
1328*795d594fSAndroid Build Coastguard Worker // by other targets, possibly being lowered to a number of ISA instructions) and
1329*795d594fSAndroid Build Coastguard Worker // implement SIMD loop predicated execution idiom.
1330*795d594fSAndroid Build Coastguard Worker //
1331*795d594fSAndroid Build Coastguard Worker 
1332*795d594fSAndroid Build Coastguard Worker // Takes two scalar values x and y, creates a vector S: s(n) = x + n, compares (OP) each s(n)
1333*795d594fSAndroid Build Coastguard Worker // with y and set the corresponding element of the predicate register to the result of the
1334*795d594fSAndroid Build Coastguard Worker // comparison.
1335*795d594fSAndroid Build Coastguard Worker //
1336*795d594fSAndroid Build Coastguard Worker // viz. [ p1, .. , pn ]  = [ x OP y , (x + 1) OP y, .. , (x + n) OP y ] where OP is CondKind
1337*795d594fSAndroid Build Coastguard Worker // condition.
1338*795d594fSAndroid Build Coastguard Worker class HVecPredWhile final : public HVecPredSetOperation {
1339*795d594fSAndroid Build Coastguard Worker  public:
1340*795d594fSAndroid Build Coastguard Worker   enum class CondKind {
1341*795d594fSAndroid Build Coastguard Worker     kLE,   // signed less than or equal.
1342*795d594fSAndroid Build Coastguard Worker     kLO,   // unsigned lower.
1343*795d594fSAndroid Build Coastguard Worker     kLS,   // unsigned lower or same.
1344*795d594fSAndroid Build Coastguard Worker     kLT,   // signed less.
1345*795d594fSAndroid Build Coastguard Worker     kLast = kLT,
1346*795d594fSAndroid Build Coastguard Worker   };
1347*795d594fSAndroid Build Coastguard Worker 
HVecPredWhile(ArenaAllocator * allocator,HInstruction * left,HInstruction * right,CondKind cond,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)1348*795d594fSAndroid Build Coastguard Worker   HVecPredWhile(ArenaAllocator* allocator,
1349*795d594fSAndroid Build Coastguard Worker                 HInstruction* left,
1350*795d594fSAndroid Build Coastguard Worker                 HInstruction* right,
1351*795d594fSAndroid Build Coastguard Worker                 CondKind cond,
1352*795d594fSAndroid Build Coastguard Worker                 DataType::Type packed_type,
1353*795d594fSAndroid Build Coastguard Worker                 size_t vector_length,
1354*795d594fSAndroid Build Coastguard Worker                 uint32_t dex_pc) :
1355*795d594fSAndroid Build Coastguard Worker       HVecPredSetOperation(kVecPredWhile,
1356*795d594fSAndroid Build Coastguard Worker                            allocator,
1357*795d594fSAndroid Build Coastguard Worker                            packed_type,
1358*795d594fSAndroid Build Coastguard Worker                            SideEffects::None(),
1359*795d594fSAndroid Build Coastguard Worker                            /* number_of_inputs= */ 2,
1360*795d594fSAndroid Build Coastguard Worker                            vector_length,
1361*795d594fSAndroid Build Coastguard Worker                            dex_pc) {
1362*795d594fSAndroid Build Coastguard Worker     DCHECK(!left->IsVecOperation());
1363*795d594fSAndroid Build Coastguard Worker     DCHECK(!left->IsVecPredSetOperation());
1364*795d594fSAndroid Build Coastguard Worker     DCHECK(!right->IsVecOperation());
1365*795d594fSAndroid Build Coastguard Worker     DCHECK(!right->IsVecPredSetOperation());
1366*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(left->GetType()));
1367*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(right->GetType()));
1368*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, left);
1369*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, right);
1370*795d594fSAndroid Build Coastguard Worker     SetPackedField<CondKindField>(cond);
1371*795d594fSAndroid Build Coastguard Worker   }
1372*795d594fSAndroid Build Coastguard Worker 
1373*795d594fSAndroid Build Coastguard Worker   // This is a special loop control instruction which must not be predicated.
MustBePredicatedInPredicatedSIMDMode()1374*795d594fSAndroid Build Coastguard Worker   bool MustBePredicatedInPredicatedSIMDMode() override { return false; }
1375*795d594fSAndroid Build Coastguard Worker 
GetCondKind()1376*795d594fSAndroid Build Coastguard Worker   CondKind GetCondKind() const {
1377*795d594fSAndroid Build Coastguard Worker     return GetPackedField<CondKindField>();
1378*795d594fSAndroid Build Coastguard Worker   }
1379*795d594fSAndroid Build Coastguard Worker 
1380*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecPredWhile);
1381*795d594fSAndroid Build Coastguard Worker 
1382*795d594fSAndroid Build Coastguard Worker  protected:
1383*795d594fSAndroid Build Coastguard Worker   // Additional packed bits.
1384*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kCondKind = HVecOperation::kNumberOfVectorOpPackedBits;
1385*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kCondKindSize =
1386*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(CondKind::kLast));
1387*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfVecPredWhilePackedBits = kCondKind + kCondKindSize;
1388*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfVecPredWhilePackedBits <= kMaxNumberOfPackedBits,
1389*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
1390*795d594fSAndroid Build Coastguard Worker   using CondKindField = BitField<CondKind, kCondKind, kCondKindSize>;
1391*795d594fSAndroid Build Coastguard Worker 
1392*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecPredWhile);
1393*795d594fSAndroid Build Coastguard Worker };
1394*795d594fSAndroid Build Coastguard Worker 
1395*795d594fSAndroid Build Coastguard Worker // Evaluates the predicate condition (PCondKind) for a vector predicate; outputs
1396*795d594fSAndroid Build Coastguard Worker // a scalar boolean value result.
1397*795d594fSAndroid Build Coastguard Worker //
1398*795d594fSAndroid Build Coastguard Worker // Note: as VecPredToBoolean can be also predicated, only active elements (determined by the
1399*795d594fSAndroid Build Coastguard Worker // instruction's governing predicate) of the input vector predicate are used for condition
1400*795d594fSAndroid Build Coastguard Worker // evaluation.
1401*795d594fSAndroid Build Coastguard Worker //
1402*795d594fSAndroid Build Coastguard Worker // Note: this instruction is currently used as a workaround for the fact that IR instructions
1403*795d594fSAndroid Build Coastguard Worker // can't have more than one output.
1404*795d594fSAndroid Build Coastguard Worker class HVecPredToBoolean final : public HVecOperation {
1405*795d594fSAndroid Build Coastguard Worker  public:
1406*795d594fSAndroid Build Coastguard Worker   // To get more info on the condition kinds please see "2.2 Process state, PSTATE" section of
1407*795d594fSAndroid Build Coastguard Worker   // "ARM Architecture Reference Manual Supplement. The Scalable Vector Extension (SVE),
1408*795d594fSAndroid Build Coastguard Worker   // for ARMv8-A".
1409*795d594fSAndroid Build Coastguard Worker   enum class PCondKind {
1410*795d594fSAndroid Build Coastguard Worker     kNone,    // No active elements were TRUE.
1411*795d594fSAndroid Build Coastguard Worker     kAny,     // An active element was TRUE.
1412*795d594fSAndroid Build Coastguard Worker     kNLast,   // The last active element was not TRUE.
1413*795d594fSAndroid Build Coastguard Worker     kLast,    // The last active element was TRUE.
1414*795d594fSAndroid Build Coastguard Worker     kFirst,   // The first active element was TRUE.
1415*795d594fSAndroid Build Coastguard Worker     kNFirst,  // The first active element was not TRUE.
1416*795d594fSAndroid Build Coastguard Worker     kPMore,   // An active element was TRUE but not the last active element.
1417*795d594fSAndroid Build Coastguard Worker     kPLast,   // The last active element was TRUE or no active elements were TRUE.
1418*795d594fSAndroid Build Coastguard Worker     kEnumLast = kPLast
1419*795d594fSAndroid Build Coastguard Worker   };
1420*795d594fSAndroid Build Coastguard Worker 
HVecPredToBoolean(ArenaAllocator * allocator,HInstruction * input,PCondKind pred_cond,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)1421*795d594fSAndroid Build Coastguard Worker   HVecPredToBoolean(ArenaAllocator* allocator,
1422*795d594fSAndroid Build Coastguard Worker                     HInstruction* input,
1423*795d594fSAndroid Build Coastguard Worker                     PCondKind pred_cond,
1424*795d594fSAndroid Build Coastguard Worker                     DataType::Type packed_type,
1425*795d594fSAndroid Build Coastguard Worker                     size_t vector_length,
1426*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc)
1427*795d594fSAndroid Build Coastguard Worker       : HVecOperation(kVecPredToBoolean,
1428*795d594fSAndroid Build Coastguard Worker                       allocator,
1429*795d594fSAndroid Build Coastguard Worker                       packed_type,
1430*795d594fSAndroid Build Coastguard Worker                       SideEffects::None(),
1431*795d594fSAndroid Build Coastguard Worker                       /* number_of_inputs */ 1,
1432*795d594fSAndroid Build Coastguard Worker                       vector_length,
1433*795d594fSAndroid Build Coastguard Worker                       dex_pc) {
1434*795d594fSAndroid Build Coastguard Worker     DCHECK(input->IsVecPredSetOperation());
1435*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, input);
1436*795d594fSAndroid Build Coastguard Worker     // Overrides the kSIMDType set by the VecOperation constructor.
1437*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeField>(DataType::Type::kBool);
1438*795d594fSAndroid Build Coastguard Worker     SetPackedField<CondKindField>(pred_cond);
1439*795d594fSAndroid Build Coastguard Worker   }
1440*795d594fSAndroid Build Coastguard Worker 
1441*795d594fSAndroid Build Coastguard Worker   // This instruction is currently used only as a special loop control instruction
1442*795d594fSAndroid Build Coastguard Worker   // which must not be predicated.
1443*795d594fSAndroid Build Coastguard Worker   // TODO: Remove the constraint.
MustBePredicatedInPredicatedSIMDMode()1444*795d594fSAndroid Build Coastguard Worker   bool MustBePredicatedInPredicatedSIMDMode() override { return false; }
1445*795d594fSAndroid Build Coastguard Worker 
GetPCondKind()1446*795d594fSAndroid Build Coastguard Worker   PCondKind GetPCondKind() const {
1447*795d594fSAndroid Build Coastguard Worker     return GetPackedField<CondKindField>();
1448*795d594fSAndroid Build Coastguard Worker   }
1449*795d594fSAndroid Build Coastguard Worker 
1450*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecPredToBoolean);
1451*795d594fSAndroid Build Coastguard Worker 
1452*795d594fSAndroid Build Coastguard Worker  protected:
1453*795d594fSAndroid Build Coastguard Worker   // Additional packed bits.
1454*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kCondKind = HVecOperation::kNumberOfVectorOpPackedBits;
1455*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kCondKindSize =
1456*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(PCondKind::kEnumLast));
1457*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfVecPredToBooleanPackedBits = kCondKind + kCondKindSize;
1458*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfVecPredToBooleanPackedBits <= kMaxNumberOfPackedBits,
1459*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
1460*795d594fSAndroid Build Coastguard Worker   using CondKindField = BitField<PCondKind, kCondKind, kCondKindSize>;
1461*795d594fSAndroid Build Coastguard Worker 
1462*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecPredToBoolean);
1463*795d594fSAndroid Build Coastguard Worker };
1464*795d594fSAndroid Build Coastguard Worker 
1465*795d594fSAndroid Build Coastguard Worker // Evaluates condition for pairwise elements in two input vectors and sets the result
1466*795d594fSAndroid Build Coastguard Worker // as an output predicate vector.
1467*795d594fSAndroid Build Coastguard Worker //
1468*795d594fSAndroid Build Coastguard Worker // viz. [ p1, .. , pn ]  = [ x1 OP y1 , x2 OP y2, .. , xn OP yn] where OP is CondKind
1469*795d594fSAndroid Build Coastguard Worker // condition.
1470*795d594fSAndroid Build Coastguard Worker class HVecCondition : public HVecPredSetOperation {
1471*795d594fSAndroid Build Coastguard Worker  public:
1472*795d594fSAndroid Build Coastguard Worker   HVecCondition(InstructionKind kind,
1473*795d594fSAndroid Build Coastguard Worker                 ArenaAllocator* allocator,
1474*795d594fSAndroid Build Coastguard Worker                 HInstruction* left,
1475*795d594fSAndroid Build Coastguard Worker                 HInstruction* right,
1476*795d594fSAndroid Build Coastguard Worker                 DataType::Type packed_type,
1477*795d594fSAndroid Build Coastguard Worker                 size_t vector_length,
1478*795d594fSAndroid Build Coastguard Worker                 uint32_t dex_pc = kNoDexPc) :
1479*795d594fSAndroid Build Coastguard Worker       HVecPredSetOperation(kind,
1480*795d594fSAndroid Build Coastguard Worker                            allocator,
1481*795d594fSAndroid Build Coastguard Worker                            packed_type,
1482*795d594fSAndroid Build Coastguard Worker                            SideEffects::None(),
1483*795d594fSAndroid Build Coastguard Worker                            /* number_of_inputs= */ 2,
1484*795d594fSAndroid Build Coastguard Worker                            vector_length,
1485*795d594fSAndroid Build Coastguard Worker                            dex_pc) {
1486*795d594fSAndroid Build Coastguard Worker     DCHECK(left->IsVecOperation());
1487*795d594fSAndroid Build Coastguard Worker     DCHECK(!left->IsVecPredSetOperation());
1488*795d594fSAndroid Build Coastguard Worker     DCHECK(right->IsVecOperation());
1489*795d594fSAndroid Build Coastguard Worker     DCHECK(!right->IsVecPredSetOperation());
1490*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, left);
1491*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, right);
1492*795d594fSAndroid Build Coastguard Worker   }
1493*795d594fSAndroid Build Coastguard Worker 
1494*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(VecCondition);
1495*795d594fSAndroid Build Coastguard Worker 
1496*795d594fSAndroid Build Coastguard Worker   virtual IfCondition GetCondition() const = 0;
1497*795d594fSAndroid Build Coastguard Worker 
1498*795d594fSAndroid Build Coastguard Worker   static HVecCondition* Create(HGraph* graph,
1499*795d594fSAndroid Build Coastguard Worker                                IfCondition cond,
1500*795d594fSAndroid Build Coastguard Worker                                HInstruction* lhs,
1501*795d594fSAndroid Build Coastguard Worker                                HInstruction* rhs,
1502*795d594fSAndroid Build Coastguard Worker                                DataType::Type packed_type,
1503*795d594fSAndroid Build Coastguard Worker                                size_t vector_length,
1504*795d594fSAndroid Build Coastguard Worker                                uint32_t dex_pc = kNoDexPc);
1505*795d594fSAndroid Build Coastguard Worker 
1506*795d594fSAndroid Build Coastguard Worker  protected:
1507*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecCondition);
1508*795d594fSAndroid Build Coastguard Worker };
1509*795d594fSAndroid Build Coastguard Worker 
1510*795d594fSAndroid Build Coastguard Worker // Instruction to check if two vector inputs are equal to each other.
1511*795d594fSAndroid Build Coastguard Worker class HVecEqual final : public HVecCondition {
1512*795d594fSAndroid Build Coastguard Worker  public:
1513*795d594fSAndroid Build Coastguard Worker   HVecEqual(ArenaAllocator* allocator,
1514*795d594fSAndroid Build Coastguard Worker             HInstruction* left,
1515*795d594fSAndroid Build Coastguard Worker             HInstruction* right,
1516*795d594fSAndroid Build Coastguard Worker             DataType::Type packed_type,
1517*795d594fSAndroid Build Coastguard Worker             size_t vector_length,
1518*795d594fSAndroid Build Coastguard Worker             uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecEqual,allocator,left,right,packed_type,vector_length,dex_pc)1519*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecEqual, allocator, left, right, packed_type, vector_length, dex_pc) {}
1520*795d594fSAndroid Build Coastguard Worker 
1521*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecEqual);
1522*795d594fSAndroid Build Coastguard Worker 
GetCondition()1523*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1524*795d594fSAndroid Build Coastguard Worker     return kCondEQ;
1525*795d594fSAndroid Build Coastguard Worker   }
1526*795d594fSAndroid Build Coastguard Worker 
1527*795d594fSAndroid Build Coastguard Worker  protected:
1528*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecEqual);
1529*795d594fSAndroid Build Coastguard Worker };
1530*795d594fSAndroid Build Coastguard Worker 
1531*795d594fSAndroid Build Coastguard Worker // Instruction to check if two vector inputs are not equal to each other.
1532*795d594fSAndroid Build Coastguard Worker class HVecNotEqual final : public HVecCondition {
1533*795d594fSAndroid Build Coastguard Worker  public:
1534*795d594fSAndroid Build Coastguard Worker   HVecNotEqual(ArenaAllocator* allocator,
1535*795d594fSAndroid Build Coastguard Worker                HInstruction* left,
1536*795d594fSAndroid Build Coastguard Worker                HInstruction* right,
1537*795d594fSAndroid Build Coastguard Worker                DataType::Type packed_type,
1538*795d594fSAndroid Build Coastguard Worker                size_t vector_length,
1539*795d594fSAndroid Build Coastguard Worker                uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecNotEqual,allocator,left,right,packed_type,vector_length,dex_pc)1540*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecNotEqual, allocator, left, right, packed_type, vector_length, dex_pc) {}
1541*795d594fSAndroid Build Coastguard Worker 
1542*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecNotEqual);
1543*795d594fSAndroid Build Coastguard Worker 
GetCondition()1544*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1545*795d594fSAndroid Build Coastguard Worker     return kCondNE;
1546*795d594fSAndroid Build Coastguard Worker   }
1547*795d594fSAndroid Build Coastguard Worker 
1548*795d594fSAndroid Build Coastguard Worker  protected:
1549*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecNotEqual);
1550*795d594fSAndroid Build Coastguard Worker };
1551*795d594fSAndroid Build Coastguard Worker 
1552*795d594fSAndroid Build Coastguard Worker // Instruction to check if one vector input is less than the other.
1553*795d594fSAndroid Build Coastguard Worker class HVecLessThan final : public HVecCondition {
1554*795d594fSAndroid Build Coastguard Worker  public:
1555*795d594fSAndroid Build Coastguard Worker   HVecLessThan(ArenaAllocator* allocator,
1556*795d594fSAndroid Build Coastguard Worker                HInstruction* left,
1557*795d594fSAndroid Build Coastguard Worker                HInstruction* right,
1558*795d594fSAndroid Build Coastguard Worker                DataType::Type packed_type,
1559*795d594fSAndroid Build Coastguard Worker                size_t vector_length,
1560*795d594fSAndroid Build Coastguard Worker                uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecLessThan,allocator,left,right,packed_type,vector_length,dex_pc)1561*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecLessThan, allocator, left, right, packed_type, vector_length, dex_pc) {}
1562*795d594fSAndroid Build Coastguard Worker 
1563*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecLessThan);
1564*795d594fSAndroid Build Coastguard Worker 
GetCondition()1565*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1566*795d594fSAndroid Build Coastguard Worker     return kCondLT;
1567*795d594fSAndroid Build Coastguard Worker   }
1568*795d594fSAndroid Build Coastguard Worker 
1569*795d594fSAndroid Build Coastguard Worker  protected:
1570*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecLessThan);
1571*795d594fSAndroid Build Coastguard Worker };
1572*795d594fSAndroid Build Coastguard Worker 
1573*795d594fSAndroid Build Coastguard Worker // Instruction to check if one vector input is less than or equal to the other.
1574*795d594fSAndroid Build Coastguard Worker class HVecLessThanOrEqual final : public HVecCondition {
1575*795d594fSAndroid Build Coastguard Worker  public:
1576*795d594fSAndroid Build Coastguard Worker   HVecLessThanOrEqual(ArenaAllocator* allocator,
1577*795d594fSAndroid Build Coastguard Worker                       HInstruction* left,
1578*795d594fSAndroid Build Coastguard Worker                       HInstruction* right,
1579*795d594fSAndroid Build Coastguard Worker                       DataType::Type packed_type,
1580*795d594fSAndroid Build Coastguard Worker                       size_t vector_length,
1581*795d594fSAndroid Build Coastguard Worker                       uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecLessThanOrEqual,allocator,left,right,packed_type,vector_length,dex_pc)1582*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecLessThanOrEqual,
1583*795d594fSAndroid Build Coastguard Worker                       allocator,
1584*795d594fSAndroid Build Coastguard Worker                       left,
1585*795d594fSAndroid Build Coastguard Worker                       right,
1586*795d594fSAndroid Build Coastguard Worker                       packed_type,
1587*795d594fSAndroid Build Coastguard Worker                       vector_length,
1588*795d594fSAndroid Build Coastguard Worker                       dex_pc) {}
1589*795d594fSAndroid Build Coastguard Worker 
1590*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecLessThanOrEqual);
1591*795d594fSAndroid Build Coastguard Worker 
GetCondition()1592*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1593*795d594fSAndroid Build Coastguard Worker     return kCondLE;
1594*795d594fSAndroid Build Coastguard Worker   }
1595*795d594fSAndroid Build Coastguard Worker 
1596*795d594fSAndroid Build Coastguard Worker  protected:
1597*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecLessThanOrEqual);
1598*795d594fSAndroid Build Coastguard Worker };
1599*795d594fSAndroid Build Coastguard Worker 
1600*795d594fSAndroid Build Coastguard Worker // Instruction to check if one vector input is greater than the other.
1601*795d594fSAndroid Build Coastguard Worker class HVecGreaterThan final : public HVecCondition {
1602*795d594fSAndroid Build Coastguard Worker  public:
1603*795d594fSAndroid Build Coastguard Worker   HVecGreaterThan(ArenaAllocator* allocator,
1604*795d594fSAndroid Build Coastguard Worker                   HInstruction* left,
1605*795d594fSAndroid Build Coastguard Worker                   HInstruction* right,
1606*795d594fSAndroid Build Coastguard Worker                   DataType::Type packed_type,
1607*795d594fSAndroid Build Coastguard Worker                   size_t vector_length,
1608*795d594fSAndroid Build Coastguard Worker                   uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecGreaterThan,allocator,left,right,packed_type,vector_length,dex_pc)1609*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecGreaterThan,
1610*795d594fSAndroid Build Coastguard Worker                       allocator,
1611*795d594fSAndroid Build Coastguard Worker                       left,
1612*795d594fSAndroid Build Coastguard Worker                       right,
1613*795d594fSAndroid Build Coastguard Worker                       packed_type,
1614*795d594fSAndroid Build Coastguard Worker                       vector_length,
1615*795d594fSAndroid Build Coastguard Worker                       dex_pc) {}
1616*795d594fSAndroid Build Coastguard Worker 
1617*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecGreaterThan);
1618*795d594fSAndroid Build Coastguard Worker 
GetCondition()1619*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1620*795d594fSAndroid Build Coastguard Worker     return kCondGT;
1621*795d594fSAndroid Build Coastguard Worker   }
1622*795d594fSAndroid Build Coastguard Worker 
1623*795d594fSAndroid Build Coastguard Worker  protected:
1624*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecGreaterThan);
1625*795d594fSAndroid Build Coastguard Worker };
1626*795d594fSAndroid Build Coastguard Worker 
1627*795d594fSAndroid Build Coastguard Worker // Instruction to check if one vector input is greater than or equal to the other.
1628*795d594fSAndroid Build Coastguard Worker class HVecGreaterThanOrEqual final : public HVecCondition {
1629*795d594fSAndroid Build Coastguard Worker  public:
1630*795d594fSAndroid Build Coastguard Worker   HVecGreaterThanOrEqual(ArenaAllocator* allocator,
1631*795d594fSAndroid Build Coastguard Worker                          HInstruction* left,
1632*795d594fSAndroid Build Coastguard Worker                          HInstruction* right,
1633*795d594fSAndroid Build Coastguard Worker                          DataType::Type packed_type,
1634*795d594fSAndroid Build Coastguard Worker                          size_t vector_length,
1635*795d594fSAndroid Build Coastguard Worker                          uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecGreaterThanOrEqual,allocator,left,right,packed_type,vector_length,dex_pc)1636*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecGreaterThanOrEqual,
1637*795d594fSAndroid Build Coastguard Worker                       allocator,
1638*795d594fSAndroid Build Coastguard Worker                       left,
1639*795d594fSAndroid Build Coastguard Worker                       right,
1640*795d594fSAndroid Build Coastguard Worker                       packed_type,
1641*795d594fSAndroid Build Coastguard Worker                       vector_length,
1642*795d594fSAndroid Build Coastguard Worker                       dex_pc) {}
1643*795d594fSAndroid Build Coastguard Worker 
1644*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecGreaterThanOrEqual);
1645*795d594fSAndroid Build Coastguard Worker 
GetCondition()1646*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1647*795d594fSAndroid Build Coastguard Worker     return kCondGE;
1648*795d594fSAndroid Build Coastguard Worker   }
1649*795d594fSAndroid Build Coastguard Worker 
1650*795d594fSAndroid Build Coastguard Worker  protected:
1651*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecGreaterThanOrEqual);
1652*795d594fSAndroid Build Coastguard Worker };
1653*795d594fSAndroid Build Coastguard Worker 
1654*795d594fSAndroid Build Coastguard Worker // Instruction to check if one unsigned vector input is less than the other, using unsigned
1655*795d594fSAndroid Build Coastguard Worker // comparison.
1656*795d594fSAndroid Build Coastguard Worker class HVecBelow final : public HVecCondition {
1657*795d594fSAndroid Build Coastguard Worker  public:
1658*795d594fSAndroid Build Coastguard Worker   HVecBelow(ArenaAllocator* allocator,
1659*795d594fSAndroid Build Coastguard Worker             HInstruction* left,
1660*795d594fSAndroid Build Coastguard Worker             HInstruction* right,
1661*795d594fSAndroid Build Coastguard Worker             DataType::Type packed_type,
1662*795d594fSAndroid Build Coastguard Worker             size_t vector_length,
1663*795d594fSAndroid Build Coastguard Worker             uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecBelow,allocator,left,right,packed_type,vector_length,dex_pc)1664*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecBelow, allocator, left, right, packed_type, vector_length, dex_pc) {}
1665*795d594fSAndroid Build Coastguard Worker 
1666*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecBelow);
1667*795d594fSAndroid Build Coastguard Worker 
GetCondition()1668*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1669*795d594fSAndroid Build Coastguard Worker     return kCondB;
1670*795d594fSAndroid Build Coastguard Worker   }
1671*795d594fSAndroid Build Coastguard Worker 
1672*795d594fSAndroid Build Coastguard Worker  protected:
1673*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecBelow);
1674*795d594fSAndroid Build Coastguard Worker };
1675*795d594fSAndroid Build Coastguard Worker 
1676*795d594fSAndroid Build Coastguard Worker // Instruction to check if one unsigned vector input is less than or equal to the other, using
1677*795d594fSAndroid Build Coastguard Worker // unsigned comparison.
1678*795d594fSAndroid Build Coastguard Worker class HVecBelowOrEqual final : public HVecCondition {
1679*795d594fSAndroid Build Coastguard Worker  public:
1680*795d594fSAndroid Build Coastguard Worker   HVecBelowOrEqual(ArenaAllocator* allocator,
1681*795d594fSAndroid Build Coastguard Worker                    HInstruction* left,
1682*795d594fSAndroid Build Coastguard Worker                    HInstruction* right,
1683*795d594fSAndroid Build Coastguard Worker                    DataType::Type packed_type,
1684*795d594fSAndroid Build Coastguard Worker                    size_t vector_length,
1685*795d594fSAndroid Build Coastguard Worker                    uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecBelowOrEqual,allocator,left,right,packed_type,vector_length,dex_pc)1686*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecBelowOrEqual,
1687*795d594fSAndroid Build Coastguard Worker                       allocator,
1688*795d594fSAndroid Build Coastguard Worker                       left,
1689*795d594fSAndroid Build Coastguard Worker                       right,
1690*795d594fSAndroid Build Coastguard Worker                       packed_type,
1691*795d594fSAndroid Build Coastguard Worker                       vector_length,
1692*795d594fSAndroid Build Coastguard Worker                       dex_pc) {}
1693*795d594fSAndroid Build Coastguard Worker 
1694*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecBelowOrEqual);
1695*795d594fSAndroid Build Coastguard Worker 
GetCondition()1696*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1697*795d594fSAndroid Build Coastguard Worker     return kCondBE;
1698*795d594fSAndroid Build Coastguard Worker   }
1699*795d594fSAndroid Build Coastguard Worker 
1700*795d594fSAndroid Build Coastguard Worker  protected:
1701*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecBelowOrEqual);
1702*795d594fSAndroid Build Coastguard Worker };
1703*795d594fSAndroid Build Coastguard Worker 
1704*795d594fSAndroid Build Coastguard Worker // Instruction to check if one unsigned vector input is greater than the other, using unsigned
1705*795d594fSAndroid Build Coastguard Worker // comparison.
1706*795d594fSAndroid Build Coastguard Worker class HVecAbove final : public HVecCondition {
1707*795d594fSAndroid Build Coastguard Worker  public:
1708*795d594fSAndroid Build Coastguard Worker   HVecAbove(ArenaAllocator* allocator,
1709*795d594fSAndroid Build Coastguard Worker             HInstruction* left,
1710*795d594fSAndroid Build Coastguard Worker             HInstruction* right,
1711*795d594fSAndroid Build Coastguard Worker             DataType::Type packed_type,
1712*795d594fSAndroid Build Coastguard Worker             size_t vector_length,
1713*795d594fSAndroid Build Coastguard Worker             uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecAbove,allocator,left,right,packed_type,vector_length,dex_pc)1714*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecAbove, allocator, left, right, packed_type, vector_length, dex_pc) {}
1715*795d594fSAndroid Build Coastguard Worker 
1716*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecAbove);
1717*795d594fSAndroid Build Coastguard Worker 
GetCondition()1718*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1719*795d594fSAndroid Build Coastguard Worker     return kCondA;
1720*795d594fSAndroid Build Coastguard Worker   }
1721*795d594fSAndroid Build Coastguard Worker 
1722*795d594fSAndroid Build Coastguard Worker  protected:
1723*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecAbove);
1724*795d594fSAndroid Build Coastguard Worker };
1725*795d594fSAndroid Build Coastguard Worker 
1726*795d594fSAndroid Build Coastguard Worker // Instruction to check if one unsigned vector input is greater than or equal to the other, using
1727*795d594fSAndroid Build Coastguard Worker // unsigned comparison.
1728*795d594fSAndroid Build Coastguard Worker class HVecAboveOrEqual final : public HVecCondition {
1729*795d594fSAndroid Build Coastguard Worker  public:
1730*795d594fSAndroid Build Coastguard Worker   HVecAboveOrEqual(ArenaAllocator* allocator,
1731*795d594fSAndroid Build Coastguard Worker                    HInstruction* left,
1732*795d594fSAndroid Build Coastguard Worker                    HInstruction* right,
1733*795d594fSAndroid Build Coastguard Worker                    DataType::Type packed_type,
1734*795d594fSAndroid Build Coastguard Worker                    size_t vector_length,
1735*795d594fSAndroid Build Coastguard Worker                    uint32_t dex_pc = kNoDexPc)
HVecCondition(kVecAboveOrEqual,allocator,left,right,packed_type,vector_length,dex_pc)1736*795d594fSAndroid Build Coastguard Worker       : HVecCondition(kVecAboveOrEqual,
1737*795d594fSAndroid Build Coastguard Worker                       allocator,
1738*795d594fSAndroid Build Coastguard Worker                       left,
1739*795d594fSAndroid Build Coastguard Worker                       right,
1740*795d594fSAndroid Build Coastguard Worker                       packed_type,
1741*795d594fSAndroid Build Coastguard Worker                       vector_length,
1742*795d594fSAndroid Build Coastguard Worker                       dex_pc) {}
1743*795d594fSAndroid Build Coastguard Worker 
1744*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecAboveOrEqual);
1745*795d594fSAndroid Build Coastguard Worker 
GetCondition()1746*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
1747*795d594fSAndroid Build Coastguard Worker     return kCondAE;
1748*795d594fSAndroid Build Coastguard Worker   }
1749*795d594fSAndroid Build Coastguard Worker 
1750*795d594fSAndroid Build Coastguard Worker  protected:
1751*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecAboveOrEqual);
1752*795d594fSAndroid Build Coastguard Worker };
1753*795d594fSAndroid Build Coastguard Worker 
1754*795d594fSAndroid Build Coastguard Worker // Inverts every component in the predicate vector.
1755*795d594fSAndroid Build Coastguard Worker //
1756*795d594fSAndroid Build Coastguard Worker // viz. [ p1, .. , pn ]  = [ !px1 , !px2 , .. , !pxn ].
1757*795d594fSAndroid Build Coastguard Worker class HVecPredNot final : public HVecPredSetOperation {
1758*795d594fSAndroid Build Coastguard Worker  public:
HVecPredNot(ArenaAllocator * allocator,HInstruction * input,DataType::Type packed_type,size_t vector_length,uint32_t dex_pc)1759*795d594fSAndroid Build Coastguard Worker   HVecPredNot(ArenaAllocator* allocator,
1760*795d594fSAndroid Build Coastguard Worker               HInstruction* input,
1761*795d594fSAndroid Build Coastguard Worker               DataType::Type packed_type,
1762*795d594fSAndroid Build Coastguard Worker               size_t vector_length,
1763*795d594fSAndroid Build Coastguard Worker               uint32_t dex_pc) :
1764*795d594fSAndroid Build Coastguard Worker       HVecPredSetOperation(kVecPredNot,
1765*795d594fSAndroid Build Coastguard Worker                            allocator,
1766*795d594fSAndroid Build Coastguard Worker                            packed_type,
1767*795d594fSAndroid Build Coastguard Worker                            SideEffects::None(),
1768*795d594fSAndroid Build Coastguard Worker                            /* number_of_inputs= */ 1,
1769*795d594fSAndroid Build Coastguard Worker                            vector_length,
1770*795d594fSAndroid Build Coastguard Worker                            dex_pc) {
1771*795d594fSAndroid Build Coastguard Worker     DCHECK(input->IsVecOperation());
1772*795d594fSAndroid Build Coastguard Worker     DCHECK(input->IsVecPredSetOperation());
1773*795d594fSAndroid Build Coastguard Worker 
1774*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, input);
1775*795d594fSAndroid Build Coastguard Worker   }
1776*795d594fSAndroid Build Coastguard Worker 
1777*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(VecPredNot);
1778*795d594fSAndroid Build Coastguard Worker 
1779*795d594fSAndroid Build Coastguard Worker  protected:
1780*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VecPredNot);
1781*795d594fSAndroid Build Coastguard Worker };
1782*795d594fSAndroid Build Coastguard Worker 
1783*795d594fSAndroid Build Coastguard Worker // Return the number of elements of the given type that will fit into a vector of given size.
GetNumberOfElementsInVector(size_t vector_size_in_bytes,DataType::Type type)1784*795d594fSAndroid Build Coastguard Worker inline size_t GetNumberOfElementsInVector(size_t vector_size_in_bytes, DataType::Type type) {
1785*795d594fSAndroid Build Coastguard Worker   return vector_size_in_bytes / DataType::Size(type);
1786*795d594fSAndroid Build Coastguard Worker }
1787*795d594fSAndroid Build Coastguard Worker 
1788*795d594fSAndroid Build Coastguard Worker }  // namespace art
1789*795d594fSAndroid Build Coastguard Worker 
1790*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_
1791