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