Have constant folding be more flexible.
- Have Evaluate methods take as argument(s) and return value
instances of HConstant (instead of built-in 32- or 64-bit
integer values), to let the evaluated instruction choose
the type of the statically evaluated node; for instance,
art::HEqual::Evaluate shall return a HIntConstant
node (as implementation of a Boolean constant) whatever
the type of its inputs (a pair of HIntConstant or a pair
of HLongConstant).
- Split the evaluation job from the operation logic: the
former is addressed by Evaluate methods, while the latter
is done by a generic Compute method.
- Adress valid BinOp(int, long) and BinOp(long, int) cases.
- Add a constructor to art::HIntConstant to build an integer
constant from a `bool` value.
Change-Id: If84b6fe8406bb94ddb1aa8b02e36628dff526db3
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 1190fae..10d8869 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -17,6 +17,8 @@
#ifndef ART_COMPILER_OPTIMIZING_NODES_H_
#define ART_COMPILER_OPTIMIZING_NODES_H_
+#include <type_traits>
+
#include "base/arena_containers.h"
#include "base/arena_object.h"
#include "dex/compiler_enums.h"
@@ -1551,6 +1553,7 @@
HInstruction* GetPreviousDisregardingMoves() const;
HBasicBlock* GetBlock() const { return block_; }
+ ArenaAllocator* GetArena() const { return block_->GetGraph()->GetArena(); }
void SetBlock(HBasicBlock* block) { block_ = block; }
bool IsInBlock() const { return block_ != nullptr; }
bool IsInLoop() const { return block_->IsInLoop(); }
@@ -2017,6 +2020,95 @@
DISALLOW_COPY_AND_ASSIGN(HGoto);
};
+class HConstant : public HExpression<0> {
+ public:
+ explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
+
+ bool CanBeMoved() const OVERRIDE { return true; }
+
+ virtual bool IsMinusOne() const { return false; }
+ virtual bool IsZero() const { return false; }
+ virtual bool IsOne() const { return false; }
+
+ DECLARE_INSTRUCTION(Constant);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HConstant);
+};
+
+class HNullConstant : public HConstant {
+ public:
+ bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
+ return true;
+ }
+
+ size_t ComputeHashCode() const OVERRIDE { return 0; }
+
+ DECLARE_INSTRUCTION(NullConstant);
+
+ private:
+ HNullConstant() : HConstant(Primitive::kPrimNot) {}
+
+ friend class HGraph;
+ DISALLOW_COPY_AND_ASSIGN(HNullConstant);
+};
+
+// Constants of the type int. Those can be from Dex instructions, or
+// synthesized (for example with the if-eqz instruction).
+class HIntConstant : public HConstant {
+ public:
+ int32_t GetValue() const { return value_; }
+
+ bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+ DCHECK(other->IsIntConstant());
+ return other->AsIntConstant()->value_ == value_;
+ }
+
+ size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
+
+ bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
+ bool IsZero() const OVERRIDE { return GetValue() == 0; }
+ bool IsOne() const OVERRIDE { return GetValue() == 1; }
+
+ DECLARE_INSTRUCTION(IntConstant);
+
+ private:
+ explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
+ explicit HIntConstant(bool value) : HConstant(Primitive::kPrimInt), value_(value ? 1 : 0) {}
+
+ const int32_t value_;
+
+ friend class HGraph;
+ ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
+ ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast);
+ DISALLOW_COPY_AND_ASSIGN(HIntConstant);
+};
+
+class HLongConstant : public HConstant {
+ public:
+ int64_t GetValue() const { return value_; }
+
+ bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+ DCHECK(other->IsLongConstant());
+ return other->AsLongConstant()->value_ == value_;
+ }
+
+ size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
+
+ bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
+ bool IsZero() const OVERRIDE { return GetValue() == 0; }
+ bool IsOne() const OVERRIDE { return GetValue() == 1; }
+
+ DECLARE_INSTRUCTION(LongConstant);
+
+ private:
+ explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
+
+ const int64_t value_;
+
+ friend class HGraph;
+ DISALLOW_COPY_AND_ASSIGN(HLongConstant);
+};
// Conditional branch. A block ending with an HIf instruction must have
// two successors.
@@ -2166,8 +2258,8 @@
HConstant* TryStaticEvaluation() const;
// Apply this operation to `x`.
- virtual int32_t Evaluate(int32_t x) const = 0;
- virtual int64_t Evaluate(int64_t x) const = 0;
+ virtual HConstant* Evaluate(HIntConstant* x) const = 0;
+ virtual HConstant* Evaluate(HLongConstant* x) const = 0;
DECLARE_INSTRUCTION(UnaryOperation);
@@ -2234,8 +2326,18 @@
HConstant* TryStaticEvaluation() const;
// Apply this operation to `x` and `y`.
- virtual int32_t Evaluate(int32_t x, int32_t y) const = 0;
- virtual int64_t Evaluate(int64_t x, int64_t y) const = 0;
+ virtual HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const = 0;
+ virtual HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const = 0;
+ virtual HConstant* Evaluate(HIntConstant* x ATTRIBUTE_UNUSED,
+ HLongConstant* y ATTRIBUTE_UNUSED) const {
+ VLOG(compiler) << DebugName() << " is not defined for the (int, long) case.";
+ return nullptr;
+ }
+ virtual HConstant* Evaluate(HLongConstant* x ATTRIBUTE_UNUSED,
+ HIntConstant* y ATTRIBUTE_UNUSED) const {
+ VLOG(compiler) << DebugName() << " is not defined for the (long, int) case.";
+ return nullptr;
+ }
// Returns an input that can legally be used as the right input and is
// constant, or null.
@@ -2318,11 +2420,13 @@
bool IsCommutative() const OVERRIDE { return true; }
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- return x == y ? 1 : 0;
+ template <typename T> bool Compute(T x, T y) const { return x == y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- return x == y ? 1 : 0;
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
DECLARE_INSTRUCTION(Equal);
@@ -2346,11 +2450,13 @@
bool IsCommutative() const OVERRIDE { return true; }
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- return x != y ? 1 : 0;
+ template <typename T> bool Compute(T x, T y) const { return x != y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- return x != y ? 1 : 0;
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
DECLARE_INSTRUCTION(NotEqual);
@@ -2372,11 +2478,13 @@
HLessThan(HInstruction* first, HInstruction* second)
: HCondition(first, second) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- return x < y ? 1 : 0;
+ template <typename T> bool Compute(T x, T y) const { return x < y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- return x < y ? 1 : 0;
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
DECLARE_INSTRUCTION(LessThan);
@@ -2398,11 +2506,13 @@
HLessThanOrEqual(HInstruction* first, HInstruction* second)
: HCondition(first, second) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- return x <= y ? 1 : 0;
+ template <typename T> bool Compute(T x, T y) const { return x <= y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- return x <= y ? 1 : 0;
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
DECLARE_INSTRUCTION(LessThanOrEqual);
@@ -2424,11 +2534,13 @@
HGreaterThan(HInstruction* first, HInstruction* second)
: HCondition(first, second) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- return x > y ? 1 : 0;
+ template <typename T> bool Compute(T x, T y) const { return x > y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- return x > y ? 1 : 0;
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
DECLARE_INSTRUCTION(GreaterThan);
@@ -2450,11 +2562,13 @@
HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
: HCondition(first, second) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- return x >= y ? 1 : 0;
+ template <typename T> bool Compute(T x, T y) const { return x >= y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- return x >= y ? 1 : 0;
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
DECLARE_INSTRUCTION(GreaterThanOrEqual);
@@ -2486,18 +2600,14 @@
DCHECK_EQ(type, second->GetType());
}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- return
- x == y ? 0 :
- x > y ? 1 :
- -1;
- }
+ template <typename T>
+ int32_t Compute(T x, T y) const { return x == y ? 0 : x > y ? 1 : -1; }
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- return
- x == y ? 0 :
- x > y ? 1 :
- -1;
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
@@ -2569,27 +2679,12 @@
DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
};
-class HConstant : public HExpression<0> {
- public:
- explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
-
- bool CanBeMoved() const OVERRIDE { return true; }
-
- virtual bool IsMinusOne() const { return false; }
- virtual bool IsZero() const { return false; }
- virtual bool IsOne() const { return false; }
-
- DECLARE_INSTRUCTION(Constant);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HConstant);
-};
-
class HFloatConstant : public HConstant {
public:
float GetValue() const { return value_; }
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+ DCHECK(other->IsFloatConstant());
return bit_cast<uint32_t, float>(other->AsFloatConstant()->value_) ==
bit_cast<uint32_t, float>(value_);
}
@@ -2629,6 +2724,7 @@
double GetValue() const { return value_; }
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+ DCHECK(other->IsDoubleConstant());
return bit_cast<uint64_t, double>(other->AsDoubleConstant()->value_) ==
bit_cast<uint64_t, double>(value_);
}
@@ -2663,77 +2759,6 @@
DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
};
-class HNullConstant : public HConstant {
- public:
- bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
- return true;
- }
-
- size_t ComputeHashCode() const OVERRIDE { return 0; }
-
- DECLARE_INSTRUCTION(NullConstant);
-
- private:
- HNullConstant() : HConstant(Primitive::kPrimNot) {}
-
- friend class HGraph;
- DISALLOW_COPY_AND_ASSIGN(HNullConstant);
-};
-
-// Constants of the type int. Those can be from Dex instructions, or
-// synthesized (for example with the if-eqz instruction).
-class HIntConstant : public HConstant {
- public:
- int32_t GetValue() const { return value_; }
-
- bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
- return other->AsIntConstant()->value_ == value_;
- }
-
- size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
-
- bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
- bool IsZero() const OVERRIDE { return GetValue() == 0; }
- bool IsOne() const OVERRIDE { return GetValue() == 1; }
-
- DECLARE_INSTRUCTION(IntConstant);
-
- private:
- explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
-
- const int32_t value_;
-
- friend class HGraph;
- ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
- ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast);
- DISALLOW_COPY_AND_ASSIGN(HIntConstant);
-};
-
-class HLongConstant : public HConstant {
- public:
- int64_t GetValue() const { return value_; }
-
- bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
- return other->AsLongConstant()->value_ == value_;
- }
-
- size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
-
- bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
- bool IsZero() const OVERRIDE { return GetValue() == 0; }
- bool IsOne() const OVERRIDE { return GetValue() == 1; }
-
- DECLARE_INSTRUCTION(LongConstant);
-
- private:
- explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
-
- const int64_t value_;
-
- friend class HGraph;
- DISALLOW_COPY_AND_ASSIGN(HLongConstant);
-};
-
enum class Intrinsics {
#define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name,
#include "intrinsics_list.h"
@@ -3052,8 +3077,14 @@
explicit HNeg(Primitive::Type result_type, HInstruction* input)
: HUnaryOperation(result_type, input) {}
- int32_t Evaluate(int32_t x) const OVERRIDE { return -x; }
- int64_t Evaluate(int64_t x) const OVERRIDE { return -x; }
+ template <typename T> T Compute(T x) const { return -x; }
+
+ HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()));
+ }
DECLARE_INSTRUCTION(Neg);
@@ -3110,11 +3141,13 @@
bool IsCommutative() const OVERRIDE { return true; }
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- return x + y;
+ template <typename T> T Compute(T x, T y) const { return x + y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- return x + y;
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
}
DECLARE_INSTRUCTION(Add);
@@ -3128,11 +3161,13 @@
HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
: HBinaryOperation(result_type, left, right) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- return x - y;
+ template <typename T> T Compute(T x, T y) const { return x - y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- return x - y;
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
}
DECLARE_INSTRUCTION(Sub);
@@ -3148,8 +3183,14 @@
bool IsCommutative() const OVERRIDE { return true; }
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x * y; }
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x * y; }
+ template <typename T> T Compute(T x, T y) const { return x * y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
DECLARE_INSTRUCTION(Mul);
@@ -3162,17 +3203,20 @@
HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
: HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- // Our graph structure ensures we never have 0 for `y` during constant folding.
+ template <typename T>
+ T Compute(T x, T y) const {
+ // Our graph structure ensures we never have 0 for `y` during
+ // constant folding.
DCHECK_NE(y, 0);
// Special case -1 to avoid getting a SIGFPE on x86(_64).
return (y == -1) ? -x : x / y;
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- DCHECK_NE(y, 0);
- // Special case -1 to avoid getting a SIGFPE on x86(_64).
- return (y == -1) ? -x : x / y;
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
}
uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
@@ -3190,16 +3234,20 @@
HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
: HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
+ template <typename T>
+ T Compute(T x, T y) const {
+ // Our graph structure ensures we never have 0 for `y` during
+ // constant folding.
DCHECK_NE(y, 0);
// Special case -1 to avoid getting a SIGFPE on x86(_64).
return (y == -1) ? 0 : x % y;
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- DCHECK_NE(y, 0);
- // Special case -1 to avoid getting a SIGFPE on x86(_64).
- return (y == -1) ? 0 : x % y;
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
}
uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
@@ -3244,8 +3292,27 @@
HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right)
: HBinaryOperation(result_type, left, right) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); }
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); }
+ template <typename T, typename U, typename V>
+ T Compute(T x, U y, V max_shift_value) const {
+ static_assert(std::is_same<V, typename std::make_unsigned<T>::type>::value,
+ "V is not the unsigned integer type corresponding to T");
+ return x << (y & max_shift_value);
+ }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue));
+ }
+ // There is no `Evaluate(HIntConstant* x, HLongConstant* y)`, as this
+ // case is handled as `x << static_cast<int>(y)`.
+ HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ }
DECLARE_INSTRUCTION(Shl);
@@ -3258,8 +3325,27 @@
HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
: HBinaryOperation(result_type, left, right) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); }
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); }
+ template <typename T, typename U, typename V>
+ T Compute(T x, U y, V max_shift_value) const {
+ static_assert(std::is_same<V, typename std::make_unsigned<T>::type>::value,
+ "V is not the unsigned integer type corresponding to T");
+ return x >> (y & max_shift_value);
+ }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue));
+ }
+ // There is no `Evaluate(HIntConstant* x, HLongConstant* y)`, as this
+ // case is handled as `x >> static_cast<int>(y)`.
+ HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ }
DECLARE_INSTRUCTION(Shr);
@@ -3272,16 +3358,27 @@
HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
: HBinaryOperation(result_type, left, right) {}
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
- uint32_t ux = static_cast<uint32_t>(x);
- uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue;
- return static_cast<int32_t>(ux >> uy);
+ template <typename T, typename U, typename V>
+ T Compute(T x, U y, V max_shift_value) const {
+ static_assert(std::is_same<V, typename std::make_unsigned<T>::type>::value,
+ "V is not the unsigned integer type corresponding to T");
+ V ux = static_cast<V>(x);
+ return static_cast<T>(ux >> (y & max_shift_value));
}
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
- uint64_t ux = static_cast<uint64_t>(x);
- uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue;
- return static_cast<int64_t>(ux >> uy);
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue));
+ }
+ // There is no `Evaluate(HIntConstant* x, HLongConstant* y)`, as this
+ // case is handled as `x >>> static_cast<int>(y)`.
+ HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
}
DECLARE_INSTRUCTION(UShr);
@@ -3297,8 +3394,21 @@
bool IsCommutative() const OVERRIDE { return true; }
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; }
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; }
+ template <typename T, typename U>
+ auto Compute(T x, U y) const -> decltype(x & y) { return x & y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HIntConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
DECLARE_INSTRUCTION(And);
@@ -3313,8 +3423,21 @@
bool IsCommutative() const OVERRIDE { return true; }
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; }
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; }
+ template <typename T, typename U>
+ auto Compute(T x, U y) const -> decltype(x | y) { return x | y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HIntConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
DECLARE_INSTRUCTION(Or);
@@ -3329,8 +3452,21 @@
bool IsCommutative() const OVERRIDE { return true; }
- int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; }
- int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; }
+ template <typename T, typename U>
+ auto Compute(T x, U y) const -> decltype(x ^ y) { return x ^ y; }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HIntConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ }
DECLARE_INSTRUCTION(Xor);
@@ -3375,8 +3511,14 @@
return true;
}
- int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
- int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
+ template <typename T> T Compute(T x) const { return ~x; }
+
+ HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()));
+ }
DECLARE_INSTRUCTION(Not);
@@ -3395,13 +3537,16 @@
return true;
}
- int32_t Evaluate(int32_t x) const OVERRIDE {
+ template <typename T> bool Compute(T x) const {
DCHECK(IsUint<1>(x));
return !x;
}
- int64_t Evaluate(int64_t x ATTRIBUTE_UNUSED) const OVERRIDE {
- LOG(FATAL) << DebugName() << " cannot be used with 64-bit values";
+ HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()));
+ }
+ HConstant* Evaluate(HLongConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for long values";
UNREACHABLE();
}