Merge "Fix bug not accounting for type in induction comparison. Extended unit tests."
diff --git a/compiler/optimizing/induction_var_analysis.cc b/compiler/optimizing/induction_var_analysis.cc
index 266cb10..c06d19d 100644
--- a/compiler/optimizing/induction_var_analysis.cc
+++ b/compiler/optimizing/induction_var_analysis.cc
@@ -141,7 +141,7 @@
   DCHECK(stack_.empty());
   map_.clear();
 
-  // Determine the loop's trip count.
+  // Determine the loop's trip-count.
   VisitControl(loop);
 }
 
@@ -917,6 +917,7 @@
         info1->induction_class == info2->induction_class &&
         info1->operation       == info2->operation       &&
         info1->fetch           == info2->fetch           &&
+        info1->type            == info2->type            &&
         InductionEqual(info1->op_a, info2->op_a)         &&
         InductionEqual(info1->op_b, info2->op_b);
   }
diff --git a/compiler/optimizing/induction_var_analysis_test.cc b/compiler/optimizing/induction_var_analysis_test.cc
index 0fbb67d..580d24b 100644
--- a/compiler/optimizing/induction_var_analysis_test.cc
+++ b/compiler/optimizing/induction_var_analysis_test.cc
@@ -157,6 +157,13 @@
         iva_->LookupInfo(loop_body_[d]->GetLoopInformation(), instruction));
   }
 
+  // Returns true if instructions have identical induction.
+  bool HaveSameInduction(HInstruction* instruction1, HInstruction* instruction2) {
+    return HInductionVarAnalysis::InductionEqual(
+      iva_->LookupInfo(loop_body_[0]->GetLoopInformation(), instruction1),
+      iva_->LookupInfo(loop_body_[0]->GetLoopInformation(), instruction2));
+  }
+
   // Performs InductionVarAnalysis (after proper set up).
   void PerformInductionVarAnalysis() {
     graph_->BuildDominatorTree();
@@ -228,6 +235,9 @@
   EXPECT_STREQ("((1) * i + (0)):PrimInt", GetInductionInfo(store->InputAt(1), 0).c_str());
   EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(increment_[0], 0).c_str());
 
+  // Offset matters!
+  EXPECT_FALSE(HaveSameInduction(store->InputAt(1), increment_[0]));
+
   // Trip-count.
   EXPECT_STREQ("((100) (TC-loop) ((0) < (100)))",
                GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
@@ -320,6 +330,10 @@
   PerformInductionVarAnalysis();
 
   EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(store->InputAt(1), 0).c_str());
+
+  // Both increments get same induction.
+  EXPECT_TRUE(HaveSameInduction(store->InputAt(1), inc1));
+  EXPECT_TRUE(HaveSameInduction(store->InputAt(1), inc2));
 }
 
 TEST_F(InductionVarAnalysisTest, FindTwoWayDerivedInduction) {
@@ -570,6 +584,33 @@
   }
 }
 
+TEST_F(InductionVarAnalysisTest, ByteInductionIntLoopControl) {
+  // Setup:
+  // for (int i = 0; i < 100; i++) {
+  //   k = (byte) i;
+  //   a[k] = 0;
+  //   a[i] = 0;
+  // }
+  BuildLoopNest(1);
+  HInstruction *conv = InsertInstruction(
+      new (&allocator_) HTypeConversion(Primitive::kPrimByte, basic_[0], -1), 0);
+  HInstruction* store1 = InsertArrayStore(conv, 0);
+  HInstruction* store2 = InsertArrayStore(basic_[0], 0);
+  PerformInductionVarAnalysis();
+
+  // Regular int induction (i) is "transferred" over conversion into byte induction (k).
+  EXPECT_STREQ("((1) * i + (0)):PrimByte", GetInductionInfo(store1->InputAt(1), 0).c_str());
+  EXPECT_STREQ("((1) * i + (0)):PrimInt",  GetInductionInfo(store2->InputAt(1), 0).c_str());
+  EXPECT_STREQ("((1) * i + (1)):PrimInt",  GetInductionInfo(increment_[0], 0).c_str());
+
+  // Type matters!
+  EXPECT_FALSE(HaveSameInduction(store1->InputAt(1), store2->InputAt(1)));
+
+  // Trip-count.
+  EXPECT_STREQ("((100) (TC-loop) ((0) < (100)))",
+               GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
+}
+
 TEST_F(InductionVarAnalysisTest, ByteLoopControl1) {
   // Setup:
   // for (byte i = -128; i < 127; i++) {  // just fits!