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_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 46f08a8..23528b5 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1412,13 +1412,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);
       }
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));
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 10f1e7f..0af825b 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -257,6 +257,9 @@
                                vixl::Register obj,
                                uint32_t offset);
 
+  // Generate a floating-point comparison.
+  void GenerateFcmp(HInstruction* instruction);
+
   void HandleShift(HBinaryOperation* instr);
   void GenerateImplicitNullCheck(HNullCheck* instruction);
   void GenerateExplicitNullCheck(HNullCheck* instruction);
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index ba6c16e..4b2a461 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -3264,13 +3264,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);
       }
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 90a0941..9c8c466 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -2588,13 +2588,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) {
         __ Bc(true_target);
       }
     } else {
-      DCHECK(cond->AsIntConstant()->IsZero());
+      DCHECK(cond->AsIntConstant()->IsFalse()) << cond->AsIntConstant()->GetValue();
       if (false_target != nullptr) {
         __ Bc(false_target);
       }
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 830e69d..33a977b 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1391,13 +1391,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) {
         __ jmp(true_target);
       }
     } else {
-      DCHECK(cond->AsIntConstant()->IsZero());
+      DCHECK(cond->AsIntConstant()->IsFalse()) << cond->AsIntConstant()->GetValue();
       if (false_target != nullptr) {
         __ jmp(false_target);
       }
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index b1674d6..3d1fe7f 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1402,13 +1402,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) {
         __ jmp(true_target);
       }
     } else {
-      DCHECK(cond->AsIntConstant()->IsZero());
+      DCHECK(cond->AsIntConstant()->IsFalse()) << cond->AsIntConstant()->GetValue();
       if (false_target != nullptr) {
         __ jmp(false_target);
       }
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc
index 7ddabde..0614945 100644
--- a/compiler/optimizing/constant_folding.cc
+++ b/compiler/optimizing/constant_folding.cc
@@ -120,7 +120,7 @@
 void HConstantFoldingVisitor::VisitDivZeroCheck(HDivZeroCheck* inst) {
   // We can safely remove the check if the input is a non-null constant.
   HInstruction* check_input = inst->InputAt(0);
-  if (check_input->IsConstant() && !check_input->AsConstant()->IsZero()) {
+  if (check_input->IsConstant() && !check_input->AsConstant()->IsArithmeticZero()) {
     inst->ReplaceWith(check_input);
     inst->GetBlock()->RemoveInstruction(inst);
   }
@@ -130,7 +130,7 @@
 void InstructionWithAbsorbingInputSimplifier::VisitShift(HBinaryOperation* instruction) {
   DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr());
   HInstruction* left = instruction->GetLeft();
-  if (left->IsConstant() && left->AsConstant()->IsZero()) {
+  if (left->IsConstant() && left->AsConstant()->IsArithmeticZero()) {
     // Replace code looking like
     //    SHL dst, 0, shift_amount
     // with
@@ -142,7 +142,7 @@
 
 void InstructionWithAbsorbingInputSimplifier::VisitAbove(HAbove* instruction) {
   if (instruction->GetLeft()->IsConstant() &&
-      instruction->GetLeft()->AsConstant()->IsZero()) {
+      instruction->GetLeft()->AsConstant()->IsArithmeticZero()) {
     // Replace code looking like
     //    ABOVE dst, 0, src  // unsigned 0 > src is always false
     // with
@@ -154,7 +154,7 @@
 
 void InstructionWithAbsorbingInputSimplifier::VisitAboveOrEqual(HAboveOrEqual* instruction) {
   if (instruction->GetRight()->IsConstant() &&
-      instruction->GetRight()->AsConstant()->IsZero()) {
+      instruction->GetRight()->AsConstant()->IsArithmeticZero()) {
     // Replace code looking like
     //    ABOVE_OR_EQUAL dst, src, 0  // unsigned src >= 0 is always true
     // with
@@ -166,7 +166,7 @@
 
 void InstructionWithAbsorbingInputSimplifier::VisitBelow(HBelow* instruction) {
   if (instruction->GetRight()->IsConstant() &&
-      instruction->GetRight()->AsConstant()->IsZero()) {
+      instruction->GetRight()->AsConstant()->IsArithmeticZero()) {
     // Replace code looking like
     //    BELOW dst, src, 0  // unsigned src < 0 is always false
     // with
@@ -178,7 +178,7 @@
 
 void InstructionWithAbsorbingInputSimplifier::VisitBelowOrEqual(HBelowOrEqual* instruction) {
   if (instruction->GetLeft()->IsConstant() &&
-      instruction->GetLeft()->AsConstant()->IsZero()) {
+      instruction->GetLeft()->AsConstant()->IsArithmeticZero()) {
     // Replace code looking like
     //    BELOW_OR_EQUAL dst, 0, src  // unsigned 0 <= src is always true
     // with
@@ -190,7 +190,7 @@
 
 void InstructionWithAbsorbingInputSimplifier::VisitAnd(HAnd* instruction) {
   HConstant* input_cst = instruction->GetConstantRight();
-  if ((input_cst != nullptr) && input_cst->IsZero()) {
+  if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
     // Replace code looking like
     //    AND dst, src, 0
     // with
@@ -224,7 +224,7 @@
   HConstant* input_cst = instruction->GetConstantRight();
   Primitive::Type type = instruction->GetType();
   if (Primitive::IsIntOrLongType(type) &&
-      (input_cst != nullptr) && input_cst->IsZero()) {
+      (input_cst != nullptr) && input_cst->IsArithmeticZero()) {
     // Replace code looking like
     //    MUL dst, src, 0
     // with
@@ -264,7 +264,7 @@
   HBasicBlock* block = instruction->GetBlock();
 
   if (instruction->GetLeft()->IsConstant() &&
-      instruction->GetLeft()->AsConstant()->IsZero()) {
+      instruction->GetLeft()->AsConstant()->IsArithmeticZero()) {
     // Replace code looking like
     //    REM dst, 0, src
     // with
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index e170e37..5b41736 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -41,11 +41,11 @@
       HIf* if_instruction = last_instruction->AsIf();
       HInstruction* condition = if_instruction->InputAt(0);
       if (condition->IsIntConstant()) {
-        if (condition->AsIntConstant()->IsOne()) {
+        if (condition->AsIntConstant()->IsTrue()) {
           live_successors = live_successors.SubArray(0u, 1u);
           DCHECK_EQ(live_successors[0], if_instruction->IfTrueSuccessor());
         } else {
-          DCHECK(condition->AsIntConstant()->IsZero());
+          DCHECK(condition->AsIntConstant()->IsFalse()) << condition->AsIntConstant()->GetValue();
           live_successors = live_successors.SubArray(1u, 1u);
           DCHECK_EQ(live_successors[0], if_instruction->IfFalseSuccessor());
         }
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index d861e39..a46478e 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -912,8 +912,7 @@
       bool needs_constructor_barrier = false;
       for (size_t i = 0; i != number_of_iputs; ++i) {
         HInstruction* value = GetInvokeInputForArgVRegIndex(invoke_instruction, iput_args[i]);
-        if (!value->IsConstant() ||
-            (!value->AsConstant()->IsZero() && !value->IsNullConstant())) {
+        if (!value->IsConstant() || !value->AsConstant()->IsZeroBitPattern()) {
           if (dex_cache.GetReference() == nullptr) {
             dex_cache = handles_->NewHandle(resolved_method->GetDexCache());
           }
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 9cfc16f..05ee109 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -608,12 +608,12 @@
       HBasicBlock* block = equal->GetBlock();
       // We are comparing the boolean to a constant which is of type int and can
       // be any constant.
-      if (input_const->AsIntConstant()->IsOne()) {
+      if (input_const->AsIntConstant()->IsTrue()) {
         // Replace (bool_value == true) with bool_value
         equal->ReplaceWith(input_value);
         block->RemoveInstruction(equal);
         RecordSimplification();
-      } else if (input_const->AsIntConstant()->IsZero()) {
+      } else if (input_const->AsIntConstant()->IsFalse()) {
         equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, equal));
         block->RemoveInstruction(equal);
         RecordSimplification();
@@ -639,11 +639,11 @@
       HBasicBlock* block = not_equal->GetBlock();
       // We are comparing the boolean to a constant which is of type int and can
       // be any constant.
-      if (input_const->AsIntConstant()->IsOne()) {
+      if (input_const->AsIntConstant()->IsTrue()) {
         not_equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, not_equal));
         block->RemoveInstruction(not_equal);
         RecordSimplification();
-      } else if (input_const->AsIntConstant()->IsZero()) {
+      } else if (input_const->AsIntConstant()->IsFalse()) {
         // Replace (bool_value != false) with bool_value
         not_equal->ReplaceWith(input_value);
         block->RemoveInstruction(not_equal);
@@ -668,10 +668,10 @@
 
   if (input->IsIntConstant()) {
     // Replace !(true/false) with false/true.
-    if (input->AsIntConstant()->IsOne()) {
+    if (input->AsIntConstant()->IsTrue()) {
       replace_with = GetGraph()->GetIntConstant(0);
     } else {
-      DCHECK(input->AsIntConstant()->IsZero());
+      DCHECK(input->AsIntConstant()->IsFalse()) << input->AsIntConstant()->GetValue();
       replace_with = GetGraph()->GetIntConstant(1);
     }
   } else if (input->IsBooleanNot()) {
@@ -712,19 +712,19 @@
     // Replace (cond ? x : x) with (x).
     replace_with = true_value;
   } else if (condition->IsIntConstant()) {
-    if (condition->AsIntConstant()->IsOne()) {
+    if (condition->AsIntConstant()->IsTrue()) {
       // Replace (true ? x : y) with (x).
       replace_with = true_value;
     } else {
       // Replace (false ? x : y) with (y).
-      DCHECK(condition->AsIntConstant()->IsZero());
+      DCHECK(condition->AsIntConstant()->IsFalse()) << condition->AsIntConstant()->GetValue();
       replace_with = false_value;
     }
   } else if (true_value->IsIntConstant() && false_value->IsIntConstant()) {
-    if (true_value->AsIntConstant()->IsOne() && false_value->AsIntConstant()->IsZero()) {
+    if (true_value->AsIntConstant()->IsTrue() && false_value->AsIntConstant()->IsFalse()) {
       // Replace (cond ? true : false) with (cond).
       replace_with = condition;
-    } else if (true_value->AsIntConstant()->IsZero() && false_value->AsIntConstant()->IsOne()) {
+    } else if (true_value->AsIntConstant()->IsFalse() && false_value->AsIntConstant()->IsTrue()) {
       // Replace (cond ? false : true) with (!cond).
       replace_with = GetGraph()->InsertOppositeCondition(condition, select);
     }
@@ -904,7 +904,7 @@
 void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {
   HConstant* input_cst = instruction->GetConstantRight();
   HInstruction* input_other = instruction->GetLeastConstantLeft();
-  if ((input_cst != nullptr) && input_cst->IsZero()) {
+  if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) {
     // Replace code looking like
     //    ADD dst, src, 0
     // with
@@ -1335,7 +1335,7 @@
   HConstant* input_cst = instruction->GetConstantRight();
   HInstruction* input_other = instruction->GetLeastConstantLeft();
 
-  if ((input_cst != nullptr) && input_cst->IsZero()) {
+  if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
     // Replace code looking like
     //    OR dst, src, 0
     // with
@@ -1380,7 +1380,7 @@
     return;
   }
 
-  if ((input_cst != nullptr) && input_cst->IsZero()) {
+  if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) {
     // Replace code looking like
     //    SUB dst, src, 0
     // with
@@ -1461,7 +1461,7 @@
   HConstant* input_cst = instruction->GetConstantRight();
   HInstruction* input_other = instruction->GetLeastConstantLeft();
 
-  if ((input_cst != nullptr) && input_cst->IsZero()) {
+  if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
     // Replace code looking like
     //    XOR dst, src, 0
     // with
@@ -1731,7 +1731,7 @@
 void InstructionSimplifierVisitor::VisitDeoptimize(HDeoptimize* deoptimize) {
   HInstruction* cond = deoptimize->InputAt(0);
   if (cond->IsConstant()) {
-    if (cond->AsIntConstant()->IsZero()) {
+    if (cond->AsIntConstant()->IsFalse()) {
       // Never deopt: instruction can be removed.
       deoptimize->GetBlock()->RemoveInstruction(deoptimize);
     } else {
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 98766a3..6a8c813 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2402,10 +2402,10 @@
     return replacement;
   } else if (cond->IsIntConstant()) {
     HIntConstant* int_const = cond->AsIntConstant();
-    if (int_const->IsZero()) {
+    if (int_const->IsFalse()) {
       return GetIntConstant(1);
     } else {
-      DCHECK(int_const->IsOne());
+      DCHECK(int_const->IsTrue()) << int_const->GetValue();
       return GetIntConstant(0);
     }
   } else {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 3733850..88d39d1 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2427,8 +2427,13 @@
 
   bool CanBeMoved() const OVERRIDE { return true; }
 
+  // Is this constant -1 in the arithmetic sense?
   virtual bool IsMinusOne() const { return false; }
-  virtual bool IsZero() const { return false; }
+  // Is this constant 0 in the arithmetic sense?
+  virtual bool IsArithmeticZero() const { return false; }
+  // Is this constant a 0-bit pattern?
+  virtual bool IsZeroBitPattern() const { return false; }
+  // Is this constant 1 in the arithmetic sense?
   virtual bool IsOne() const { return false; }
 
   virtual uint64_t GetValueAsUint64() const = 0;
@@ -2449,6 +2454,9 @@
 
   size_t ComputeHashCode() const OVERRIDE { return 0; }
 
+  // The null constant representation is a 0-bit pattern.
+  virtual bool IsZeroBitPattern() const { return true; }
+
   DECLARE_INSTRUCTION(NullConstant);
 
  private:
@@ -2476,9 +2484,15 @@
   size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
 
   bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
-  bool IsZero() const OVERRIDE { return GetValue() == 0; }
+  bool IsArithmeticZero() const OVERRIDE { return GetValue() == 0; }
+  bool IsZeroBitPattern() const OVERRIDE { return GetValue() == 0; }
   bool IsOne() const OVERRIDE { return GetValue() == 1; }
 
+  // Integer constants are used to encode Boolean values as well,
+  // where 1 means true and 0 means false.
+  bool IsTrue() const { return GetValue() == 1; }
+  bool IsFalse() const { return GetValue() == 0; }
+
   DECLARE_INSTRUCTION(IntConstant);
 
  private:
@@ -2509,7 +2523,8 @@
   size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
 
   bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
-  bool IsZero() const OVERRIDE { return GetValue() == 0; }
+  bool IsArithmeticZero() const OVERRIDE { return GetValue() == 0; }
+  bool IsZeroBitPattern() const OVERRIDE { return GetValue() == 0; }
   bool IsOne() const OVERRIDE { return GetValue() == 1; }
 
   DECLARE_INSTRUCTION(LongConstant);
@@ -2542,7 +2557,16 @@
   bool IsMinusOne() const OVERRIDE {
     return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
   }
-  bool IsZero() const OVERRIDE {
+  bool IsArithmeticZero() const OVERRIDE {
+    return std::fpclassify(value_) == FP_ZERO;
+  }
+  bool IsArithmeticPositiveZero() const {
+    return IsArithmeticZero() && !std::signbit(value_);
+  }
+  bool IsArithmeticNegativeZero() const {
+    return IsArithmeticZero() && std::signbit(value_);
+  }
+  bool IsZeroBitPattern() const OVERRIDE {
     return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(0.0f);
   }
   bool IsOne() const OVERRIDE {
@@ -2584,7 +2608,16 @@
   bool IsMinusOne() const OVERRIDE {
     return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
   }
-  bool IsZero() const OVERRIDE {
+  bool IsArithmeticZero() const OVERRIDE {
+    return std::fpclassify(value_) == FP_ZERO;
+  }
+  bool IsArithmeticPositiveZero() const {
+    return IsArithmeticZero() && !std::signbit(value_);
+  }
+  bool IsArithmeticNegativeZero() const {
+    return IsArithmeticZero() && std::signbit(value_);
+  }
+  bool IsZeroBitPattern() const OVERRIDE {
     return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((0.0));
   }
   bool IsOne() const OVERRIDE {
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 75356c8..95f10e0 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -291,12 +291,12 @@
     if (rhs != nullptr) {
       HInstruction* lhs = input->AsEqual()->GetLeastConstantLeft();
       if (lhs->IsInstanceOf() && rhs->IsIntConstant()) {
-        if (rhs->AsIntConstant()->IsOne()) {
+        if (rhs->AsIntConstant()->IsTrue()) {
           // Case (1a)
           *trueBranch = ifInstruction->IfTrueSuccessor();
         } else {
           // Case (2a)
-          DCHECK(rhs->AsIntConstant()->IsZero());
+          DCHECK(rhs->AsIntConstant()->IsFalse()) << rhs->AsIntConstant()->GetValue();
           *trueBranch = ifInstruction->IfFalseSuccessor();
         }
         *instanceOf = lhs->AsInstanceOf();
@@ -308,12 +308,12 @@
     if (rhs != nullptr) {
       HInstruction* lhs = input->AsNotEqual()->GetLeastConstantLeft();
       if (lhs->IsInstanceOf() && rhs->IsIntConstant()) {
-        if (rhs->AsIntConstant()->IsZero()) {
+        if (rhs->AsIntConstant()->IsFalse()) {
           // Case (1b)
           *trueBranch = ifInstruction->IfTrueSuccessor();
         } else {
           // Case (2b)
-          DCHECK(rhs->AsIntConstant()->IsOne());
+          DCHECK(rhs->AsIntConstant()->IsTrue()) << rhs->AsIntConstant()->GetValue();
           *trueBranch = ifInstruction->IfFalseSuccessor();
         }
         *instanceOf = lhs->AsInstanceOf();