xref: /aosp_15_r20/art/compiler/optimizing/nodes_x86.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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