xref: /aosp_15_r20/art/compiler/optimizing/nodes_shared.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 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_SHARED_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_NODES_SHARED_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker // This `#include` should never be used by compilation, as this file (`nodes_shared.h`) is included
21*795d594fSAndroid Build Coastguard Worker // in `nodes.h`. However it helps editing tools (e.g. YouCompleteMe) by giving them better context
22*795d594fSAndroid Build Coastguard Worker // (defining `HInstruction` and co).
23*795d594fSAndroid Build Coastguard Worker #include "nodes.h"
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker class HMultiplyAccumulate final : public HExpression<3> {
28*795d594fSAndroid Build Coastguard Worker  public:
29*795d594fSAndroid Build Coastguard Worker   HMultiplyAccumulate(DataType::Type type,
30*795d594fSAndroid Build Coastguard Worker                       InstructionKind op,
31*795d594fSAndroid Build Coastguard Worker                       HInstruction* accumulator,
32*795d594fSAndroid Build Coastguard Worker                       HInstruction* mul_left,
33*795d594fSAndroid Build Coastguard Worker                       HInstruction* mul_right,
34*795d594fSAndroid Build Coastguard Worker                       uint32_t dex_pc = kNoDexPc)
HExpression(kMultiplyAccumulate,type,SideEffects::None (),dex_pc)35*795d594fSAndroid Build Coastguard Worker       : HExpression(kMultiplyAccumulate, type, SideEffects::None(), dex_pc),
36*795d594fSAndroid Build Coastguard Worker         op_kind_(op) {
37*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(kInputAccumulatorIndex, accumulator);
38*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(kInputMulLeftIndex, mul_left);
39*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(kInputMulRightIndex, mul_right);
40*795d594fSAndroid Build Coastguard Worker   }
41*795d594fSAndroid Build Coastguard Worker 
IsClonable()42*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker   static constexpr int kInputAccumulatorIndex = 0;
45*795d594fSAndroid Build Coastguard Worker   static constexpr int kInputMulLeftIndex = 1;
46*795d594fSAndroid Build Coastguard Worker   static constexpr int kInputMulRightIndex = 2;
47*795d594fSAndroid Build Coastguard Worker 
CanBeMoved()48*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
InstructionDataEquals(const HInstruction * other)49*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
50*795d594fSAndroid Build Coastguard Worker     return op_kind_ == other->AsMultiplyAccumulate()->op_kind_;
51*795d594fSAndroid Build Coastguard Worker   }
52*795d594fSAndroid Build Coastguard Worker 
GetOpKind()53*795d594fSAndroid Build Coastguard Worker   InstructionKind GetOpKind() const { return op_kind_; }
54*795d594fSAndroid Build Coastguard Worker 
55*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(MultiplyAccumulate);
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker  protected:
58*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(MultiplyAccumulate);
59*795d594fSAndroid Build Coastguard Worker 
60*795d594fSAndroid Build Coastguard Worker  private:
61*795d594fSAndroid Build Coastguard Worker   // Indicates if this is a MADD or MSUB.
62*795d594fSAndroid Build Coastguard Worker   const InstructionKind op_kind_;
63*795d594fSAndroid Build Coastguard Worker };
64*795d594fSAndroid Build Coastguard Worker 
65*795d594fSAndroid Build Coastguard Worker // This instruction computes part of the array access offset (data and index offset).
66*795d594fSAndroid Build Coastguard Worker //
67*795d594fSAndroid Build Coastguard Worker // For array accesses the element address has the following structure:
68*795d594fSAndroid Build Coastguard Worker // Address = CONST_OFFSET + base_addr + index << ELEM_SHIFT. Taking into account LDR/STR addressing
69*795d594fSAndroid Build Coastguard Worker // modes address part (CONST_OFFSET + index << ELEM_SHIFT) can be shared across array access with
70*795d594fSAndroid Build Coastguard Worker // the same data type and index. For example, for the following loop 5 accesses can share address
71*795d594fSAndroid Build Coastguard Worker // computation:
72*795d594fSAndroid Build Coastguard Worker //
73*795d594fSAndroid Build Coastguard Worker // void foo(int[] a, int[] b, int[] c) {
74*795d594fSAndroid Build Coastguard Worker //   for (i...) {
75*795d594fSAndroid Build Coastguard Worker //     a[i] = a[i] + 5;
76*795d594fSAndroid Build Coastguard Worker //     b[i] = b[i] + c[i];
77*795d594fSAndroid Build Coastguard Worker //   }
78*795d594fSAndroid Build Coastguard Worker // }
79*795d594fSAndroid Build Coastguard Worker //
80*795d594fSAndroid Build Coastguard Worker // Note: as the instruction doesn't involve base array address into computations it has no side
81*795d594fSAndroid Build Coastguard Worker // effects (in comparison of HIntermediateAddress).
82*795d594fSAndroid Build Coastguard Worker class HIntermediateAddressIndex final : public HExpression<3> {
83*795d594fSAndroid Build Coastguard Worker  public:
HIntermediateAddressIndex(HInstruction * index,HInstruction * offset,HInstruction * shift,uint32_t dex_pc)84*795d594fSAndroid Build Coastguard Worker   HIntermediateAddressIndex(
85*795d594fSAndroid Build Coastguard Worker       HInstruction* index, HInstruction* offset, HInstruction* shift, uint32_t dex_pc)
86*795d594fSAndroid Build Coastguard Worker       : HExpression(kIntermediateAddressIndex,
87*795d594fSAndroid Build Coastguard Worker                     DataType::Type::kInt32,
88*795d594fSAndroid Build Coastguard Worker                     SideEffects::None(),
89*795d594fSAndroid Build Coastguard Worker                     dex_pc) {
90*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, index);
91*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, offset);
92*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(2, shift);
93*795d594fSAndroid Build Coastguard Worker   }
94*795d594fSAndroid Build Coastguard Worker 
IsClonable()95*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
CanBeMoved()96*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
InstructionDataEquals(const HInstruction * other)97*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
98*795d594fSAndroid Build Coastguard Worker     return true;
99*795d594fSAndroid Build Coastguard Worker   }
IsActualObject()100*795d594fSAndroid Build Coastguard Worker   bool IsActualObject() const override { return false; }
101*795d594fSAndroid Build Coastguard Worker 
GetIndex()102*795d594fSAndroid Build Coastguard Worker   HInstruction* GetIndex() const { return InputAt(0); }
GetOffset()103*795d594fSAndroid Build Coastguard Worker   HInstruction* GetOffset() const { return InputAt(1); }
GetShift()104*795d594fSAndroid Build Coastguard Worker   HInstruction* GetShift() const { return InputAt(2); }
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(IntermediateAddressIndex);
107*795d594fSAndroid Build Coastguard Worker 
108*795d594fSAndroid Build Coastguard Worker  protected:
109*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(IntermediateAddressIndex);
110*795d594fSAndroid Build Coastguard Worker };
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker class HDataProcWithShifterOp final : public HExpression<2> {
113*795d594fSAndroid Build Coastguard Worker  public:
114*795d594fSAndroid Build Coastguard Worker   enum OpKind {
115*795d594fSAndroid Build Coastguard Worker     kLSL,   // Logical shift left.
116*795d594fSAndroid Build Coastguard Worker     kLSR,   // Logical shift right.
117*795d594fSAndroid Build Coastguard Worker     kASR,   // Arithmetic shift right.
118*795d594fSAndroid Build Coastguard Worker     kUXTB,  // Unsigned extend byte.
119*795d594fSAndroid Build Coastguard Worker     kUXTH,  // Unsigned extend half-word.
120*795d594fSAndroid Build Coastguard Worker     kUXTW,  // Unsigned extend word.
121*795d594fSAndroid Build Coastguard Worker     kSXTB,  // Signed extend byte.
122*795d594fSAndroid Build Coastguard Worker     kSXTH,  // Signed extend half-word.
123*795d594fSAndroid Build Coastguard Worker     kSXTW,  // Signed extend word.
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker     // Aliases.
126*795d594fSAndroid Build Coastguard Worker     kFirstShiftOp = kLSL,
127*795d594fSAndroid Build Coastguard Worker     kLastShiftOp = kASR,
128*795d594fSAndroid Build Coastguard Worker     kFirstExtensionOp = kUXTB,
129*795d594fSAndroid Build Coastguard Worker     kLastExtensionOp = kSXTW
130*795d594fSAndroid Build Coastguard Worker   };
131*795d594fSAndroid Build Coastguard Worker   HDataProcWithShifterOp(HInstruction* instr,
132*795d594fSAndroid Build Coastguard Worker                          HInstruction* left,
133*795d594fSAndroid Build Coastguard Worker                          HInstruction* right,
134*795d594fSAndroid Build Coastguard Worker                          OpKind op,
135*795d594fSAndroid Build Coastguard Worker                          // The shift argument is unused if the operation
136*795d594fSAndroid Build Coastguard Worker                          // is an extension.
137*795d594fSAndroid Build Coastguard Worker                          int shift = 0,
138*795d594fSAndroid Build Coastguard Worker                          uint32_t dex_pc = kNoDexPc)
139*795d594fSAndroid Build Coastguard Worker       : HExpression(kDataProcWithShifterOp, instr->GetType(), SideEffects::None(), dex_pc),
140*795d594fSAndroid Build Coastguard Worker         instr_kind_(instr->GetKind()), op_kind_(op),
141*795d594fSAndroid Build Coastguard Worker         shift_amount_(shift & (instr->GetType() == DataType::Type::kInt32
142*795d594fSAndroid Build Coastguard Worker             ? kMaxIntShiftDistance
143*795d594fSAndroid Build Coastguard Worker             : kMaxLongShiftDistance)) {
144*795d594fSAndroid Build Coastguard Worker     DCHECK(!instr->HasSideEffects());
145*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, left);
146*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, right);
147*795d594fSAndroid Build Coastguard Worker   }
148*795d594fSAndroid Build Coastguard Worker 
IsClonable()149*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
CanBeMoved()150*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
InstructionDataEquals(const HInstruction * other_instr)151*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other_instr) const override {
152*795d594fSAndroid Build Coastguard Worker     const HDataProcWithShifterOp* other = other_instr->AsDataProcWithShifterOp();
153*795d594fSAndroid Build Coastguard Worker     return instr_kind_ == other->instr_kind_ &&
154*795d594fSAndroid Build Coastguard Worker         op_kind_ == other->op_kind_ &&
155*795d594fSAndroid Build Coastguard Worker         shift_amount_ == other->shift_amount_;
156*795d594fSAndroid Build Coastguard Worker   }
157*795d594fSAndroid Build Coastguard Worker 
IsShiftOp(OpKind op_kind)158*795d594fSAndroid Build Coastguard Worker   static bool IsShiftOp(OpKind op_kind) {
159*795d594fSAndroid Build Coastguard Worker     return kFirstShiftOp <= op_kind && op_kind <= kLastShiftOp;
160*795d594fSAndroid Build Coastguard Worker   }
161*795d594fSAndroid Build Coastguard Worker 
IsExtensionOp(OpKind op_kind)162*795d594fSAndroid Build Coastguard Worker   static bool IsExtensionOp(OpKind op_kind) {
163*795d594fSAndroid Build Coastguard Worker     return kFirstExtensionOp <= op_kind && op_kind <= kLastExtensionOp;
164*795d594fSAndroid Build Coastguard Worker   }
165*795d594fSAndroid Build Coastguard Worker 
166*795d594fSAndroid Build Coastguard Worker   // Find the operation kind and shift amount from a bitfield move instruction.
167*795d594fSAndroid Build Coastguard Worker   static void GetOpInfoFromInstruction(HInstruction* bitfield_op,
168*795d594fSAndroid Build Coastguard Worker                                        /*out*/OpKind* op_kind,
169*795d594fSAndroid Build Coastguard Worker                                        /*out*/int* shift_amount);
170*795d594fSAndroid Build Coastguard Worker 
GetInstrKind()171*795d594fSAndroid Build Coastguard Worker   InstructionKind GetInstrKind() const { return instr_kind_; }
GetOpKind()172*795d594fSAndroid Build Coastguard Worker   OpKind GetOpKind() const { return op_kind_; }
GetShiftAmount()173*795d594fSAndroid Build Coastguard Worker   int GetShiftAmount() const { return shift_amount_; }
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(DataProcWithShifterOp);
176*795d594fSAndroid Build Coastguard Worker 
177*795d594fSAndroid Build Coastguard Worker  protected:
178*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(DataProcWithShifterOp);
179*795d594fSAndroid Build Coastguard Worker 
180*795d594fSAndroid Build Coastguard Worker  private:
181*795d594fSAndroid Build Coastguard Worker   InstructionKind instr_kind_;
182*795d594fSAndroid Build Coastguard Worker   OpKind op_kind_;
183*795d594fSAndroid Build Coastguard Worker   int shift_amount_;
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker   friend std::ostream& operator<<(std::ostream& os, OpKind op);
186*795d594fSAndroid Build Coastguard Worker };
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const HDataProcWithShifterOp::OpKind op);
189*795d594fSAndroid Build Coastguard Worker 
190*795d594fSAndroid Build Coastguard Worker }  // namespace art
191*795d594fSAndroid Build Coastguard Worker 
192*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_NODES_SHARED_H_
193