Improved subscript and data dependence analysis.

Rationale:
We missed vectorizing a simple stencil operation
due to inaccurate unit stride analysis and failure
to detect single runtime data dependence test.

Test: test-art-host, test-art-target
Change-Id: I07ba03455bfb1c0aff371c1244a1328f885d0916
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 32f4002..b61d7b8 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -620,12 +620,15 @@
           // Conservatively assume a potential loop-carried data dependence otherwise, avoided by
           // generating an explicit a != b disambiguation runtime test on the two references.
           if (x != y) {
-            // For now, we reject after one test to avoid excessive overhead.
-            if (vector_runtime_test_a_ != nullptr) {
-              return false;
+            // To avoid excessive overhead, we only accept one a != b test.
+            if (vector_runtime_test_a_ == nullptr) {
+              // First test found.
+              vector_runtime_test_a_ = a;
+              vector_runtime_test_b_ = b;
+            } else if ((vector_runtime_test_a_ != a || vector_runtime_test_b_ != b) &&
+                       (vector_runtime_test_a_ != b || vector_runtime_test_b_ != a)) {
+              return false;  // second test would be needed
             }
-            vector_runtime_test_a_ = a;
-            vector_runtime_test_b_ = b;
           }
         }
       }
@@ -842,7 +845,7 @@
     HInstruction* offset = nullptr;
     if (TrySetVectorType(type, &restrictions) &&
         node->loop_info->IsDefinedOutOfTheLoop(base) &&
-        induction_range_.IsUnitStride(instruction, index, &offset) &&
+        induction_range_.IsUnitStride(instruction, index, graph_, &offset) &&
         VectorizeUse(node, value, generate_code, type, restrictions)) {
       if (generate_code) {
         GenerateVecSub(index, offset);
@@ -900,7 +903,7 @@
     HInstruction* offset = nullptr;
     if (type == instruction->GetType() &&
         node->loop_info->IsDefinedOutOfTheLoop(base) &&
-        induction_range_.IsUnitStride(instruction, index, &offset)) {
+        induction_range_.IsUnitStride(instruction, index, graph_, &offset)) {
       if (generate_code) {
         GenerateVecSub(index, offset);
         GenerateVecMem(instruction, vector_map_->Get(index), nullptr, offset, type);
@@ -1216,7 +1219,8 @@
 void HLoopOptimization::GenerateVecSub(HInstruction* org, HInstruction* offset) {
   if (vector_map_->find(org) == vector_map_->end()) {
     HInstruction* subscript = vector_index_;
-    if (offset != nullptr) {
+    int64_t value = 0;
+    if (!IsInt64AndGet(offset, &value) || value != 0) {
       subscript = new (global_allocator_) HAdd(Primitive::kPrimInt, subscript, offset);
       if (org->IsPhi()) {
         Insert(vector_body_, subscript);  // lacks layout placeholder