diff options
| author | 2015-09-08 17:33:16 +0600 | |
|---|---|---|
| committer | 2016-01-12 13:07:06 +0000 | |
| commit | f9f196c55f3b25c3b09350cd8ed5d7ead31f1757 (patch) | |
| tree | 0be051a729b2f2674c3148d8734e5520713ad546 /compiler/optimizing | |
| parent | c3ba07ef76549129705af28173070b88a1c39531 (diff) | |
Change condition to opposite if lhs is constant
Swap operands if lhs is constant. Handeled unsigned comparison
in insruction simplifier. Fixed NaN comparison: no matter what
bias is set result of Equal and NotEqual operations should not
depend on it. Added checker tests.
Change-Id: I5a9ac25fb10f2705127a52534867cee43368ed1b
Signed-off-by: Anton Shamin <anton.shamin@intel.com>
Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com>
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 72 | ||||
| -rw-r--r-- | compiler/optimizing/nodes.h | 16 |
2 files changed, 84 insertions, 4 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index c504ded54c..10a06a31d9 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -66,6 +66,10 @@ class InstructionSimplifierVisitor : public HGraphDelegateVisitor { void VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) OVERRIDE; void VisitLessThan(HLessThan* condition) OVERRIDE; void VisitLessThanOrEqual(HLessThanOrEqual* condition) OVERRIDE; + void VisitBelow(HBelow* condition) OVERRIDE; + void VisitBelowOrEqual(HBelowOrEqual* condition) OVERRIDE; + void VisitAbove(HAbove* condition) OVERRIDE; + void VisitAboveOrEqual(HAboveOrEqual* condition) OVERRIDE; void VisitDiv(HDiv* instruction) OVERRIDE; void VisitMul(HMul* instruction) OVERRIDE; void VisitNeg(HNeg* instruction) OVERRIDE; @@ -510,6 +514,36 @@ void InstructionSimplifierVisitor::VisitSuspendCheck(HSuspendCheck* check) { block->RemoveInstruction(check); } +static HCondition* GetOppositeConditionSwapOps(ArenaAllocator* arena, HInstruction* cond) { + HInstruction *lhs = cond->InputAt(0); + HInstruction *rhs = cond->InputAt(1); + switch (cond->GetKind()) { + case HInstruction::kEqual: + return new (arena) HEqual(rhs, lhs); + case HInstruction::kNotEqual: + return new (arena) HNotEqual(rhs, lhs); + case HInstruction::kLessThan: + return new (arena) HGreaterThan(rhs, lhs); + case HInstruction::kLessThanOrEqual: + return new (arena) HGreaterThanOrEqual(rhs, lhs); + case HInstruction::kGreaterThan: + return new (arena) HLessThan(rhs, lhs); + case HInstruction::kGreaterThanOrEqual: + return new (arena) HLessThanOrEqual(rhs, lhs); + case HInstruction::kBelow: + return new (arena) HAbove(rhs, lhs); + case HInstruction::kBelowOrEqual: + return new (arena) HAboveOrEqual(rhs, lhs); + case HInstruction::kAbove: + return new (arena) HBelow(rhs, lhs); + case HInstruction::kAboveOrEqual: + return new (arena) HBelowOrEqual(rhs, lhs); + default: + LOG(FATAL) << "Unknown ConditionType " << cond->GetKind(); + } + return nullptr; +} + void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) { HInstruction* input_const = equal->GetConstantRight(); if (input_const != nullptr) { @@ -772,13 +806,47 @@ void InstructionSimplifierVisitor::VisitLessThanOrEqual(HLessThanOrEqual* condit VisitCondition(condition); } -// TODO: unsigned comparisons too? +void InstructionSimplifierVisitor::VisitBelow(HBelow* condition) { + VisitCondition(condition); +} + +void InstructionSimplifierVisitor::VisitBelowOrEqual(HBelowOrEqual* condition) { + VisitCondition(condition); +} + +void InstructionSimplifierVisitor::VisitAbove(HAbove* condition) { + VisitCondition(condition); +} + +void InstructionSimplifierVisitor::VisitAboveOrEqual(HAboveOrEqual* condition) { + VisitCondition(condition); +} void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) { - // Try to fold an HCompare into this HCondition. + // Reverse condition if left is constant. Our code generators prefer constant + // on the right hand side. + if (condition->GetLeft()->IsConstant() && !condition->GetRight()->IsConstant()) { + HBasicBlock* block = condition->GetBlock(); + HCondition* replacement = GetOppositeConditionSwapOps(block->GetGraph()->GetArena(), condition); + // If it is a fp we must set the opposite bias. + if (replacement != nullptr) { + if (condition->IsLtBias()) { + replacement->SetBias(ComparisonBias::kGtBias); + } else if (condition->IsGtBias()) { + replacement->SetBias(ComparisonBias::kLtBias); + } + block->ReplaceAndRemoveInstructionWith(condition, replacement); + RecordSimplification(); + + condition = replacement; + } + } HInstruction* left = condition->GetLeft(); HInstruction* right = condition->GetRight(); + + // Try to fold an HCompare into this HCondition. + // We can only replace an HCondition which compares a Compare to 0. // Both 'dx' and 'jack' generate a compare to 0 when compiling a // condition with a long, float or double comparison as input. diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index c06d164523..cfb71791f4 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -2706,6 +2706,8 @@ class HCondition : public HBinaryOperation { bool IsGtBias() const { return bias_ == ComparisonBias::kGtBias; } + bool IsLtBias() const { return bias_ == ComparisonBias::kLtBias; } + void SetBias(ComparisonBias bias) { bias_ = bias; } bool InstructionDataEquals(HInstruction* other) const OVERRIDE { @@ -2715,13 +2717,23 @@ class HCondition : public HBinaryOperation { bool IsFPConditionTrueIfNaN() const { DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())); IfCondition if_cond = GetCondition(); - return IsGtBias() ? ((if_cond == kCondGT) || (if_cond == kCondGE)) : (if_cond == kCondNE); + if (if_cond == kCondNE) { + return true; + } else if (if_cond == kCondEQ) { + return false; + } + return ((if_cond == kCondGT) || (if_cond == kCondGE)) && IsGtBias(); } bool IsFPConditionFalseIfNaN() const { DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())); IfCondition if_cond = GetCondition(); - return IsGtBias() ? ((if_cond == kCondLT) || (if_cond == kCondLE)) : (if_cond == kCondEQ); + if (if_cond == kCondEQ) { + return true; + } else if (if_cond == kCondNE) { + return false; + } + return ((if_cond == kCondLT) || (if_cond == kCondLE)) && IsGtBias(); } private: |