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