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