diff options
Diffstat (limited to 'compiler/optimizing/nodes.h')
-rw-r--r-- | compiler/optimizing/nodes.h | 654 |
1 files changed, 472 insertions, 182 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 18b256f48e..399afabea6 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -131,6 +131,7 @@ class HInstructionList : public ValueObject { void SetBlockOfInstructions(HBasicBlock* block) const; void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list); + void AddBefore(HInstruction* cursor, const HInstructionList& instruction_list); void Add(const HInstructionList& instruction_list); // Return the number of instructions in the list. This is an expensive operation. @@ -345,8 +346,9 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { void ComputeTryBlockInformation(); // Inline this graph in `outer_graph`, replacing the given `invoke` instruction. - // Returns the instruction used to replace the invoke expression or null if the - // invoke is for a void method. + // Returns the instruction to replace the invoke expression or null if the + // invoke is for a void method. Note that the caller is responsible for replacing + // and removing the invoke instruction. HInstruction* InlineInto(HGraph* outer_graph, HInvoke* invoke); // Need to add a couple of blocks to test if the loop body is entered and @@ -617,6 +619,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { friend class SsaBuilder; // For caching constants. friend class SsaLivenessAnalysis; // For the linear order. + friend class HInliner; // For the reverse post order. ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1); DISALLOW_COPY_AND_ASSIGN(HGraph); }; @@ -971,12 +974,15 @@ class HBasicBlock : public ArenaObject<kArenaAllocBasicBlock> { // loop and try/catch information. HBasicBlock* SplitBefore(HInstruction* cursor); - // Split the block into two blocks just after `cursor`. Returns the newly + // Split the block into two blocks just before `cursor`. Returns the newly // created block. Note that this method just updates raw block information, // like predecessors, successors, dominators, and instruction list. It does not // update the graph, reverse post order, loop information, nor make sure the // blocks are consistent (for example ending with a control flow instruction). - HBasicBlock* SplitAfter(HInstruction* cursor); + HBasicBlock* SplitBeforeForInlining(HInstruction* cursor); + + // Similar to `SplitBeforeForInlining` but does it after `cursor`. + HBasicBlock* SplitAfterForInlining(HInstruction* cursor); // Split catch block into two blocks after the original move-exception bytecode // instruction, or at the beginning if not present. Returns the newly created, @@ -2062,6 +2068,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { } SideEffects GetSideEffects() const { return side_effects_; } + void SetSideEffects(SideEffects other) { side_effects_ = other; } void AddSideEffects(SideEffects other) { side_effects_.Add(other); } size_t GetLifetimePosition() const { return lifetime_position_; } @@ -2100,7 +2107,6 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { protected: virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0; virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0; - void SetSideEffects(SideEffects other) { side_effects_ = other; } private: void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); } @@ -2393,7 +2399,7 @@ class HIntConstant : public HConstant { } bool InstructionDataEquals(HInstruction* other) const OVERRIDE { - DCHECK(other->IsIntConstant()); + DCHECK(other->IsIntConstant()) << other->DebugName(); return other->AsIntConstant()->value_ == value_; } @@ -2426,7 +2432,7 @@ class HLongConstant : public HConstant { 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_; } @@ -2448,6 +2454,92 @@ class HLongConstant : public HConstant { 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> { @@ -2649,14 +2741,16 @@ class HUnaryOperation : public HExpression<1> { 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); @@ -2719,12 +2813,17 @@ class HBinaryOperation : public HExpression<2> { 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, @@ -2737,11 +2836,8 @@ class HBinaryOperation : public HExpression<2> { 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. @@ -2765,6 +2861,8 @@ enum class ComparisonBias { 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) @@ -2782,7 +2880,7 @@ class HCondition : public HBinaryOperation { 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 { @@ -2790,17 +2888,34 @@ class HCondition : public HBinaryOperation { } 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_; @@ -2816,17 +2931,25 @@ class HEqual : public HCondition { bool IsCommutative() const OVERRIDE { return true; } + HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED, + HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE { + return MakeConstantCondition(true, GetDexPc()); + } 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 HEqual 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(HNullConstant* x ATTRIBUTE_UNUSED, - HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE { - return GetBlock()->GetGraph()->GetIntConstant(1); + 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); @@ -2852,17 +2975,24 @@ class HNotEqual : public HCondition { bool IsCommutative() const OVERRIDE { return true; } + HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED, + HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE { + return MakeConstantCondition(false, GetDexPc()); + } 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 HNotEqual 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(HNullConstant* x ATTRIBUTE_UNUSED, - HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE { - return GetBlock()->GetGraph()->GetIntConstant(0); + 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); @@ -2887,12 +3017,19 @@ class HLessThan : public HCondition { : 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); @@ -2917,12 +3054,19 @@ class HLessThanOrEqual : public HCondition { : 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); @@ -2947,12 +3091,19 @@ class HGreaterThan : public HCondition { : 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); @@ -2977,12 +3128,19 @@ class HGreaterThanOrEqual : public HCondition { : 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); @@ -3007,14 +3165,20 @@ class HBelow : public HCondition { : 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); @@ -3028,7 +3192,9 @@ class HBelow : public HCondition { } 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); }; @@ -3039,14 +3205,20 @@ class HBelowOrEqual : public HCondition { : 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); @@ -3060,7 +3232,9 @@ class HBelowOrEqual : public HCondition { } 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); }; @@ -3071,14 +3245,20 @@ class HAbove : public HCondition { : 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); @@ -3092,7 +3272,9 @@ class HAbove : public HCondition { } 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); }; @@ -3103,14 +3285,20 @@ class HAboveOrEqual : public HCondition { : 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); @@ -3124,7 +3312,9 @@ class HAboveOrEqual : public HCondition { } 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); }; @@ -3149,15 +3339,32 @@ class HCompare : public HBinaryOperation { } 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 { @@ -3166,8 +3373,12 @@ class HCompare : public HBinaryOperation { 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. @@ -3176,6 +3387,13 @@ class HCompare : public HBinaryOperation { 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_; @@ -3233,92 +3451,6 @@ class HStoreLocal : public HTemplateInstruction<2> { 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, @@ -3671,6 +3803,7 @@ class HInvokeStaticOrDirect : public HInvoke { // method pointer; otherwise there may be one platform-specific special input, // such as PC-relative addressing base. uint32_t GetSpecialInputIndex() const { return GetNumberOfArguments(); } + bool HasSpecialInput() const { return GetNumberOfArguments() != InputCount(); } InvokeType GetOptimizedInvokeType() const { return optimized_invoke_type_; } void SetOptimizedInvokeType(InvokeType invoke_type) { @@ -3869,6 +4002,12 @@ class HNeg : public HUnaryOperation { 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); @@ -3935,6 +4074,14 @@ class HAdd : public HBinaryOperation { 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); @@ -3960,6 +4107,14 @@ class HSub : public HBinaryOperation { 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); @@ -3987,6 +4142,14 @@ class HMul : public HBinaryOperation { 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); @@ -4003,7 +4166,8 @@ class HDiv : public HBinaryOperation { : 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); @@ -4011,13 +4175,27 @@ class HDiv : public HBinaryOperation { 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() { @@ -4040,7 +4218,8 @@ class HRem : public HBinaryOperation { : 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); @@ -4048,15 +4227,28 @@ class HRem : public HBinaryOperation { 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(); @@ -4123,6 +4315,16 @@ class HShl : public HBinaryOperation { 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); @@ -4159,6 +4361,16 @@ class HShr : public HBinaryOperation { 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); @@ -4196,6 +4408,16 @@ class HUShr : public HBinaryOperation { 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); @@ -4232,6 +4454,16 @@ class HAnd : public HBinaryOperation { 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); @@ -4268,6 +4500,16 @@ class HOr : public HBinaryOperation { 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); @@ -4304,6 +4546,16 @@ class HXor : public HBinaryOperation { 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); @@ -4342,6 +4594,16 @@ class HRor : public HBinaryOperation { 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); @@ -4408,6 +4670,14 @@ class HNot : public HUnaryOperation { 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); @@ -4426,7 +4696,7 @@ class HBooleanNot : public HUnaryOperation { } template <typename T> bool Compute(T x) const { - DCHECK(IsUint<1>(x)); + DCHECK(IsUint<1>(x)) << x; return !x; } @@ -4437,6 +4707,14 @@ class HBooleanNot : public HUnaryOperation { 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); @@ -4784,10 +5062,10 @@ class HArrayGet : public HExpression<2> { 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; @@ -6002,7 +6280,7 @@ inline int64_t Int64FromConstant(HConstant* constant) { } else if (constant->IsLongConstant()) { return constant->AsLongConstant()->GetValue(); } else { - DCHECK(constant->IsNullConstant()); + DCHECK(constant->IsNullConstant()) << constant->DebugName(); return 0; } } @@ -6097,6 +6375,18 @@ class SwitchTable : public ValueObject { DISALLOW_COPY_AND_ASSIGN(SwitchTable); }; +// Create space in `blocks` for adding `number_of_new_blocks` entries +// starting at location `at`. Blocks after `at` are moved accordingly. +inline void MakeRoomFor(ArenaVector<HBasicBlock*>* blocks, + size_t number_of_new_blocks, + size_t after) { + DCHECK_LT(after, blocks->size()); + size_t old_size = blocks->size(); + size_t new_size = old_size + number_of_new_blocks; + blocks->resize(new_size); + std::copy_backward(blocks->begin() + after + 1u, blocks->begin() + old_size, blocks->end()); +} + } // namespace art #endif // ART_COMPILER_OPTIMIZING_NODES_H_ |