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();