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_X86_H_ 18 #define ART_COMPILER_OPTIMIZING_NODES_X86_H_ 19 20 namespace art HIDDEN { 21 22 // Compute the address of the method for X86 Constant area support. 23 class HX86ComputeBaseMethodAddress final : public HExpression<0> { 24 public: 25 // Treat the value as an int32_t, but it is really a 32 bit native pointer. HX86ComputeBaseMethodAddress()26 HX86ComputeBaseMethodAddress() 27 : HExpression(kX86ComputeBaseMethodAddress, 28 DataType::Type::kInt32, 29 SideEffects::None(), 30 kNoDexPc) { 31 } 32 CanBeMoved()33 bool CanBeMoved() const override { return true; } 34 35 DECLARE_INSTRUCTION(X86ComputeBaseMethodAddress); 36 37 protected: 38 DEFAULT_COPY_CONSTRUCTOR(X86ComputeBaseMethodAddress); 39 }; 40 41 // Load a constant value from the constant table. 42 class HX86LoadFromConstantTable final : public HExpression<2> { 43 public: HX86LoadFromConstantTable(HX86ComputeBaseMethodAddress * method_base,HConstant * constant)44 HX86LoadFromConstantTable(HX86ComputeBaseMethodAddress* method_base, 45 HConstant* constant) 46 : HExpression(kX86LoadFromConstantTable, 47 constant->GetType(), 48 SideEffects::None(), 49 kNoDexPc) { 50 SetRawInputAt(0, method_base); 51 SetRawInputAt(1, constant); 52 } 53 GetBaseMethodAddress()54 HX86ComputeBaseMethodAddress* GetBaseMethodAddress() const { 55 return InputAt(0)->AsX86ComputeBaseMethodAddress(); 56 } 57 GetConstant()58 HConstant* GetConstant() const { 59 return InputAt(1)->AsConstant(); 60 } 61 CanBeMoved()62 bool CanBeMoved() const override { return true; } 63 64 DECLARE_INSTRUCTION(X86LoadFromConstantTable); 65 66 protected: 67 DEFAULT_COPY_CONSTRUCTOR(X86LoadFromConstantTable); 68 }; 69 70 // Version of HNeg with access to the constant table for FP types. 71 class HX86FPNeg final : public HExpression<2> { 72 public: HX86FPNeg(DataType::Type result_type,HInstruction * input,HX86ComputeBaseMethodAddress * method_base,uint32_t dex_pc)73 HX86FPNeg(DataType::Type result_type, 74 HInstruction* input, 75 HX86ComputeBaseMethodAddress* method_base, 76 uint32_t dex_pc) 77 : HExpression(kX86FPNeg, result_type, SideEffects::None(), dex_pc) { 78 DCHECK(DataType::IsFloatingPointType(result_type)); 79 SetRawInputAt(0, input); 80 SetRawInputAt(1, method_base); 81 } 82 GetBaseMethodAddress()83 HX86ComputeBaseMethodAddress* GetBaseMethodAddress() const { 84 return InputAt(1)->AsX86ComputeBaseMethodAddress(); 85 } 86 87 DECLARE_INSTRUCTION(X86FPNeg); 88 89 protected: 90 DEFAULT_COPY_CONSTRUCTOR(X86FPNeg); 91 }; 92 93 // X86 version of HPackedSwitch that holds a pointer to the base method address. 94 class HX86PackedSwitch final : public HExpression<2> { 95 public: HX86PackedSwitch(int32_t start_value,int32_t num_entries,HInstruction * input,HX86ComputeBaseMethodAddress * method_base,uint32_t dex_pc)96 HX86PackedSwitch(int32_t start_value, 97 int32_t num_entries, 98 HInstruction* input, 99 HX86ComputeBaseMethodAddress* method_base, 100 uint32_t dex_pc) 101 : HExpression(kX86PackedSwitch, SideEffects::None(), dex_pc), 102 start_value_(start_value), 103 num_entries_(num_entries) { 104 SetRawInputAt(0, input); 105 SetRawInputAt(1, method_base); 106 } 107 IsControlFlow()108 bool IsControlFlow() const override { return true; } 109 GetStartValue()110 int32_t GetStartValue() const { return start_value_; } 111 GetNumEntries()112 int32_t GetNumEntries() const { return num_entries_; } 113 GetBaseMethodAddress()114 HX86ComputeBaseMethodAddress* GetBaseMethodAddress() const { 115 return InputAt(1)->AsX86ComputeBaseMethodAddress(); 116 } 117 GetDefaultBlock()118 HBasicBlock* GetDefaultBlock() const { 119 // Last entry is the default block. 120 return GetBlock()->GetSuccessors()[num_entries_]; 121 } 122 123 DECLARE_INSTRUCTION(X86PackedSwitch); 124 125 protected: 126 DEFAULT_COPY_CONSTRUCTOR(X86PackedSwitch); 127 128 private: 129 const int32_t start_value_; 130 const int32_t num_entries_; 131 }; 132 133 class HX86AndNot final : public HBinaryOperation { 134 public: 135 HX86AndNot(DataType::Type result_type, 136 HInstruction* left, 137 HInstruction* right, 138 uint32_t dex_pc = kNoDexPc) HBinaryOperation(kX86AndNot,result_type,left,right,SideEffects::None (),dex_pc)139 : HBinaryOperation(kX86AndNot, result_type, left, right, SideEffects::None(), dex_pc) { 140 } 141 IsCommutative()142 bool IsCommutative() const override { return false; } 143 Compute(T x,T y)144 template <typename T> static T Compute(T x, T y) { return ~x & y; } 145 Evaluate(HIntConstant * x,HIntConstant * y)146 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override { 147 return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue())); 148 } Evaluate(HLongConstant * x,HLongConstant * y)149 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override { 150 return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue())); 151 } 152 153 DECLARE_INSTRUCTION(X86AndNot); 154 155 protected: 156 DEFAULT_COPY_CONSTRUCTOR(X86AndNot); 157 }; 158 159 class HX86MaskOrResetLeastSetBit final : public HUnaryOperation { 160 public: 161 HX86MaskOrResetLeastSetBit(DataType::Type result_type, InstructionKind op, 162 HInstruction* input, uint32_t dex_pc = kNoDexPc) HUnaryOperation(kX86MaskOrResetLeastSetBit,result_type,input,dex_pc)163 : HUnaryOperation(kX86MaskOrResetLeastSetBit, result_type, input, dex_pc), 164 op_kind_(op) { 165 DCHECK_EQ(result_type, DataType::Kind(input->GetType())); 166 DCHECK(op == HInstruction::kAnd || op == HInstruction::kXor) << op; 167 } 168 template <typename T> 169 auto Compute(T x) const -> decltype(x & (x-1)) { 170 static_assert(std::is_same<decltype(x & (x-1)), decltype(x ^(x-1))>::value, 171 "Inconsistent bitwise types"); 172 switch (op_kind_) { 173 case HInstruction::kAnd: 174 return x & (x-1); 175 case HInstruction::kXor: 176 return x ^ (x-1); 177 default: 178 LOG(FATAL) << "Unreachable"; 179 UNREACHABLE(); 180 } 181 } 182 Evaluate(HIntConstant * x)183 HConstant* Evaluate(HIntConstant* x) const override { 184 return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue())); 185 } Evaluate(HLongConstant * x)186 HConstant* Evaluate(HLongConstant* x) const override { 187 return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue())); 188 } 189 GetOpKind()190 InstructionKind GetOpKind() const { return op_kind_; } 191 192 DECLARE_INSTRUCTION(X86MaskOrResetLeastSetBit); 193 194 protected: 195 const InstructionKind op_kind_; 196 197 DEFAULT_COPY_CONSTRUCTOR(X86MaskOrResetLeastSetBit); 198 }; 199 200 } // namespace art 201 202 #endif // ART_COMPILER_OPTIMIZING_NODES_X86_H_ 203