Revert "Revert "Revert "Revert "Change condition to opposite if lhs is constant""""

This reverts commit d4aee949b3dd976295201b5310f13aa2df40afa1.

Change-Id: I505b8c9863c310a3a708f580b00d425b750c9541
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index b95ece5..049901b 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -70,6 +70,10 @@
   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;
@@ -559,6 +563,36 @@
   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) {
@@ -982,13 +1016,47 @@
   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 ecb690f..b3c51a1 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2964,6 +2964,8 @@
   virtual IfCondition GetOppositeCondition() const = 0;
 
   bool IsGtBias() const { return GetBias() == ComparisonBias::kGtBias; }
+  bool IsLtBias() const { return GetBias() == ComparisonBias::kLtBias; }
+
   ComparisonBias GetBias() const { return GetPackedField<ComparisonBiasField>(); }
   void SetBias(ComparisonBias bias) { SetPackedField<ComparisonBiasField>(bias); }
 
@@ -2974,13 +2976,23 @@
   bool IsFPConditionTrueIfNaN() const {
     DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << 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())) << 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();
   }
 
  protected:
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index 8640148..dd4ffe4 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -1601,6 +1601,34 @@
     return (short) (value & 0x17fff);
   }
 
+  /// CHECK-START: int Main.intReverseCondition(int) instruction_simplifier (before)
+  /// CHECK-DAG:      <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:      <<Const42:i\d+>>  IntConstant 42
+  /// CHECK-DAG:      <<LE:z\d+>>       LessThanOrEqual [<<Const42>>,<<Arg>>]
+
+  /// CHECK-START: int Main.intReverseCondition(int) instruction_simplifier (after)
+  /// CHECK-DAG:      <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:      <<Const42:i\d+>>  IntConstant 42
+  /// CHECK-DAG:      <<GE:z\d+>>       GreaterThanOrEqual [<<Arg>>,<<Const42>>]
+
+  public static int intReverseCondition(int i) {
+    return (42 > i) ? 13 : 54;
+  }
+
+  /// CHECK-START: int Main.intReverseConditionNaN(int) instruction_simplifier (before)
+  /// CHECK-DAG:      <<Const42:d\d+>>  DoubleConstant 42
+  /// CHECK-DAG:      <<Result:d\d+>>   InvokeStaticOrDirect
+  /// CHECK-DAG:      <<CMP:i\d+>>      Compare [<<Const42>>,<<Result>>]
+
+  /// CHECK-START: int Main.intReverseConditionNaN(int) instruction_simplifier (after)
+  /// CHECK-DAG:      <<Const42:d\d+>>  DoubleConstant 42
+  /// CHECK-DAG:      <<Result:d\d+>>   InvokeStaticOrDirect
+  /// CHECK-DAG:      <<EQ:z\d+>>       Equal [<<Result>>,<<Const42>>]
+
+  public static int intReverseConditionNaN(int i) {
+    return (42 != Math.sqrt(i)) ? 13 : 54;
+  }
+
   public static int runSmaliTest(String name, boolean input) {
     try {
       Class<?> c = Class.forName("SmaliTests");
@@ -1611,7 +1639,7 @@
     }
   }
 
-  public static void main(String[] args) {
+public static void main(String[] args) {
     int arg = 123456;
 
     assertLongEquals(Add0(arg), arg);
@@ -1740,6 +1768,9 @@
     assertIntEquals(intAnd0x17fffToShort(Integer.MIN_VALUE), 0);
     assertIntEquals(intAnd0x17fffToShort(Integer.MAX_VALUE), Short.MAX_VALUE);
 
+    assertIntEquals(intReverseCondition(41), 13);
+    assertIntEquals(intReverseConditionNaN(-5), 13);
+
     for (String condition : new String[] { "Equal", "NotEqual" }) {
       for (String constant : new String[] { "True", "False" }) {
         for (String side : new String[] { "Rhs", "Lhs" }) {
diff --git a/test/537-checker-jump-over-jump/src/Main.java b/test/537-checker-jump-over-jump/src/Main.java
index cf9a69d..7a58e8b 100644
--- a/test/537-checker-jump-over-jump/src/Main.java
+++ b/test/537-checker-jump-over-jump/src/Main.java
@@ -24,7 +24,7 @@
   //
   /// CHECK:                            If
   /// CHECK-NEXT:                       cmp
-  /// CHECK-NEXT:                       jnl/ge
+  /// CHECK-NEXT:                       jle/ng
   //
   /// CHECK-DAG:   <<Fibs:l\d+>>        StaticFieldGet
   /// CHECK-DAG:                        NullCheck [<<Fibs>>]