blob: c6bfbcc7fbaab7d6a227a94d0482d65986325b20 [file] [log] [blame]
Artem Udovichenko4a0dad62016-01-26 12:28:31 +03001/*
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_SHARED_H_
18#define ART_COMPILER_OPTIMIZING_NODES_SHARED_H_
19
Alexandre Ramesebc32802016-09-19 13:56:18 +010020// This `#include` should never be used by compilation, as this file (`nodes_shared.h`) is included
21// in `nodes.h`. However it helps editing tools (e.g. YouCompleteMe) by giving them better context
22// (defining `HInstruction` and co).
23#include "nodes.h"
24
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030025namespace art {
26
Vladimir Markofcb503c2016-05-18 12:48:17 +010027class HMultiplyAccumulate FINAL : public HExpression<3> {
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030028 public:
29 HMultiplyAccumulate(Primitive::Type type,
30 InstructionKind op,
31 HInstruction* accumulator,
32 HInstruction* mul_left,
33 HInstruction* mul_right,
34 uint32_t dex_pc = kNoDexPc)
35 : HExpression(type, SideEffects::None(), dex_pc), op_kind_(op) {
36 SetRawInputAt(kInputAccumulatorIndex, accumulator);
37 SetRawInputAt(kInputMulLeftIndex, mul_left);
38 SetRawInputAt(kInputMulRightIndex, mul_right);
39 }
40
41 static constexpr int kInputAccumulatorIndex = 0;
42 static constexpr int kInputMulLeftIndex = 1;
43 static constexpr int kInputMulRightIndex = 2;
44
45 bool CanBeMoved() const OVERRIDE { return true; }
Vladimir Marko372f10e2016-05-17 16:30:10 +010046 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030047 return op_kind_ == other->AsMultiplyAccumulate()->op_kind_;
48 }
49
50 InstructionKind GetOpKind() const { return op_kind_; }
51
52 DECLARE_INSTRUCTION(MultiplyAccumulate);
53
54 private:
55 // Indicates if this is a MADD or MSUB.
56 const InstructionKind op_kind_;
57
58 DISALLOW_COPY_AND_ASSIGN(HMultiplyAccumulate);
59};
60
Vladimir Markofcb503c2016-05-18 12:48:17 +010061class HBitwiseNegatedRight FINAL : public HBinaryOperation {
Artem Serov7fc63502016-02-09 17:15:29 +000062 public:
63 HBitwiseNegatedRight(Primitive::Type result_type,
64 InstructionKind op,
65 HInstruction* left,
66 HInstruction* right,
67 uint32_t dex_pc = kNoDexPc)
68 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc),
69 op_kind_(op) {
70 DCHECK(op == HInstruction::kAnd || op == HInstruction::kOr || op == HInstruction::kXor) << op;
71 }
72
73 template <typename T, typename U>
74 auto Compute(T x, U y) const -> decltype(x & ~y) {
75 static_assert(std::is_same<decltype(x & ~y), decltype(x | ~y)>::value &&
76 std::is_same<decltype(x & ~y), decltype(x ^ ~y)>::value,
77 "Inconsistent negated bitwise types");
78 switch (op_kind_) {
79 case HInstruction::kAnd:
80 return x & ~y;
81 case HInstruction::kOr:
82 return x | ~y;
83 case HInstruction::kXor:
84 return x ^ ~y;
85 default:
86 LOG(FATAL) << "Unreachable";
87 UNREACHABLE();
88 }
89 }
90
91 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
92 return GetBlock()->GetGraph()->GetIntConstant(
93 Compute(x->GetValue(), y->GetValue()), GetDexPc());
94 }
95 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
96 return GetBlock()->GetGraph()->GetLongConstant(
97 Compute(x->GetValue(), y->GetValue()), GetDexPc());
98 }
99 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
100 HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
101 LOG(FATAL) << DebugName() << " is not defined for float values";
102 UNREACHABLE();
103 }
104 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
105 HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
106 LOG(FATAL) << DebugName() << " is not defined for double values";
107 UNREACHABLE();
108 }
109
110 InstructionKind GetOpKind() const { return op_kind_; }
111
112 DECLARE_INSTRUCTION(BitwiseNegatedRight);
113
114 private:
115 // Specifies the bitwise operation, which will be then negated.
116 const InstructionKind op_kind_;
117
118 DISALLOW_COPY_AND_ASSIGN(HBitwiseNegatedRight);
119};
120
Artem Serov328429f2016-07-06 16:23:04 +0100121
122// This instruction computes an intermediate address pointing in the 'middle' of an object. The
123// result pointer cannot be handled by GC, so extra care is taken to make sure that this value is
124// never used across anything that can trigger GC.
Alexandre Rames91a65162016-09-19 13:54:30 +0100125// The result of this instruction is not a pointer in the sense of `Primitive::kPrimNot`. So we
126// represent it by the type `Primitive::kPrimInt`.
Artem Serov328429f2016-07-06 16:23:04 +0100127class HIntermediateAddress FINAL : public HExpression<2> {
128 public:
129 HIntermediateAddress(HInstruction* base_address, HInstruction* offset, uint32_t dex_pc)
Alexandre Rames91a65162016-09-19 13:54:30 +0100130 : HExpression(Primitive::kPrimInt, SideEffects::DependsOnGC(), dex_pc) {
131 DCHECK_EQ(Primitive::ComponentSize(Primitive::kPrimInt),
132 Primitive::ComponentSize(Primitive::kPrimNot))
133 << "kPrimInt and kPrimNot have different sizes.";
Artem Serov328429f2016-07-06 16:23:04 +0100134 SetRawInputAt(0, base_address);
135 SetRawInputAt(1, offset);
136 }
137
138 bool CanBeMoved() const OVERRIDE { return true; }
139 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
140 return true;
141 }
142 bool IsActualObject() const OVERRIDE { return false; }
143
144 HInstruction* GetBaseAddress() const { return InputAt(0); }
145 HInstruction* GetOffset() const { return InputAt(1); }
146
147 DECLARE_INSTRUCTION(IntermediateAddress);
148
149 private:
150 DISALLOW_COPY_AND_ASSIGN(HIntermediateAddress);
151};
152
Anton Kirilov74234da2017-01-13 14:42:47 +0000153class HDataProcWithShifterOp FINAL : public HExpression<2> {
154 public:
155 enum OpKind {
156 kLSL, // Logical shift left.
157 kLSR, // Logical shift right.
158 kASR, // Arithmetic shift right.
159 kUXTB, // Unsigned extend byte.
160 kUXTH, // Unsigned extend half-word.
161 kUXTW, // Unsigned extend word.
162 kSXTB, // Signed extend byte.
163 kSXTH, // Signed extend half-word.
164 kSXTW, // Signed extend word.
165
166 // Aliases.
167 kFirstShiftOp = kLSL,
168 kLastShiftOp = kASR,
169 kFirstExtensionOp = kUXTB,
170 kLastExtensionOp = kSXTW
171 };
172 HDataProcWithShifterOp(HInstruction* instr,
173 HInstruction* left,
174 HInstruction* right,
175 OpKind op,
176 // The shift argument is unused if the operation
177 // is an extension.
178 int shift = 0,
179 uint32_t dex_pc = kNoDexPc)
180 : HExpression(instr->GetType(), SideEffects::None(), dex_pc),
181 instr_kind_(instr->GetKind()), op_kind_(op),
182 shift_amount_(shift & (instr->GetType() == Primitive::kPrimInt
183 ? kMaxIntShiftDistance
184 : kMaxLongShiftDistance)) {
185 DCHECK(!instr->HasSideEffects());
186 SetRawInputAt(0, left);
187 SetRawInputAt(1, right);
188 }
189
190 bool CanBeMoved() const OVERRIDE { return true; }
191 bool InstructionDataEquals(const HInstruction* other_instr) const OVERRIDE {
192 const HDataProcWithShifterOp* other = other_instr->AsDataProcWithShifterOp();
193 return instr_kind_ == other->instr_kind_ &&
194 op_kind_ == other->op_kind_ &&
195 shift_amount_ == other->shift_amount_;
196 }
197
198 static bool IsShiftOp(OpKind op_kind) {
199 return kFirstShiftOp <= op_kind && op_kind <= kLastShiftOp;
200 }
201
202 static bool IsExtensionOp(OpKind op_kind) {
203 return kFirstExtensionOp <= op_kind && op_kind <= kLastExtensionOp;
204 }
205
206 // Find the operation kind and shift amount from a bitfield move instruction.
207 static void GetOpInfoFromInstruction(HInstruction* bitfield_op,
208 /*out*/OpKind* op_kind,
209 /*out*/int* shift_amount);
210
211 InstructionKind GetInstrKind() const { return instr_kind_; }
212 OpKind GetOpKind() const { return op_kind_; }
213 int GetShiftAmount() const { return shift_amount_; }
214
215 DECLARE_INSTRUCTION(DataProcWithShifterOp);
216
217 private:
218 InstructionKind instr_kind_;
219 OpKind op_kind_;
220 int shift_amount_;
221
222 friend std::ostream& operator<<(std::ostream& os, OpKind op);
223
224 DISALLOW_COPY_AND_ASSIGN(HDataProcWithShifterOp);
225};
226
227std::ostream& operator<<(std::ostream& os, const HDataProcWithShifterOp::OpKind op);
Artem Serov328429f2016-07-06 16:23:04 +0100228
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300229} // namespace art
230
231#endif // ART_COMPILER_OPTIMIZING_NODES_SHARED_H_