Compensate in compiler for verifier shortcomings.

The verifier does not differentiate zero and null, so a move-object
of zero can be used as a non-object later on.

Change the compiler to ignore the object conversion when the input
is zero or a phi (which might just hold zeros). The type propagation
will then do proper inferencing of the types.

Also remove some stalled comments in ssa_builder.cc.

bug:31313170
test: dex2oat b31313170.apk
test: run-test 800
test: m test-art-host-run-test
Change-Id: I579d667415a7decf8ff2c2238dae4c13eec5d0e0
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 5a6a212..f7dc237 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1815,7 +1815,20 @@
     case Instruction::MOVE_OBJECT:
     case Instruction::MOVE_OBJECT_16:
     case Instruction::MOVE_OBJECT_FROM16: {
-      HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot);
+      // The verifier has no notion of a null type, so a move-object of constant 0
+      // will lead to the same constant 0 in the destination register. To mimic
+      // this behavior, we just pretend we haven't seen a type change (int to reference)
+      // for the 0 constant and phis. We rely on our type propagation to eventually get the
+      // types correct.
+      uint32_t reg_number = instruction.VRegB();
+      HInstruction* value = (*current_locals_)[reg_number];
+      if (value->IsIntConstant()) {
+        DCHECK_EQ(value->AsIntConstant()->GetValue(), 0);
+      } else if (value->IsPhi()) {
+        DCHECK(value->GetType() == Primitive::kPrimInt || value->GetType() == Primitive::kPrimNot);
+      } else {
+        value = LoadLocal(reg_number, Primitive::kPrimNot);
+      }
       UpdateLocal(instruction.VRegA(), value);
       break;
     }