blob: e837f1e7e0caaab94a5642e9175e3d36fd3f6f1a [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:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010029 HMultiplyAccumulate(DataType::Type type,
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030030 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
Artem Serovcced8ba2017-07-19 18:18:09 +010041 bool IsClonable() const OVERRIDE { return true; }
42
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030043 static constexpr int kInputAccumulatorIndex = 0;
44 static constexpr int kInputMulLeftIndex = 1;
45 static constexpr int kInputMulRightIndex = 2;
46
47 bool CanBeMoved() const OVERRIDE { return true; }
Vladimir Marko372f10e2016-05-17 16:30:10 +010048 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030049 return op_kind_ == other->AsMultiplyAccumulate()->op_kind_;
50 }
51
52 InstructionKind GetOpKind() const { return op_kind_; }
53
54 DECLARE_INSTRUCTION(MultiplyAccumulate);
55
Artem Serovcced8ba2017-07-19 18:18:09 +010056 protected:
57 DEFAULT_COPY_CONSTRUCTOR(MultiplyAccumulate);
58
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030059 private:
60 // Indicates if this is a MADD or MSUB.
61 const InstructionKind op_kind_;
Artem Udovichenko4a0dad62016-01-26 12:28:31 +030062};
63
Vladimir Markofcb503c2016-05-18 12:48:17 +010064class HBitwiseNegatedRight FINAL : public HBinaryOperation {
Artem Serov7fc63502016-02-09 17:15:29 +000065 public:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010066 HBitwiseNegatedRight(DataType::Type result_type,
67 InstructionKind op,
68 HInstruction* left,
69 HInstruction* right,
70 uint32_t dex_pc = kNoDexPc)
Artem Serov7fc63502016-02-09 17:15:29 +000071 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc),
72 op_kind_(op) {
73 DCHECK(op == HInstruction::kAnd || op == HInstruction::kOr || op == HInstruction::kXor) << op;
74 }
75
76 template <typename T, typename U>
77 auto Compute(T x, U y) const -> decltype(x & ~y) {
78 static_assert(std::is_same<decltype(x & ~y), decltype(x | ~y)>::value &&
79 std::is_same<decltype(x & ~y), decltype(x ^ ~y)>::value,
80 "Inconsistent negated bitwise types");
81 switch (op_kind_) {
82 case HInstruction::kAnd:
83 return x & ~y;
84 case HInstruction::kOr:
85 return x | ~y;
86 case HInstruction::kXor:
87 return x ^ ~y;
88 default:
89 LOG(FATAL) << "Unreachable";
90 UNREACHABLE();
91 }
92 }
93
94 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
95 return GetBlock()->GetGraph()->GetIntConstant(
96 Compute(x->GetValue(), y->GetValue()), GetDexPc());
97 }
98 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
99 return GetBlock()->GetGraph()->GetLongConstant(
100 Compute(x->GetValue(), y->GetValue()), GetDexPc());
101 }
102 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
103 HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
104 LOG(FATAL) << DebugName() << " is not defined for float values";
105 UNREACHABLE();
106 }
107 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
108 HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
109 LOG(FATAL) << DebugName() << " is not defined for double values";
110 UNREACHABLE();
111 }
112
113 InstructionKind GetOpKind() const { return op_kind_; }
114
115 DECLARE_INSTRUCTION(BitwiseNegatedRight);
116
Artem Serovcced8ba2017-07-19 18:18:09 +0100117 protected:
118 DEFAULT_COPY_CONSTRUCTOR(BitwiseNegatedRight);
119
Artem Serov7fc63502016-02-09 17:15:29 +0000120 private:
121 // Specifies the bitwise operation, which will be then negated.
122 const InstructionKind op_kind_;
Artem Serov7fc63502016-02-09 17:15:29 +0000123};
124
Artem Serove1811ed2017-04-27 16:50:47 +0100125// This instruction computes part of the array access offset (data and index offset).
126//
127// For array accesses the element address has the following structure:
128// Address = CONST_OFFSET + base_addr + index << ELEM_SHIFT. Taking into account LDR/STR addressing
129// modes address part (CONST_OFFSET + index << ELEM_SHIFT) can be shared across array access with
130// the same data type and index. For example, for the following loop 5 accesses can share address
131// computation:
132//
133// void foo(int[] a, int[] b, int[] c) {
134// for (i...) {
135// a[i] = a[i] + 5;
136// b[i] = b[i] + c[i];
137// }
138// }
139//
140// Note: as the instruction doesn't involve base array address into computations it has no side
141// effects (in comparison of HIntermediateAddress).
142class HIntermediateAddressIndex FINAL : public HExpression<3> {
143 public:
144 HIntermediateAddressIndex(
145 HInstruction* index, HInstruction* offset, HInstruction* shift, uint32_t dex_pc)
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100146 : HExpression(DataType::Type::kInt32, SideEffects::None(), dex_pc) {
Artem Serove1811ed2017-04-27 16:50:47 +0100147 SetRawInputAt(0, index);
148 SetRawInputAt(1, offset);
149 SetRawInputAt(2, shift);
150 }
151
Artem Serovcced8ba2017-07-19 18:18:09 +0100152 bool IsClonable() const OVERRIDE { return true; }
Artem Serove1811ed2017-04-27 16:50:47 +0100153 bool CanBeMoved() const OVERRIDE { return true; }
154 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
155 return true;
156 }
157 bool IsActualObject() const OVERRIDE { return false; }
158
159 HInstruction* GetIndex() const { return InputAt(0); }
160 HInstruction* GetOffset() const { return InputAt(1); }
161 HInstruction* GetShift() const { return InputAt(2); }
162
163 DECLARE_INSTRUCTION(IntermediateAddressIndex);
164
Artem Serovcced8ba2017-07-19 18:18:09 +0100165 protected:
166 DEFAULT_COPY_CONSTRUCTOR(IntermediateAddressIndex);
Artem Serove1811ed2017-04-27 16:50:47 +0100167};
168
Anton Kirilov74234da2017-01-13 14:42:47 +0000169class HDataProcWithShifterOp FINAL : public HExpression<2> {
170 public:
171 enum OpKind {
172 kLSL, // Logical shift left.
173 kLSR, // Logical shift right.
174 kASR, // Arithmetic shift right.
175 kUXTB, // Unsigned extend byte.
176 kUXTH, // Unsigned extend half-word.
177 kUXTW, // Unsigned extend word.
178 kSXTB, // Signed extend byte.
179 kSXTH, // Signed extend half-word.
180 kSXTW, // Signed extend word.
181
182 // Aliases.
183 kFirstShiftOp = kLSL,
184 kLastShiftOp = kASR,
185 kFirstExtensionOp = kUXTB,
186 kLastExtensionOp = kSXTW
187 };
188 HDataProcWithShifterOp(HInstruction* instr,
189 HInstruction* left,
190 HInstruction* right,
191 OpKind op,
192 // The shift argument is unused if the operation
193 // is an extension.
194 int shift = 0,
195 uint32_t dex_pc = kNoDexPc)
196 : HExpression(instr->GetType(), SideEffects::None(), dex_pc),
197 instr_kind_(instr->GetKind()), op_kind_(op),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100198 shift_amount_(shift & (instr->GetType() == DataType::Type::kInt32
Anton Kirilov74234da2017-01-13 14:42:47 +0000199 ? kMaxIntShiftDistance
200 : kMaxLongShiftDistance)) {
201 DCHECK(!instr->HasSideEffects());
202 SetRawInputAt(0, left);
203 SetRawInputAt(1, right);
204 }
205
Artem Serovcced8ba2017-07-19 18:18:09 +0100206 bool IsClonable() const OVERRIDE { return true; }
Anton Kirilov74234da2017-01-13 14:42:47 +0000207 bool CanBeMoved() const OVERRIDE { return true; }
208 bool InstructionDataEquals(const HInstruction* other_instr) const OVERRIDE {
209 const HDataProcWithShifterOp* other = other_instr->AsDataProcWithShifterOp();
210 return instr_kind_ == other->instr_kind_ &&
211 op_kind_ == other->op_kind_ &&
212 shift_amount_ == other->shift_amount_;
213 }
214
215 static bool IsShiftOp(OpKind op_kind) {
216 return kFirstShiftOp <= op_kind && op_kind <= kLastShiftOp;
217 }
218
219 static bool IsExtensionOp(OpKind op_kind) {
220 return kFirstExtensionOp <= op_kind && op_kind <= kLastExtensionOp;
221 }
222
223 // Find the operation kind and shift amount from a bitfield move instruction.
224 static void GetOpInfoFromInstruction(HInstruction* bitfield_op,
225 /*out*/OpKind* op_kind,
226 /*out*/int* shift_amount);
227
228 InstructionKind GetInstrKind() const { return instr_kind_; }
229 OpKind GetOpKind() const { return op_kind_; }
230 int GetShiftAmount() const { return shift_amount_; }
231
232 DECLARE_INSTRUCTION(DataProcWithShifterOp);
233
Artem Serovcced8ba2017-07-19 18:18:09 +0100234 protected:
235 DEFAULT_COPY_CONSTRUCTOR(DataProcWithShifterOp);
236
Anton Kirilov74234da2017-01-13 14:42:47 +0000237 private:
238 InstructionKind instr_kind_;
239 OpKind op_kind_;
240 int shift_amount_;
241
242 friend std::ostream& operator<<(std::ostream& os, OpKind op);
Anton Kirilov74234da2017-01-13 14:42:47 +0000243};
244
245std::ostream& operator<<(std::ostream& os, const HDataProcWithShifterOp::OpKind op);
Artem Serov328429f2016-07-06 16:23:04 +0100246
Artem Udovichenko4a0dad62016-01-26 12:28:31 +0300247} // namespace art
248
249#endif // ART_COMPILER_OPTIMIZING_NODES_SHARED_H_