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.
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 
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:
HX86FPNeg(DataType::Type result_type,HInstruction * input,HX86ComputeBaseMethodAddress * method_base,uint32_t dex_pc)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 
GetBaseMethodAddress()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:
HX86PackedSwitch(int32_t start_value,int32_t num_entries,HInstruction * input,HX86ComputeBaseMethodAddress * method_base,uint32_t dex_pc)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 
IsControlFlow()106   bool IsControlFlow() const override { return true; }
107 
GetStartValue()108   int32_t GetStartValue() const { return start_value_; }
109 
GetNumEntries()110   int32_t GetNumEntries() const { return num_entries_; }
111 
GetBaseMethodAddress()112   HX86ComputeBaseMethodAddress* GetBaseMethodAddress() const {
113     return InputAt(1)->AsX86ComputeBaseMethodAddress();
114   }
115 
GetDefaultBlock()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)
HBinaryOperation(kX86AndNot,result_type,left,right,SideEffects::None (),dex_pc)137       : HBinaryOperation(kX86AndNot, result_type, left, right, SideEffects::None(), dex_pc) {
138   }
139 
IsCommutative()140   bool IsCommutative() const override { return false; }
141 
Compute(T x,T y)142   template <typename T> static T Compute(T x, T y) { return ~x & y; }
143 
Evaluate(HIntConstant * x,HIntConstant * y)144   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
145     return GetBlock()->GetGraph()->GetIntConstant(
146         Compute(x->GetValue(), y->GetValue()), GetDexPc());
147   }
Evaluate(HLongConstant * x,HLongConstant * y)148   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
149     return GetBlock()->GetGraph()->GetLongConstant(
150         Compute(x->GetValue(), y->GetValue()), GetDexPc());
151   }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED,HFloatConstant * y ATTRIBUTE_UNUSED)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   }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED,HDoubleConstant * y ATTRIBUTE_UNUSED)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)
HUnaryOperation(kX86MaskOrResetLeastSetBit,result_type,input,dex_pc)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 
Evaluate(HIntConstant * x)193   HConstant* Evaluate(HIntConstant* x) const override {
194     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
195   }
Evaluate(HLongConstant * x)196   HConstant* Evaluate(HLongConstant* x) const override {
197     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
198   }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED)199   HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED) const override {
200     LOG(FATAL) << DebugName() << "is not defined for float values";
201     UNREACHABLE();
202   }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED)203   HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED) const override {
204     LOG(FATAL) << DebugName() << "is not defined for double values";
205     UNREACHABLE();
206   }
GetOpKind()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