Fuse long and FP compare & condition on ARM in Optimizing.

Also:
- Stylistic changes in corresponding parts on the x86 and
  x86-64 code generators.
- Update and improve the documentation of
  art::arm::Condition.

Bug: 21120453
Change-Id: If144772046e7d21362c3c2086246cb7d011d49ce
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index be71443..fd4bd18 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -344,7 +344,7 @@
 #undef __
 #define __ down_cast<X86Assembler*>(GetAssembler())->
 
-inline Condition X86Condition(IfCondition cond) {
+inline Condition X86SignedCondition(IfCondition cond) {
   switch (cond) {
     case kCondEQ: return kEqual;
     case kCondNE: return kNotEqual;
@@ -352,10 +352,22 @@
     case kCondLE: return kLessEqual;
     case kCondGT: return kGreater;
     case kCondGE: return kGreaterEqual;
-    default:
-      LOG(FATAL) << "Unknown if condition";
   }
-  return kEqual;
+  LOG(FATAL) << "Unreachable";
+  UNREACHABLE();
+}
+
+inline Condition X86UnsignedOrFPCondition(IfCondition cond) {
+  switch (cond) {
+    case kCondEQ: return kEqual;
+    case kCondNE: return kNotEqual;
+    case kCondLT: return kBelow;
+    case kCondLE: return kBelowEqual;
+    case kCondGT: return kAbove;
+    case kCondGE: return kAboveEqual;
+  }
+  LOG(FATAL) << "Unreachable";
+  UNREACHABLE();
 }
 
 void CodeGeneratorX86::DumpCoreRegister(std::ostream& stream, int reg) const {
@@ -892,46 +904,12 @@
 void InstructionCodeGeneratorX86::GenerateFPJumps(HCondition* cond,
                                                   Label* true_label,
                                                   Label* false_label) {
-  bool gt_bias = cond->IsGtBias();
-  IfCondition if_cond = cond->GetCondition();
-  Condition ccode = X86Condition(if_cond);
-  switch (if_cond) {
-    case kCondEQ:
-      if (!gt_bias) {
-        __ j(kParityEven, false_label);
-      }
-      break;
-    case kCondNE:
-      if (!gt_bias) {
-        __ j(kParityEven, true_label);
-      }
-      break;
-    case kCondLT:
-      if (gt_bias) {
-        __ j(kParityEven, false_label);
-      }
-      ccode = kBelow;
-      break;
-    case kCondLE:
-      if (gt_bias) {
-        __ j(kParityEven, false_label);
-      }
-      ccode = kBelowEqual;
-      break;
-    case kCondGT:
-      if (gt_bias) {
-        __ j(kParityEven, true_label);
-      }
-      ccode = kAbove;
-      break;
-    case kCondGE:
-      if (gt_bias) {
-        __ j(kParityEven, true_label);
-      }
-      ccode = kAboveEqual;
-      break;
+  if (cond->IsFPConditionTrueIfNaN()) {
+    __ j(kUnordered, true_label);
+  } else if (cond->IsFPConditionFalseIfNaN()) {
+    __ j(kUnordered, false_label);
   }
-  __ j(ccode, true_label);
+  __ j(X86UnsignedOrFPCondition(cond->GetCondition()), true_label);
 }
 
 void InstructionCodeGeneratorX86::GenerateLongComparesAndJumps(HCondition* cond,
@@ -942,43 +920,37 @@
   Location right = locations->InAt(1);
   IfCondition if_cond = cond->GetCondition();
 
-  Register left_low = left.AsRegisterPairLow<Register>();
   Register left_high = left.AsRegisterPairHigh<Register>();
+  Register left_low = left.AsRegisterPairLow<Register>();
   IfCondition true_high_cond = if_cond;
   IfCondition false_high_cond = cond->GetOppositeCondition();
-  Condition final_condition = X86Condition(if_cond);
+  Condition final_condition = X86UnsignedOrFPCondition(if_cond);
 
   // Set the conditions for the test, remembering that == needs to be
   // decided using the low words.
   switch (if_cond) {
     case kCondEQ:
-      false_high_cond = kCondNE;
-      break;
     case kCondNE:
-      false_high_cond = kCondEQ;
+      // Nothing to do.
       break;
     case kCondLT:
       false_high_cond = kCondGT;
-      final_condition = kBelow;
       break;
     case kCondLE:
       true_high_cond = kCondLT;
-      final_condition = kBelowEqual;
       break;
     case kCondGT:
       false_high_cond = kCondLT;
-      final_condition = kAbove;
       break;
     case kCondGE:
       true_high_cond = kCondGT;
-      final_condition = kAboveEqual;
       break;
   }
 
   if (right.IsConstant()) {
     int64_t value = right.GetConstant()->AsLongConstant()->GetValue();
-    int32_t val_low = Low32Bits(value);
     int32_t val_high = High32Bits(value);
+    int32_t val_low = Low32Bits(value);
 
     if (val_high == 0) {
       __ testl(left_high, left_high);
@@ -986,12 +958,12 @@
       __ cmpl(left_high, Immediate(val_high));
     }
     if (if_cond == kCondNE) {
-      __ j(X86Condition(true_high_cond), true_label);
+      __ j(X86SignedCondition(true_high_cond), true_label);
     } else if (if_cond == kCondEQ) {
-      __ j(X86Condition(false_high_cond), false_label);
+      __ j(X86SignedCondition(false_high_cond), false_label);
     } else {
-      __ j(X86Condition(true_high_cond), true_label);
-      __ j(X86Condition(false_high_cond), false_label);
+      __ j(X86SignedCondition(true_high_cond), true_label);
+      __ j(X86SignedCondition(false_high_cond), false_label);
     }
     // Must be equal high, so compare the lows.
     if (val_low == 0) {
@@ -1000,17 +972,17 @@
       __ cmpl(left_low, Immediate(val_low));
     }
   } else {
-    Register right_low = right.AsRegisterPairLow<Register>();
     Register right_high = right.AsRegisterPairHigh<Register>();
+    Register right_low = right.AsRegisterPairLow<Register>();
 
     __ cmpl(left_high, right_high);
     if (if_cond == kCondNE) {
-      __ j(X86Condition(true_high_cond), true_label);
+      __ j(X86SignedCondition(true_high_cond), true_label);
     } else if (if_cond == kCondEQ) {
-      __ j(X86Condition(false_high_cond), false_label);
+      __ j(X86SignedCondition(false_high_cond), false_label);
     } else {
-      __ j(X86Condition(true_high_cond), true_label);
-      __ j(X86Condition(false_high_cond), false_label);
+      __ j(X86SignedCondition(true_high_cond), true_label);
+      __ j(X86SignedCondition(false_high_cond), false_label);
     }
     // Must be equal high, so compare the lows.
     __ cmpl(left_low, right_low);
@@ -1045,12 +1017,10 @@
       GenerateLongComparesAndJumps(condition, true_target, false_target);
       break;
     case Primitive::kPrimFloat:
-      DCHECK(right.IsFpuRegister());
       __ ucomiss(left.AsFpuRegister<XmmRegister>(), right.AsFpuRegister<XmmRegister>());
       GenerateFPJumps(condition, true_target, false_target);
       break;
     case Primitive::kPrimDouble:
-      DCHECK(right.IsFpuRegister());
       __ ucomisd(left.AsFpuRegister<XmmRegister>(), right.AsFpuRegister<XmmRegister>());
       GenerateFPJumps(condition, true_target, false_target);
       break;
@@ -1080,7 +1050,7 @@
       DCHECK_EQ(cond_value, 0);
     }
   } else {
-    bool materialized =
+    bool is_materialized =
         !cond->IsCondition() || cond->AsCondition()->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
@@ -1089,8 +1059,8 @@
     Primitive::Type type = cond->IsCondition() ? cond->InputAt(0)->GetType() : Primitive::kPrimInt;
     bool eflags_set = cond->IsCondition()
         && cond->AsCondition()->IsBeforeWhenDisregardMoves(instruction)
-        && type == Primitive::kPrimInt;
-    if (materialized) {
+        && (type != Primitive::kPrimLong && !Primitive::IsFloatingPointType(type));
+    if (is_materialized) {
       if (!eflags_set) {
         // Materialized condition, compare against 0.
         Location lhs = instruction->GetLocations()->InAt(0);
@@ -1101,9 +1071,12 @@
         }
         __ j(kNotEqual, true_target);
       } else {
-        __ j(X86Condition(cond->AsCondition()->GetCondition()), true_target);
+        __ j(X86SignedCondition(cond->AsCondition()->GetCondition()), true_target);
       }
     } else {
+      // Condition has not been materialized, use its inputs as the
+      // comparison and its condition as the branch condition.
+
       // Is this a long or FP comparison that has been folded into the HCondition?
       if (type == Primitive::kPrimLong || Primitive::IsFloatingPointType(type)) {
         // Generate the comparison directly.
@@ -1114,6 +1087,7 @@
                                      always_true_target);
         return;
       }
+
       Location lhs = cond->GetLocations()->InAt(0);
       Location rhs = cond->GetLocations()->InAt(1);
       // LHS is guaranteed to be in a register (see
@@ -1130,7 +1104,7 @@
       } else {
         __ cmpl(lhs.AsRegister<Register>(), Address(ESP, rhs.GetStackIndex()));
       }
-      __ j(X86Condition(cond->AsCondition()->GetCondition()), true_target);
+      __ j(X86SignedCondition(cond->AsCondition()->GetCondition()), true_target);
     }
   }
   if (false_target != nullptr) {
@@ -1288,7 +1262,7 @@
       } else {
         __ cmpl(lhs.AsRegister<Register>(), Address(ESP, rhs.GetStackIndex()));
       }
-      __ setb(X86Condition(cond->GetCondition()), reg);
+      __ setb(X86SignedCondition(cond->GetCondition()), reg);
       return;
     }
     case Primitive::kPrimLong:
@@ -1307,12 +1281,12 @@
   // Convert the jumps into the result.
   Label done_label;
 
-  // false case: result = 0;
+  // False case: result = 0.
   __ Bind(&false_label);
   __ xorl(reg, reg);
   __ jmp(&done_label);
 
-  // True case: result = 1
+  // True case: result = 1.
   __ Bind(&true_label);
   __ movl(reg, Immediate(1));
   __ Bind(&done_label);