ART: Resolve ambiguous ArraySets

Just like aget(-wide), the value operand of aput(-wide) bytecode
instructions can be both int/long and float/double. This patch builds
on the previous mechanism for resolving type of ArrayGets to type the
values of ArraySets based on the reference type of the array.

Bug: 22538329

Change-Id: Ic86abbb58de146692de04476b555010b6fcdd8b6
diff --git a/compiler/optimizing/licm_test.cc b/compiler/optimizing/licm_test.cc
index aa60fd6..2b63ec8 100644
--- a/compiler/optimizing/licm_test.cc
+++ b/compiler/optimizing/licm_test.cc
@@ -65,7 +65,8 @@
     // Provide boiler-plate instructions.
     parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimNot);
     entry_->AddInstruction(parameter_);
-    constant_ = graph_->GetIntConstant(42);
+    int_constant_ = graph_->GetIntConstant(42);
+    float_constant_ = graph_->GetFloatConstant(42.0f);
     loop_preheader_->AddInstruction(new (&allocator_) HGoto());
     loop_header_->AddInstruction(new (&allocator_) HIf(parameter_));
     loop_body_->AddInstruction(new (&allocator_) HGoto());
@@ -95,7 +96,8 @@
   HBasicBlock* exit_;
 
   HInstruction* parameter_;  // "this"
-  HInstruction* constant_;
+  HInstruction* int_constant_;
+  HInstruction* float_constant_;
 };
 
 //
@@ -118,7 +120,7 @@
                                                                 0);
   loop_body_->InsertInstructionBefore(get_field, loop_body_->GetLastInstruction());
   HInstruction* set_field = new (&allocator_) HInstanceFieldSet(
-      parameter_, constant_, Primitive::kPrimInt, MemberOffset(20),
+      parameter_, int_constant_, Primitive::kPrimInt, MemberOffset(20),
       false, kUnknownFieldIndex, kUnknownClassDefIndex, graph_->GetDexFile(), dex_cache, 0);
   loop_body_->InsertInstructionBefore(set_field, loop_body_->GetLastInstruction());
 
@@ -167,11 +169,13 @@
   BuildLoop();
 
   // Populate the loop with instructions: set/get array with different types.
+  // ArrayGet is typed as kPrimByte and ArraySet given a float value in order to
+  // avoid SsaBuilder's typing of ambiguous array operations from reference type info.
   HInstruction* get_array = new (&allocator_) HArrayGet(
-      parameter_, constant_, Primitive::kPrimByte, 0);
+      parameter_, int_constant_, Primitive::kPrimByte, 0);
   loop_body_->InsertInstructionBefore(get_array, loop_body_->GetLastInstruction());
   HInstruction* set_array = new (&allocator_) HArraySet(
-      parameter_, constant_, constant_, Primitive::kPrimShort, 0);
+      parameter_, int_constant_, float_constant_, Primitive::kPrimShort, 0);
   loop_body_->InsertInstructionBefore(set_array, loop_body_->GetLastInstruction());
 
   EXPECT_EQ(get_array->GetBlock(), loop_body_);
@@ -185,11 +189,13 @@
   BuildLoop();
 
   // Populate the loop with instructions: set/get array with same types.
+  // ArrayGet is typed as kPrimByte and ArraySet given a float value in order to
+  // avoid SsaBuilder's typing of ambiguous array operations from reference type info.
   HInstruction* get_array = new (&allocator_) HArrayGet(
-      parameter_, constant_, Primitive::kPrimByte, 0);
+      parameter_, int_constant_, Primitive::kPrimByte, 0);
   loop_body_->InsertInstructionBefore(get_array, loop_body_->GetLastInstruction());
   HInstruction* set_array = new (&allocator_) HArraySet(
-      parameter_, get_array, constant_, Primitive::kPrimByte, 0);
+      parameter_, get_array, float_constant_, Primitive::kPrimByte, 0);
   loop_body_->InsertInstructionBefore(set_array, loop_body_->GetLastInstruction());
 
   EXPECT_EQ(get_array->GetBlock(), loop_body_);