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