Clean up art::HConstant predicates.

- Make the difference between arithmetic zero and zero-bit
  pattern non ambiguous.
- Introduce Boolean predicates in art::HIntConstant for when
  they are used as Booleans.
- Introduce aritmetic positive and negative zero predicates
  for floating-point constants.

Bug: 27639313
Change-Id: Ia04ecc6f6aa7450136028c5362ed429760c883bd
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 99fa9c6..a04918a 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1949,7 +1949,7 @@
       __ And(out, left, right_operand);
       break;
     case HInstruction::kNeg:
-      DCHECK(instruction->InputAt(0)->AsConstant()->IsZero());
+      DCHECK(instruction->InputAt(0)->AsConstant()->IsArithmeticZero());
       __ Neg(out, right_operand);
       break;
     case HInstruction::kOr:
@@ -1994,7 +1994,7 @@
   HInstruction* accumulator = instr->InputAt(HMultiplyAccumulate::kInputAccumulatorIndex);
   if (instr->GetOpKind() == HInstruction::kSub &&
       accumulator->IsConstant() &&
-      accumulator->AsConstant()->IsZero()) {
+      accumulator->AsConstant()->IsArithmeticZero()) {
     // Don't allocate register for Mneg instruction.
   } else {
     locations->SetInAt(HMultiplyAccumulate::kInputAccumulatorIndex,
@@ -2033,7 +2033,7 @@
   } else {
     DCHECK(instr->GetOpKind() == HInstruction::kSub);
     HInstruction* accum_instr = instr->InputAt(HMultiplyAccumulate::kInputAccumulatorIndex);
-    if (accum_instr->IsConstant() && accum_instr->AsConstant()->IsZero()) {
+    if (accum_instr->IsConstant() && accum_instr->AsConstant()->IsArithmeticZero()) {
       __ Mneg(res, mul_left, mul_right);
     } else {
       Register accumulator = InputRegisterAt(instr, HMultiplyAccumulate::kInputAccumulatorIndex);
@@ -2378,9 +2378,35 @@
   GenerateClassInitializationCheck(slow_path, InputRegisterAt(check, 0));
 }
 
-static bool IsFloatingPointZeroConstant(HInstruction* instruction) {
-  return (instruction->IsFloatConstant() && (instruction->AsFloatConstant()->GetValue() == 0.0f))
-      || (instruction->IsDoubleConstant() && (instruction->AsDoubleConstant()->GetValue() == 0.0));
+static bool IsFloatingPointZeroConstant(HInstruction* inst) {
+  return (inst->IsFloatConstant() && (inst->AsFloatConstant()->IsArithmeticZero()))
+      || (inst->IsDoubleConstant() && (inst->AsDoubleConstant()->IsArithmeticZero()));
+}
+
+void InstructionCodeGeneratorARM64::GenerateFcmp(HInstruction* instruction) {
+  FPRegister lhs_reg = InputFPRegisterAt(instruction, 0);
+  Location rhs_loc = instruction->GetLocations()->InAt(1);
+  if (rhs_loc.IsConstant()) {
+    // 0.0 is the only immediate that can be encoded directly in
+    // an FCMP instruction.
+    //
+    // Both the JLS (section 15.20.1) and the JVMS (section 6.5)
+    // specify that in a floating-point comparison, positive zero
+    // and negative zero are considered equal, so we can use the
+    // literal 0.0 for both cases here.
+    //
+    // Note however that some methods (Float.equal, Float.compare,
+    // Float.compareTo, Double.equal, Double.compare,
+    // Double.compareTo, Math.max, Math.min, StrictMath.max,
+    // StrictMath.min) consider 0.0 to be (strictly) greater than
+    // -0.0. So if we ever translate calls to these methods into a
+    // HCompare instruction, we must handle the -0.0 case with
+    // care here.
+    DCHECK(IsFloatingPointZeroConstant(rhs_loc.GetConstant()));
+    __ Fcmp(lhs_reg, 0.0);
+  } else {
+    __ Fcmp(lhs_reg, InputFPRegisterAt(instruction, 1));
+  }
 }
 
 void LocationsBuilderARM64::VisitCompare(HCompare* compare) {
@@ -2430,14 +2456,7 @@
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble: {
       Register result = OutputRegister(compare);
-      FPRegister left = InputFPRegisterAt(compare, 0);
-      if (compare->GetLocations()->InAt(1).IsConstant()) {
-        DCHECK(IsFloatingPointZeroConstant(compare->GetLocations()->InAt(1).GetConstant()));
-        // 0.0 is the only immediate that can be encoded directly in an FCMP instruction.
-        __ Fcmp(left, 0.0);
-      } else {
-        __ Fcmp(left, InputFPRegisterAt(compare, 1));
-      }
+      GenerateFcmp(compare);
       __ Cset(result, ne);
       __ Cneg(result, result, ARM64FPCondition(kCondLT, compare->IsGtBias()));
       break;
@@ -2477,14 +2496,7 @@
   IfCondition if_cond = instruction->GetCondition();
 
   if (Primitive::IsFloatingPointType(instruction->InputAt(0)->GetType())) {
-    FPRegister lhs = InputFPRegisterAt(instruction, 0);
-    if (locations->InAt(1).IsConstant()) {
-      DCHECK(IsFloatingPointZeroConstant(locations->InAt(1).GetConstant()));
-      // 0.0 is the only immediate that can be encoded directly in an FCMP instruction.
-      __ Fcmp(lhs, 0.0);
-    } else {
-      __ Fcmp(lhs, InputFPRegisterAt(instruction, 1));
-    }
+    GenerateFcmp(instruction);
     __ Cset(res, ARM64FPCondition(if_cond, instruction->IsGtBias()));
   } else {
     // Integer cases.
@@ -2815,13 +2827,13 @@
     // Nothing to do. The code always falls through.
     return;
   } else if (cond->IsIntConstant()) {
-    // Constant condition, statically compared against 1.
-    if (cond->AsIntConstant()->IsOne()) {
+    // Constant condition, statically compared against "true" (integer value 1).
+    if (cond->AsIntConstant()->IsTrue()) {
       if (true_target != nullptr) {
         __ B(true_target);
       }
     } else {
-      DCHECK(cond->AsIntConstant()->IsZero());
+      DCHECK(cond->AsIntConstant()->IsFalse()) << cond->AsIntConstant()->GetValue();
       if (false_target != nullptr) {
         __ B(false_target);
       }
@@ -2853,14 +2865,7 @@
 
     Primitive::Type type = condition->InputAt(0)->GetType();
     if (Primitive::IsFloatingPointType(type)) {
-      FPRegister lhs = InputFPRegisterAt(condition, 0);
-      if (condition->GetLocations()->InAt(1).IsConstant()) {
-        DCHECK(IsFloatingPointZeroConstant(condition->GetLocations()->InAt(1).GetConstant()));
-        // 0.0 is the only immediate that can be encoded directly in an FCMP instruction.
-        __ Fcmp(lhs, 0.0);
-      } else {
-        __ Fcmp(lhs, InputFPRegisterAt(condition, 1));
-      }
+      GenerateFcmp(condition);
       if (true_target == nullptr) {
         IfCondition opposite_condition = condition->GetOppositeCondition();
         __ B(ARM64FPCondition(opposite_condition, condition->IsGtBias()), false_target);
@@ -3044,13 +3049,7 @@
       csel_cond = HasSwappedInputs(variant) ? eq : ne;
     }
   } else if (IsConditionOnFloatingPointValues(cond)) {
-    Location rhs = cond->GetLocations()->InAt(1);
-    if (rhs.IsConstant()) {
-      DCHECK(IsFloatingPointZeroConstant(rhs.GetConstant()));
-      __ Fcmp(InputFPRegisterAt(cond, 0), 0.0);
-    } else {
-      __ Fcmp(InputFPRegisterAt(cond, 0), InputFPRegisterAt(cond, 1));
-    }
+    GenerateFcmp(cond);
     csel_cond = GetConditionForSelect(cond->AsCondition(), variant);
   } else {
     __ Cmp(InputRegisterAt(cond, 0), InputOperandAt(cond, 1));