ART: Simplify more bool operations
Now that we have the HBooleanNot instruction, the instruction
simplifier can optimize out more conditions comparing a boolean
against a constant, as well as sequences of Boolean negations.
Change-Id: I7f634f6428a3984dd97b27b3d6362491346f1ff6
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index afbc490..b8ae1f6 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -43,6 +43,8 @@
void VisitSuspendCheck(HSuspendCheck* check) OVERRIDE;
void VisitEqual(HEqual* equal) OVERRIDE;
+ void VisitNotEqual(HNotEqual* equal) OVERRIDE;
+ void VisitBooleanNot(HBooleanNot* bool_not) OVERRIDE;
void VisitArraySet(HArraySet* equal) OVERRIDE;
void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
void VisitNullCheck(HNullCheck* instruction) OVERRIDE;
@@ -195,21 +197,62 @@
}
void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) {
- HInstruction* input1 = equal->InputAt(0);
- HInstruction* input2 = equal->InputAt(1);
- if (input1->GetType() == Primitive::kPrimBoolean && input2->IsIntConstant()) {
- if (input2->AsIntConstant()->GetValue() == 1) {
- // Replace (bool_value == 1) with bool_value
- equal->ReplaceWith(equal->InputAt(0));
- equal->GetBlock()->RemoveInstruction(equal);
- } else {
- // We should replace (bool_value == 0) with !bool_value, but we unfortunately
- // do not have such instruction.
- DCHECK_EQ(input2->AsIntConstant()->GetValue(), 0);
+ HInstruction* input_const = equal->GetConstantRight();
+ if (input_const != nullptr) {
+ HInstruction* input_value = equal->GetLeastConstantLeft();
+ if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) {
+ HBasicBlock* block = equal->GetBlock();
+ if (input_const->AsIntConstant()->IsOne()) {
+ // Replace (bool_value == true) with bool_value
+ equal->ReplaceWith(input_value);
+ block->RemoveInstruction(equal);
+ RecordSimplification();
+ } else {
+ // Replace (bool_value == false) with !bool_value
+ DCHECK(input_const->AsIntConstant()->IsZero());
+ block->ReplaceAndRemoveInstructionWith(
+ equal, new (block->GetGraph()->GetArena()) HBooleanNot(input_value));
+ RecordSimplification();
+ }
}
}
}
+void InstructionSimplifierVisitor::VisitNotEqual(HNotEqual* not_equal) {
+ HInstruction* input_const = not_equal->GetConstantRight();
+ if (input_const != nullptr) {
+ HInstruction* input_value = not_equal->GetLeastConstantLeft();
+ if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) {
+ HBasicBlock* block = not_equal->GetBlock();
+ if (input_const->AsIntConstant()->IsOne()) {
+ // Replace (bool_value != true) with !bool_value
+ block->ReplaceAndRemoveInstructionWith(
+ not_equal, new (block->GetGraph()->GetArena()) HBooleanNot(input_value));
+ RecordSimplification();
+ } else {
+ // Replace (bool_value != false) with bool_value
+ DCHECK(input_const->AsIntConstant()->IsZero());
+ not_equal->ReplaceWith(input_value);
+ block->RemoveInstruction(not_equal);
+ RecordSimplification();
+ }
+ }
+ }
+}
+
+void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) {
+ HInstruction* parent = bool_not->InputAt(0);
+ if (parent->IsBooleanNot()) {
+ HInstruction* value = parent->InputAt(0);
+ // Replace (!(!bool_value)) with bool_value
+ bool_not->ReplaceWith(value);
+ bool_not->GetBlock()->RemoveInstruction(bool_not);
+ // It is possible that `parent` is dead at this point but we leave
+ // its removal to DCE for simplicity.
+ RecordSimplification();
+ }
+}
+
void InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) {
HInstruction* input = instruction->InputAt(0);
// If the array is a NewArray with constant size, replace the array length
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 479b87f..31ddbb7 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -102,14 +102,17 @@
if (!lastInstruction->IsIf()) {
return;
}
+
HInstruction* ifInput = lastInstruction->InputAt(0);
- // TODO: Handle more patterns here: HIf(bool) HIf(HNotEqual).
- if (!ifInput->IsEqual()) {
- return;
- }
- HInstruction* instanceOf = ifInput->InputAt(0);
- HInstruction* comp_value = ifInput->InputAt(1);
- if (!instanceOf->IsInstanceOf() || !comp_value->IsIntConstant()) {
+ HInstruction* instanceOf;
+ HBasicBlock* instanceOfTrueBlock;
+ if (ifInput->IsInstanceOf()) {
+ instanceOf = ifInput;
+ instanceOfTrueBlock = lastInstruction->AsIf()->IfTrueSuccessor();
+ } else if (ifInput->IsBooleanNot() && ifInput->InputAt(0)->IsInstanceOf()) {
+ instanceOf = ifInput->InputAt(0);
+ instanceOfTrueBlock = lastInstruction->AsIf()->IfFalseSuccessor();
+ } else {
return;
}
@@ -132,11 +135,6 @@
}
block->InsertInstructionBefore(bound_type, lastInstruction);
- // Pick the right successor based on the value we compare against.
- HIntConstant* comp_value_int = comp_value->AsIntConstant();
- HBasicBlock* instanceOfTrueBlock = comp_value_int->GetValue() == 0
- ? lastInstruction->AsIf()->IfFalseSuccessor()
- : lastInstruction->AsIf()->IfTrueSuccessor();
for (HUseIterator<HInstruction*> it(obj->GetUses()); !it.Done(); it.Advance()) {
HInstruction* user = it.Current()->GetUser();