diff options
author | 2015-11-17 11:16:56 -0500 | |
---|---|---|
committer | 2015-11-20 16:48:04 +0000 | |
commit | f652917de5634b30c974c81d35a72871915b352a (patch) | |
tree | c50bcaf37c246df633d42a166334c9b6332e5394 | |
parent | 60c4c6ad2b892bb00a6016a147b1cc089ba6bcb5 (diff) |
Simplify boolean condition compared to 0
CaffeineMarkRR Logic has some boolean flipping which can be helped by
some simplification.
Simplify non-FP (A COND_OP B) != 0 to A OPPOSITE_COND_OP B.
This is better than the original code, which would use a HBooleanNot
after the condition.
Also simplify non-FP (A COND_OP B) == 1 to A OPPOSITE_COND_OP B.
Move GetOppositeCondition to nodes.h/nodes.cc to share with Boolean
Simplification, renaming it to InsertOppositeCondition, as it inserts
the new HInstruction (unless it is a constant).
Change-Id: I34ded7758836e375de0d6fdba9239d2d451928d0
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
-rw-r--r-- | compiler/optimizing/boolean_simplifier.cc | 39 | ||||
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 10 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 39 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 5 | ||||
-rw-r--r-- | test/458-checker-instruction-simplification/src/Main.java | 105 |
5 files changed, 152 insertions, 46 deletions
diff --git a/compiler/optimizing/boolean_simplifier.cc b/compiler/optimizing/boolean_simplifier.cc index f985745e7a..f0cafc847f 100644 --- a/compiler/optimizing/boolean_simplifier.cc +++ b/compiler/optimizing/boolean_simplifier.cc @@ -61,40 +61,6 @@ static bool NegatesCondition(HInstruction* input_true, HInstruction* input_false && input_false->IsIntConstant() && input_false->AsIntConstant()->IsOne(); } -// Returns an instruction with the opposite boolean value from 'cond'. -static HInstruction* GetOppositeCondition(HInstruction* cond) { - HGraph* graph = cond->GetBlock()->GetGraph(); - ArenaAllocator* allocator = graph->GetArena(); - - if (cond->IsCondition()) { - HInstruction* lhs = cond->InputAt(0); - HInstruction* rhs = cond->InputAt(1); - switch (cond->AsCondition()->GetOppositeCondition()) { // get *opposite* - case kCondEQ: return new (allocator) HEqual(lhs, rhs); - case kCondNE: return new (allocator) HNotEqual(lhs, rhs); - case kCondLT: return new (allocator) HLessThan(lhs, rhs); - case kCondLE: return new (allocator) HLessThanOrEqual(lhs, rhs); - case kCondGT: return new (allocator) HGreaterThan(lhs, rhs); - case kCondGE: return new (allocator) HGreaterThanOrEqual(lhs, rhs); - case kCondB: return new (allocator) HBelow(lhs, rhs); - case kCondBE: return new (allocator) HBelowOrEqual(lhs, rhs); - case kCondA: return new (allocator) HAbove(lhs, rhs); - case kCondAE: return new (allocator) HAboveOrEqual(lhs, rhs); - } - } else if (cond->IsIntConstant()) { - HIntConstant* int_const = cond->AsIntConstant(); - if (int_const->IsZero()) { - return graph->GetIntConstant(1); - } else { - DCHECK(int_const->IsOne()); - return graph->GetIntConstant(0); - } - } - // General case when 'cond' is another instruction of type boolean, - // as verified by SSAChecker. - return new (allocator) HBooleanNot(cond); -} - void HBooleanSimplifier::TryRemovingBooleanSelection(HBasicBlock* block) { DCHECK(block->EndsWithIf()); @@ -126,10 +92,7 @@ void HBooleanSimplifier::TryRemovingBooleanSelection(HBasicBlock* block) { HInstruction* replacement; if (NegatesCondition(true_value, false_value)) { - replacement = GetOppositeCondition(if_condition); - if (replacement->GetBlock() == nullptr) { - block->InsertInstructionBefore(replacement, if_instruction); - } + replacement = graph_->InsertOppositeCondition(if_condition, if_instruction); } else if (PreservesCondition(true_value, false_value)) { replacement = if_condition; } else { diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 9ad2dd1c8e..d82b5d2033 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -372,9 +372,8 @@ void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) { block->RemoveInstruction(equal); RecordSimplification(); } else if (input_const->AsIntConstant()->IsZero()) { - // Replace (bool_value == false) with !bool_value - block->ReplaceAndRemoveInstructionWith( - equal, new (block->GetGraph()->GetArena()) HBooleanNot(input_value)); + equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, equal)); + block->RemoveInstruction(equal); RecordSimplification(); } else { // Replace (bool_value == integer_not_zero_nor_one_constant) with false @@ -399,9 +398,8 @@ void InstructionSimplifierVisitor::VisitNotEqual(HNotEqual* not_equal) { // We are comparing the boolean to a constant which is of type int and can // be any constant. if (input_const->AsIntConstant()->IsOne()) { - // Replace (bool_value != true) with !bool_value - block->ReplaceAndRemoveInstructionWith( - not_equal, new (block->GetGraph()->GetArena()) HBooleanNot(input_value)); + not_equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, not_equal)); + block->RemoveInstruction(not_equal); RecordSimplification(); } else if (input_const->AsIntConstant()->IsZero()) { // Replace (bool_value != false) with bool_value diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 0a39ff31bf..1680c07776 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -2090,4 +2090,43 @@ void HInstruction::RemoveEnvironmentUsers() { env_uses_.Clear(); } +// Returns an instruction with the opposite boolean value from 'cond'. +HInstruction* HGraph::InsertOppositeCondition(HInstruction* cond, HInstruction* cursor) { + ArenaAllocator* allocator = GetArena(); + + if (cond->IsCondition() && + !Primitive::IsFloatingPointType(cond->InputAt(0)->GetType())) { + // Can't reverse floating point conditions. We have to use HBooleanNot in that case. + HInstruction* lhs = cond->InputAt(0); + HInstruction* rhs = cond->InputAt(1); + HInstruction* replacement; + switch (cond->AsCondition()->GetOppositeCondition()) { // get *opposite* + case kCondEQ: replacement = new (allocator) HEqual(lhs, rhs); break; + case kCondNE: replacement = new (allocator) HNotEqual(lhs, rhs); break; + case kCondLT: replacement = new (allocator) HLessThan(lhs, rhs); break; + case kCondLE: replacement = new (allocator) HLessThanOrEqual(lhs, rhs); break; + case kCondGT: replacement = new (allocator) HGreaterThan(lhs, rhs); break; + case kCondGE: replacement = new (allocator) HGreaterThanOrEqual(lhs, rhs); break; + case kCondB: replacement = new (allocator) HBelow(lhs, rhs); break; + case kCondBE: replacement = new (allocator) HBelowOrEqual(lhs, rhs); break; + case kCondA: replacement = new (allocator) HAbove(lhs, rhs); break; + case kCondAE: replacement = new (allocator) HAboveOrEqual(lhs, rhs); break; + } + cursor->GetBlock()->InsertInstructionBefore(replacement, cursor); + return replacement; + } else if (cond->IsIntConstant()) { + HIntConstant* int_const = cond->AsIntConstant(); + if (int_const->IsZero()) { + return GetIntConstant(1); + } else { + DCHECK(int_const->IsOne()); + return GetIntConstant(0); + } + } else { + HInstruction* replacement = new (allocator) HBooleanNot(cond); + cursor->GetBlock()->InsertInstructionBefore(replacement, cursor); + return replacement; + } +} + } // namespace art diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 4f894b07c7..744067f59a 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -371,6 +371,11 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { bool HasTryCatch() const { return has_try_catch_; } void SetHasTryCatch(bool value) { has_try_catch_ = value; } + // Returns an instruction with the opposite boolean value from 'cond'. + // The instruction has been inserted into the graph, either as a constant, or + // before cursor. + HInstruction* InsertOppositeCondition(HInstruction* cond, HInstruction* cursor); + private: void FindBackEdges(ArenaBitVector* visited); void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const; diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java index d5fed2adfe..50817097c7 100644 --- a/test/458-checker-instruction-simplification/src/Main.java +++ b/test/458-checker-instruction-simplification/src/Main.java @@ -1245,7 +1245,6 @@ public class Main { return arg * 9; } - /** * Test strength reduction of factors of the form (2^n - 1). */ @@ -1265,6 +1264,91 @@ public class Main { return arg * 31; } + /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier (before) + /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 + /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet + /// CHECK-DAG: <<NE:z\d+>> NotEqual [<<Field>>,<<Const1>>] + /// CHECK-DAG: If [<<NE>>] + + /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier (after) + /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet + /// CHECK-DAG: <<Not:z\d+>> BooleanNot [<<Field>>] + /// CHECK-DAG: If [<<Not>>] + + public static int booleanFieldNotEqualOne() { + return (booleanField == true) ? 13 : 54; + } + + /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier (before) + /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 + /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet + /// CHECK-DAG: <<EQ:z\d+>> Equal [<<Field>>,<<Const0>>] + /// CHECK-DAG: If [<<EQ>>] + + /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier (after) + /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet + /// CHECK-DAG: <<Not:z\d+>> BooleanNot [<<Field>>] + /// CHECK-DAG: If [<<Not>>] + + public static int booleanFieldEqualZero() { + return (booleanField != false) ? 13 : 54; + } + + /// CHECK-START: int Main.intConditionNotEqualOne(int) instruction_simplifier_after_bce (before) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 + /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 + /// CHECK-DAG: <<GT:z\d+>> GreaterThan [<<Arg>>,<<Const42>>] + /// CHECK-DAG: <<NE:z\d+>> NotEqual [<<GT>>,<<Const1>>] + /// CHECK-DAG: If [<<NE>>] + + /// CHECK-START: int Main.intConditionNotEqualOne(int) instruction_simplifier_after_bce (after) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 + /// CHECK-DAG: If [<<LE:z\d+>>] + /// CHECK-DAG: <<LE>> LessThanOrEqual [<<Arg>>,<<Const42>>] + // Note that we match `LE` from If because there are two identical LessThanOrEqual instructions. + + public static int intConditionNotEqualOne(int i) { + return ((i > 42) == true) ? 13 : 54; + } + + /// CHECK-START: int Main.intConditionEqualZero(int) instruction_simplifier_after_bce (before) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 + /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 + /// CHECK-DAG: <<GT:z\d+>> GreaterThan [<<Arg>>,<<Const42>>] + /// CHECK-DAG: <<EQ:z\d+>> Equal [<<GT>>,<<Const0>>] + /// CHECK-DAG: If [<<EQ>>] + + /// CHECK-START: int Main.intConditionEqualZero(int) instruction_simplifier_after_bce (after) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 + /// CHECK-DAG: If [<<LE:z\d+>>] + /// CHECK-DAG: <<LE>> LessThanOrEqual [<<Arg>>,<<Const42>>] + // Note that we match `LE` from If because there are two identical LessThanOrEqual instructions. + + public static int intConditionEqualZero(int i) { + return ((i > 42) != false) ? 13 : 54; + } + + // Test that conditions on float/double are not flipped. + + /// CHECK-START: int Main.floatConditionNotEqualOne(float) register (before) + /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 + /// CHECK-DAG: NotEqual [{{i\d+}},<<Const1>>] + + public static int floatConditionNotEqualOne(float f) { + return ((f > 42.0f) == true) ? 13 : 54; + } + + /// CHECK-START: int Main.doubleConditionEqualZero(double) register (before) + /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 + /// CHECK-DAG: Equal [{{i\d+}},<<Const0>>] + + public static int doubleConditionEqualZero(double d) { + return ((d > 42.0) != false) ? 13 : 54; + } public static void main(String[] args) { int arg = 123456; @@ -1333,5 +1417,22 @@ public class Main { assertLongEquals(62, mulPow2Minus1(2)); assertLongEquals(3100, mulPow2Minus1(100)); assertLongEquals(382695, mulPow2Minus1(12345)); - } + + booleanField = false; + assertIntEquals(booleanFieldNotEqualOne(), 54); + assertIntEquals(booleanFieldEqualZero(), 54); + booleanField = true; + assertIntEquals(booleanFieldNotEqualOne(), 13); + assertIntEquals(booleanFieldEqualZero(), 13); + assertIntEquals(intConditionNotEqualOne(6), 54); + assertIntEquals(intConditionNotEqualOne(43), 13); + assertIntEquals(intConditionEqualZero(6), 54); + assertIntEquals(intConditionEqualZero(43), 13); + assertIntEquals(floatConditionNotEqualOne(6.0f), 54); + assertIntEquals(floatConditionNotEqualOne(43.0f), 13); + assertIntEquals(doubleConditionEqualZero(6.0), 54); + assertIntEquals(doubleConditionEqualZero(43.0), 13); + } + + public static boolean booleanField; } |