Extend constant folding to float and double operations.
Change-Id: I2837064b2ceea587bc171fc520507f13355292c6
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc
index 57452cc..014353d 100644
--- a/compiler/optimizing/constant_folding.cc
+++ b/compiler/optimizing/constant_folding.cc
@@ -178,7 +178,7 @@
((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->IsNaN()) ||
(input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->IsNaN()))) {
// Replace code looking like
- // CMP{G,L} dst, src, NaN
+ // CMP{G,L}-{FLOAT,DOUBLE} dst, src, NaN
// with
// CONSTANT +1 (gt bias)
// or
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 4cf0eb1..c0263e4 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -384,6 +384,13 @@
<< array_set->GetValueCanBeNull() << std::noboolalpha;
}
+ void VisitCompare(HCompare* compare) OVERRIDE {
+ ComparisonBias bias = compare->GetBias();
+ StartAttributeStream("bias") << (bias == ComparisonBias::kGtBias
+ ? "gt"
+ : (bias == ComparisonBias::kLtBias ? "lt" : "none"));
+ }
+
void VisitInvoke(HInvoke* invoke) OVERRIDE {
StartAttributeStream("dex_file_index") << invoke->GetDexMethodIndex();
StartAttributeStream("method_name") << PrettyMethod(
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 27015c0..b26ce0a 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -15,6 +15,8 @@
*/
#include "nodes.h"
+#include <cfloat>
+
#include "code_generator.h"
#include "common_dominator.h"
#include "ssa_builder.h"
@@ -27,6 +29,12 @@
namespace art {
+// Enable floating-point static evaluation during constant folding
+// only if all floating-point operations and constants evaluate in the
+// range and precision of the type used (i.e., 32-bit float, 64-bit
+// double).
+static constexpr bool kEnableFloatingPointStaticEvaluation = (FLT_EVAL_METHOD == 0);
+
void HGraph::InitializeInexactObjectRTI(StackHandleScopeCollection* handles) {
ScopedObjectAccess soa(Thread::Current());
// Create the inexact Object reference type and store it in the HGraph.
@@ -1159,6 +1167,12 @@
return Evaluate(GetInput()->AsIntConstant());
} else if (GetInput()->IsLongConstant()) {
return Evaluate(GetInput()->AsLongConstant());
+ } else if (kEnableFloatingPointStaticEvaluation) {
+ if (GetInput()->IsFloatConstant()) {
+ return Evaluate(GetInput()->AsFloatConstant());
+ } else if (GetInput()->IsDoubleConstant()) {
+ return Evaluate(GetInput()->AsDoubleConstant());
+ }
}
return nullptr;
}
@@ -1178,6 +1192,12 @@
}
} else if (GetLeft()->IsNullConstant() && GetRight()->IsNullConstant()) {
return Evaluate(GetLeft()->AsNullConstant(), GetRight()->AsNullConstant());
+ } else if (kEnableFloatingPointStaticEvaluation) {
+ if (GetLeft()->IsFloatConstant() && GetRight()->IsFloatConstant()) {
+ return Evaluate(GetLeft()->AsFloatConstant(), GetRight()->AsFloatConstant());
+ } else if (GetLeft()->IsDoubleConstant() && GetRight()->IsDoubleConstant()) {
+ return Evaluate(GetLeft()->AsDoubleConstant(), GetRight()->AsDoubleConstant());
+ }
}
return nullptr;
}
@@ -1205,6 +1225,20 @@
}
}
+std::ostream& operator<<(std::ostream& os, const ComparisonBias& rhs) {
+ switch (rhs) {
+ case ComparisonBias::kNoBias:
+ return os << "no_bias";
+ case ComparisonBias::kGtBias:
+ return os << "gt_bias";
+ case ComparisonBias::kLtBias:
+ return os << "lt_bias";
+ default:
+ LOG(FATAL) << "Unknown ComparisonBias: " << static_cast<int>(rhs);
+ UNREACHABLE();
+ }
+}
+
bool HCondition::IsBeforeWhenDisregardMoves(HInstruction* instruction) const {
return this == instruction->GetPreviousDisregardingMoves();
}
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 854854f..01ba704 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2394,7 +2394,7 @@
}
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
- DCHECK(other->IsIntConstant());
+ DCHECK(other->IsIntConstant()) << other->DebugName();
return other->AsIntConstant()->value_ == value_;
}
@@ -2427,7 +2427,7 @@
uint64_t GetValueAsUint64() const OVERRIDE { return value_; }
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
- DCHECK(other->IsLongConstant());
+ DCHECK(other->IsLongConstant()) << other->DebugName();
return other->AsLongConstant()->value_ == value_;
}
@@ -2449,6 +2449,92 @@
DISALLOW_COPY_AND_ASSIGN(HLongConstant);
};
+class HFloatConstant : public HConstant {
+ public:
+ float GetValue() const { return value_; }
+
+ uint64_t GetValueAsUint64() const OVERRIDE {
+ return static_cast<uint64_t>(bit_cast<uint32_t, float>(value_));
+ }
+
+ bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+ DCHECK(other->IsFloatConstant()) << other->DebugName();
+ return other->AsFloatConstant()->GetValueAsUint64() == GetValueAsUint64();
+ }
+
+ size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
+
+ bool IsMinusOne() const OVERRIDE {
+ return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
+ }
+ bool IsZero() const OVERRIDE {
+ return value_ == 0.0f;
+ }
+ bool IsOne() const OVERRIDE {
+ return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
+ }
+ bool IsNaN() const {
+ return std::isnan(value_);
+ }
+
+ DECLARE_INSTRUCTION(FloatConstant);
+
+ private:
+ explicit HFloatConstant(float value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimFloat, dex_pc), value_(value) {}
+ explicit HFloatConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimFloat, dex_pc), value_(bit_cast<float, int32_t>(value)) {}
+
+ const float value_;
+
+ // Only the SsaBuilder and HGraph can create floating-point constants.
+ friend class SsaBuilder;
+ friend class HGraph;
+ DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
+};
+
+class HDoubleConstant : public HConstant {
+ public:
+ double GetValue() const { return value_; }
+
+ uint64_t GetValueAsUint64() const OVERRIDE { return bit_cast<uint64_t, double>(value_); }
+
+ bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+ DCHECK(other->IsDoubleConstant()) << other->DebugName();
+ return other->AsDoubleConstant()->GetValueAsUint64() == GetValueAsUint64();
+ }
+
+ size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
+
+ bool IsMinusOne() const OVERRIDE {
+ return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
+ }
+ bool IsZero() const OVERRIDE {
+ return value_ == 0.0;
+ }
+ bool IsOne() const OVERRIDE {
+ return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
+ }
+ bool IsNaN() const {
+ return std::isnan(value_);
+ }
+
+ DECLARE_INSTRUCTION(DoubleConstant);
+
+ private:
+ explicit HDoubleConstant(double value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimDouble, dex_pc), value_(value) {}
+ explicit HDoubleConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimDouble, dex_pc), value_(bit_cast<double, int64_t>(value)) {}
+
+ const double value_;
+
+ // Only the SsaBuilder and HGraph can create floating-point constants.
+ friend class SsaBuilder;
+ friend class HGraph;
+ DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
+};
+
// Conditional branch. A block ending with an HIf instruction must have
// two successors.
class HIf : public HTemplateInstruction<1> {
@@ -2650,14 +2736,16 @@
return true;
}
- // Try to statically evaluate `operation` and return a HConstant
- // containing the result of this evaluation. If `operation` cannot
+ // Try to statically evaluate `this` and return a HConstant
+ // containing the result of this evaluation. If `this` cannot
// be evaluated as a constant, return null.
HConstant* TryStaticEvaluation() const;
// Apply this operation to `x`.
virtual HConstant* Evaluate(HIntConstant* x) const = 0;
virtual HConstant* Evaluate(HLongConstant* x) const = 0;
+ virtual HConstant* Evaluate(HFloatConstant* x) const = 0;
+ virtual HConstant* Evaluate(HDoubleConstant* x) const = 0;
DECLARE_ABSTRACT_INSTRUCTION(UnaryOperation);
@@ -2720,12 +2808,17 @@
return true;
}
- // Try to statically evaluate `operation` and return a HConstant
- // containing the result of this evaluation. If `operation` cannot
+ // Try to statically evaluate `this` and return a HConstant
+ // containing the result of this evaluation. If `this` cannot
// be evaluated as a constant, return null.
HConstant* TryStaticEvaluation() const;
// Apply this operation to `x` and `y`.
+ virtual HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
+ HNullConstant* y ATTRIBUTE_UNUSED) const {
+ VLOG(compiler) << DebugName() << " is not defined for the (null, null) case.";
+ return nullptr;
+ }
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,
@@ -2738,11 +2831,8 @@
VLOG(compiler) << DebugName() << " is not defined for the (long, int) case.";
return nullptr;
}
- virtual HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
- HNullConstant* y ATTRIBUTE_UNUSED) const {
- VLOG(compiler) << DebugName() << " is not defined for the (null, null) case.";
- return nullptr;
- }
+ virtual HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const = 0;
+ virtual HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const = 0;
// Returns an input that can legally be used as the right input and is
// constant, or null.
@@ -2766,6 +2856,8 @@
kLtBias, // return -1 for NaN comparisons
};
+std::ostream& operator<<(std::ostream& os, const ComparisonBias& rhs);
+
class HCondition : public HBinaryOperation {
public:
HCondition(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
@@ -2783,7 +2875,7 @@
virtual IfCondition GetOppositeCondition() const = 0;
bool IsGtBias() const { return bias_ == ComparisonBias::kGtBias; }
-
+ ComparisonBias GetBias() const { return bias_; }
void SetBias(ComparisonBias bias) { bias_ = bias; }
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
@@ -2791,17 +2883,34 @@
}
bool IsFPConditionTrueIfNaN() const {
- DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType()));
+ DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
IfCondition if_cond = GetCondition();
return IsGtBias() ? ((if_cond == kCondGT) || (if_cond == kCondGE)) : (if_cond == kCondNE);
}
bool IsFPConditionFalseIfNaN() const {
- DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType()));
+ DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
IfCondition if_cond = GetCondition();
return IsGtBias() ? ((if_cond == kCondLT) || (if_cond == kCondLE)) : (if_cond == kCondEQ);
}
+ protected:
+ template <typename T>
+ int32_t Compare(T x, T y) const { return x > y ? 1 : (x < y ? -1 : 0); }
+
+ template <typename T>
+ int32_t CompareFP(T x, T y) const {
+ DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
+ DCHECK_NE(GetBias(), ComparisonBias::kNoBias);
+ // Handle the bias.
+ return std::isunordered(x, y) ? (IsGtBias() ? 1 : -1) : Compare(x, y);
+ }
+
+ // Return an integer constant containing the result of a condition evaluated at compile time.
+ HIntConstant* MakeConstantCondition(bool value, uint32_t dex_pc) const {
+ return GetBlock()->GetGraph()->GetIntConstant(value, dex_pc);
+ }
+
private:
// Needed if we merge a HCompare into a HCondition.
ComparisonBias bias_;
@@ -2817,17 +2926,25 @@
bool IsCommutative() const OVERRIDE { return true; }
- HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
- }
- HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
- }
HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(1);
+ return MakeConstantCondition(true, GetDexPc());
+ }
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ // In the following Evaluate methods, a HCompare instruction has
+ // been merged into this HEqual instruction; evaluate it as
+ // `Compare(x, y) == 0`.
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0),
+ GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
}
DECLARE_INSTRUCTION(Equal);
@@ -2853,17 +2970,24 @@
bool IsCommutative() const OVERRIDE { return true; }
- HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
- }
- HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
- }
HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(0);
+ return MakeConstantCondition(false, GetDexPc());
+ }
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ // In the following Evaluate methods, a HCompare instruction has
+ // been merged into this HNotEqual instruction; evaluate it as
+ // `Compare(x, y) != 0`.
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
}
DECLARE_INSTRUCTION(NotEqual);
@@ -2888,12 +3012,19 @@
: HCondition(first, second, dex_pc) {}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ // In the following Evaluate methods, a HCompare instruction has
+ // been merged into this HLessThan instruction; evaluate it as
+ // `Compare(x, y) < 0`.
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
}
DECLARE_INSTRUCTION(LessThan);
@@ -2918,12 +3049,19 @@
: HCondition(first, second, dex_pc) {}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ // In the following Evaluate methods, a HCompare instruction has
+ // been merged into this HLessThanOrEqual instruction; evaluate it as
+ // `Compare(x, y) <= 0`.
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
}
DECLARE_INSTRUCTION(LessThanOrEqual);
@@ -2948,12 +3086,19 @@
: HCondition(first, second, dex_pc) {}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ // In the following Evaluate methods, a HCompare instruction has
+ // been merged into this HGreaterThan instruction; evaluate it as
+ // `Compare(x, y) > 0`.
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
}
DECLARE_INSTRUCTION(GreaterThan);
@@ -2978,12 +3123,19 @@
: HCondition(first, second, dex_pc) {}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ // In the following Evaluate methods, a HCompare instruction has
+ // been merged into this HGreaterThanOrEqual instruction; evaluate it as
+ // `Compare(x, y) >= 0`.
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
}
DECLARE_INSTRUCTION(GreaterThanOrEqual);
@@ -3008,14 +3160,20 @@
: HCondition(first, second, dex_pc) {}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(static_cast<uint32_t>(x->GetValue()),
- static_cast<uint32_t>(y->GetValue())), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(static_cast<uint64_t>(x->GetValue()),
- static_cast<uint64_t>(y->GetValue())), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
}
DECLARE_INSTRUCTION(Below);
@@ -3029,7 +3187,9 @@
}
private:
- template <typename T> bool Compute(T x, T y) const { return x < y; }
+ template <typename T> bool Compute(T x, T y) const {
+ return MakeUnsigned(x) < MakeUnsigned(y);
+ }
DISALLOW_COPY_AND_ASSIGN(HBelow);
};
@@ -3040,14 +3200,20 @@
: HCondition(first, second, dex_pc) {}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(static_cast<uint32_t>(x->GetValue()),
- static_cast<uint32_t>(y->GetValue())), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(static_cast<uint64_t>(x->GetValue()),
- static_cast<uint64_t>(y->GetValue())), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
}
DECLARE_INSTRUCTION(BelowOrEqual);
@@ -3061,7 +3227,9 @@
}
private:
- template <typename T> bool Compute(T x, T y) const { return x <= y; }
+ template <typename T> bool Compute(T x, T y) const {
+ return MakeUnsigned(x) <= MakeUnsigned(y);
+ }
DISALLOW_COPY_AND_ASSIGN(HBelowOrEqual);
};
@@ -3072,14 +3240,20 @@
: HCondition(first, second, dex_pc) {}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(static_cast<uint32_t>(x->GetValue()),
- static_cast<uint32_t>(y->GetValue())), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(static_cast<uint64_t>(x->GetValue()),
- static_cast<uint64_t>(y->GetValue())), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
}
DECLARE_INSTRUCTION(Above);
@@ -3093,7 +3267,9 @@
}
private:
- template <typename T> bool Compute(T x, T y) const { return x > y; }
+ template <typename T> bool Compute(T x, T y) const {
+ return MakeUnsigned(x) > MakeUnsigned(y);
+ }
DISALLOW_COPY_AND_ASSIGN(HAbove);
};
@@ -3104,14 +3280,20 @@
: HCondition(first, second, dex_pc) {}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(static_cast<uint32_t>(x->GetValue()),
- static_cast<uint32_t>(y->GetValue())), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(static_cast<uint64_t>(x->GetValue()),
- static_cast<uint64_t>(y->GetValue())), GetDexPc());
+ return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
}
DECLARE_INSTRUCTION(AboveOrEqual);
@@ -3125,7 +3307,9 @@
}
private:
- template <typename T> bool Compute(T x, T y) const { return x >= y; }
+ template <typename T> bool Compute(T x, T y) const {
+ return MakeUnsigned(x) >= MakeUnsigned(y);
+ }
DISALLOW_COPY_AND_ASSIGN(HAboveOrEqual);
};
@@ -3150,15 +3334,32 @@
}
template <typename T>
- int32_t Compute(T x, T y) const { return x == y ? 0 : x > y ? 1 : -1; }
+ int32_t Compute(T x, T y) const { return x > y ? 1 : (x < y ? -1 : 0); }
+
+ template <typename T>
+ int32_t ComputeFP(T x, T y) const {
+ DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
+ DCHECK_NE(GetBias(), ComparisonBias::kNoBias);
+ // Handle the bias.
+ return std::isunordered(x, y) ? (IsGtBias() ? 1 : -1) : Compute(x, y);
+ }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ // Note that there is no "cmp-int" Dex instruction so we shouldn't
+ // reach this code path when processing a freshly built HIR
+ // graph. However HCompare integer instructions can be synthesized
+ // by the instruction simplifier to implement IntegerCompare and
+ // IntegerSignum intrinsics, so we have to handle this case.
+ return MakeConstantComparison(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ return MakeConstantComparison(Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return MakeConstantComparison(ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return MakeConstantComparison(ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
}
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
@@ -3167,8 +3368,12 @@
ComparisonBias GetBias() const { return bias_; }
- bool IsGtBias() { return bias_ == ComparisonBias::kGtBias; }
-
+ // Does this compare instruction have a "gt bias" (vs an "lt bias")?
+ // Only meaninfgul for floating-point comparisons.
+ bool IsGtBias() const {
+ DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
+ return bias_ == ComparisonBias::kGtBias;
+ }
static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type type) {
// MIPS64 uses a runtime call for FP comparisons.
@@ -3177,6 +3382,13 @@
DECLARE_INSTRUCTION(Compare);
+ protected:
+ // Return an integer constant containing the result of a comparison evaluated at compile time.
+ HIntConstant* MakeConstantComparison(int32_t value, uint32_t dex_pc) const {
+ DCHECK(value == -1 || value == 0 || value == 1) << value;
+ return GetBlock()->GetGraph()->GetIntConstant(value, dex_pc);
+ }
+
private:
const ComparisonBias bias_;
@@ -3234,92 +3446,6 @@
DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
};
-class HFloatConstant : public HConstant {
- public:
- float GetValue() const { return value_; }
-
- uint64_t GetValueAsUint64() const OVERRIDE {
- return static_cast<uint64_t>(bit_cast<uint32_t, float>(value_));
- }
-
- bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
- DCHECK(other->IsFloatConstant());
- return other->AsFloatConstant()->GetValueAsUint64() == GetValueAsUint64();
- }
-
- size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
-
- bool IsMinusOne() const OVERRIDE {
- return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
- }
- bool IsZero() const OVERRIDE {
- return value_ == 0.0f;
- }
- bool IsOne() const OVERRIDE {
- return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
- }
- bool IsNaN() const {
- return std::isnan(value_);
- }
-
- DECLARE_INSTRUCTION(FloatConstant);
-
- private:
- explicit HFloatConstant(float value, uint32_t dex_pc = kNoDexPc)
- : HConstant(Primitive::kPrimFloat, dex_pc), value_(value) {}
- explicit HFloatConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
- : HConstant(Primitive::kPrimFloat, dex_pc), value_(bit_cast<float, int32_t>(value)) {}
-
- const float value_;
-
- // Only the SsaBuilder and HGraph can create floating-point constants.
- friend class SsaBuilder;
- friend class HGraph;
- DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
-};
-
-class HDoubleConstant : public HConstant {
- public:
- double GetValue() const { return value_; }
-
- uint64_t GetValueAsUint64() const OVERRIDE { return bit_cast<uint64_t, double>(value_); }
-
- bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
- DCHECK(other->IsDoubleConstant());
- return other->AsDoubleConstant()->GetValueAsUint64() == GetValueAsUint64();
- }
-
- size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
-
- bool IsMinusOne() const OVERRIDE {
- return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
- }
- bool IsZero() const OVERRIDE {
- return value_ == 0.0;
- }
- bool IsOne() const OVERRIDE {
- return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
- }
- bool IsNaN() const {
- return std::isnan(value_);
- }
-
- DECLARE_INSTRUCTION(DoubleConstant);
-
- private:
- explicit HDoubleConstant(double value, uint32_t dex_pc = kNoDexPc)
- : HConstant(Primitive::kPrimDouble, dex_pc), value_(value) {}
- explicit HDoubleConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
- : HConstant(Primitive::kPrimDouble, dex_pc), value_(bit_cast<double, int64_t>(value)) {}
-
- const double value_;
-
- // Only the SsaBuilder and HGraph can create floating-point constants.
- friend class SsaBuilder;
- friend class HGraph;
- DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
-};
-
class HNewInstance : public HExpression<2> {
public:
HNewInstance(HInstruction* cls,
@@ -3871,6 +3997,12 @@
HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetFloatConstant(Compute(x->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetDoubleConstant(Compute(x->GetValue()), GetDexPc());
+ }
DECLARE_INSTRUCTION(Neg);
@@ -3937,6 +4069,14 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetFloatConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetDoubleConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
DECLARE_INSTRUCTION(Add);
@@ -3962,6 +4102,14 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetFloatConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetDoubleConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
DECLARE_INSTRUCTION(Sub);
@@ -3989,6 +4137,14 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetFloatConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetDoubleConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ }
DECLARE_INSTRUCTION(Mul);
@@ -4005,7 +4161,8 @@
: HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls(), dex_pc) {}
template <typename T>
- T Compute(T x, T y) const {
+ T ComputeIntegral(T x, T y) const {
+ DCHECK(!Primitive::IsFloatingPointType(GetType())) << GetType();
// Our graph structure ensures we never have 0 for `y` during
// constant folding.
DCHECK_NE(y, 0);
@@ -4013,13 +4170,27 @@
return (y == -1) ? -x : x / y;
}
+ template <typename T>
+ T ComputeFP(T x, T y) const {
+ DCHECK(Primitive::IsFloatingPointType(GetType())) << GetType();
+ return x / y;
+ }
+
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetFloatConstant(
+ ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetDoubleConstant(
+ ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
}
static SideEffects SideEffectsForArchRuntimeCalls() {
@@ -4042,7 +4213,8 @@
: HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls(), dex_pc) {}
template <typename T>
- T Compute(T x, T y) const {
+ T ComputeIntegral(T x, T y) const {
+ DCHECK(!Primitive::IsFloatingPointType(GetType())) << GetType();
// Our graph structure ensures we never have 0 for `y` during
// constant folding.
DCHECK_NE(y, 0);
@@ -4050,15 +4222,28 @@
return (y == -1) ? 0 : x % y;
}
+ template <typename T>
+ T ComputeFP(T x, T y) const {
+ DCHECK(Primitive::IsFloatingPointType(GetType())) << GetType();
+ return std::fmod(x, y);
+ }
+
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
+ ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
}
-
+ HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetFloatConstant(
+ ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
+ }
+ HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
+ return GetBlock()->GetGraph()->GetDoubleConstant(
+ ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
+ }
static SideEffects SideEffectsForArchRuntimeCalls() {
return SideEffects::CanTriggerGC();
@@ -4125,6 +4310,16 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
+ }
DECLARE_INSTRUCTION(Shl);
@@ -4161,6 +4356,16 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
+ }
DECLARE_INSTRUCTION(Shr);
@@ -4198,6 +4403,16 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
+ }
DECLARE_INSTRUCTION(UShr);
@@ -4234,6 +4449,16 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
+ }
DECLARE_INSTRUCTION(And);
@@ -4270,6 +4495,16 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
+ }
DECLARE_INSTRUCTION(Or);
@@ -4306,6 +4541,16 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
+ }
DECLARE_INSTRUCTION(Xor);
@@ -4344,6 +4589,16 @@
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
+ HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
+ HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
+ }
DECLARE_INSTRUCTION(Ror);
@@ -4410,6 +4665,14 @@
HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
}
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
+ }
DECLARE_INSTRUCTION(Not);
@@ -4428,7 +4691,7 @@
}
template <typename T> bool Compute(T x) const {
- DCHECK(IsUint<1>(x));
+ DCHECK(IsUint<1>(x)) << x;
return !x;
}
@@ -4439,6 +4702,14 @@
LOG(FATAL) << DebugName() << " is not defined for long values";
UNREACHABLE();
}
+ HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for float values";
+ UNREACHABLE();
+ }
+ HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
+ LOG(FATAL) << DebugName() << " is not defined for double values";
+ UNREACHABLE();
+ }
DECLARE_INSTRUCTION(BooleanNot);
@@ -4786,10 +5057,10 @@
DCHECK_EQ(GetArray(), other->GetArray());
DCHECK_EQ(GetIndex(), other->GetIndex());
if (Primitive::IsIntOrLongType(GetType())) {
- DCHECK(Primitive::IsFloatingPointType(other->GetType()));
+ DCHECK(Primitive::IsFloatingPointType(other->GetType())) << other->GetType();
} else {
- DCHECK(Primitive::IsFloatingPointType(GetType()));
- DCHECK(Primitive::IsIntOrLongType(other->GetType()));
+ DCHECK(Primitive::IsFloatingPointType(GetType())) << GetType();
+ DCHECK(Primitive::IsIntOrLongType(other->GetType())) << other->GetType();
}
}
return result;
@@ -6004,7 +6275,7 @@
} else if (constant->IsLongConstant()) {
return constant->AsLongConstant()->GetValue();
} else {
- DCHECK(constant->IsNullConstant());
+ DCHECK(constant->IsNullConstant()) << constant->DebugName();
return 0;
}
}