Fix conditional jump over jmp (X86/X86-64/ARM32)

Optimize the code generation for 'if' statements to jump to the
'false' block if the next block to be generated is the 'true' block.

Add an X86-64 test for this case.

Note that ARM64 & MIPS64 have not been updated.

Change-Id: Iebb1352feb9d3bd0142d8b0621a2e3069a708ea7
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 0df7e3b..0db5837 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1216,16 +1216,21 @@
       DCHECK_EQ(cond_value, 0);
     }
   } else {
+    HCondition* condition = cond->AsCondition();
     bool is_materialized =
-        !cond->IsCondition() || cond->AsCondition()->NeedsMaterialization();
+        condition == nullptr || condition->NeedsMaterialization();
     // Moves do not affect the eflags register, so if the condition is
     // evaluated just before the if, we don't need to evaluate it
     // again.  We can't use the eflags on long/FP conditions if they are
     // materialized due to the complex branching.
-    Primitive::Type type = cond->IsCondition() ? cond->InputAt(0)->GetType() : Primitive::kPrimInt;
-    bool eflags_set = cond->IsCondition()
-        && cond->AsCondition()->IsBeforeWhenDisregardMoves(instruction)
+    Primitive::Type type = (condition != nullptr)
+        ? cond->InputAt(0)->GetType()
+        : Primitive::kPrimInt;
+    bool eflags_set = condition != nullptr
+        && condition->IsBeforeWhenDisregardMoves(instruction)
         && (type != Primitive::kPrimLong && !Primitive::IsFloatingPointType(type));
+    // Can we optimize the jump if we know that the next block is the true case?
+    bool can_jump_to_false = CanReverseCondition(always_true_target, false_target, condition);
     if (is_materialized) {
       if (!eflags_set) {
         // Materialized condition, compare against 0.
@@ -1235,9 +1240,17 @@
         } else {
           __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0));
         }
+        if (can_jump_to_false) {
+          __ j(kEqual, false_target);
+          return;
+        }
         __ j(kNotEqual, true_target);
       } else {
-        __ j(X86Condition(cond->AsCondition()->GetCondition()), true_target);
+        if (can_jump_to_false) {
+          __ j(X86Condition(condition->GetOppositeCondition()), false_target);
+          return;
+        }
+        __ j(X86Condition(condition->GetCondition()), true_target);
       }
     } else {
       // Condition has not been materialized, use its inputs as the
@@ -1247,7 +1260,7 @@
       if (type == Primitive::kPrimLong || Primitive::IsFloatingPointType(type)) {
         // Generate the comparison directly.
         GenerateCompareTestAndBranch(instruction->AsIf(),
-                                     cond->AsCondition(),
+                                     condition,
                                      true_target,
                                      false_target,
                                      always_true_target);
@@ -1270,7 +1283,13 @@
       } else {
         __ cmpl(lhs.AsRegister<Register>(), Address(ESP, rhs.GetStackIndex()));
       }
-      __ j(X86Condition(cond->AsCondition()->GetCondition()), true_target);
+
+      if (can_jump_to_false) {
+        __ j(X86Condition(condition->GetOppositeCondition()), false_target);
+        return;
+      }
+
+      __ j(X86Condition(condition->GetCondition()), true_target);
     }
   }
   if (false_target != nullptr) {