Merge "Fixed missing context while detecting unit strides."
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc
index d6513c8..1c8674d 100644
--- a/compiler/optimizing/induction_var_range.cc
+++ b/compiler/optimizing/induction_var_range.cc
@@ -383,12 +383,13 @@
return false;
}
-bool InductionVarRange::IsUnitStride(HInstruction* instruction,
+bool InductionVarRange::IsUnitStride(HInstruction* context,
+ HInstruction* instruction,
/*out*/ HInstruction** offset) const {
HLoopInformation* loop = nullptr;
HInductionVarAnalysis::InductionInfo* info = nullptr;
HInductionVarAnalysis::InductionInfo* trip = nullptr;
- if (HasInductionInfo(instruction, instruction, &loop, &info, &trip)) {
+ if (HasInductionInfo(context, instruction, &loop, &info, &trip)) {
if (info->induction_class == HInductionVarAnalysis::kLinear &&
info->op_b->operation == HInductionVarAnalysis::kFetch &&
!HInductionVarAnalysis::IsNarrowingLinear(info)) {
diff --git a/compiler/optimizing/induction_var_range.h b/compiler/optimizing/induction_var_range.h
index 0858d73..a8ee829 100644
--- a/compiler/optimizing/induction_var_range.h
+++ b/compiler/optimizing/induction_var_range.h
@@ -156,10 +156,14 @@
bool IsFinite(HLoopInformation* loop, /*out*/ int64_t* tc) const;
/**
- * Checks if instruction is a unit stride induction inside the closest enveloping loop.
- * Returns invariant offset on success.
+ * Checks if the given instruction is a unit stride induction inside the closest enveloping
+ * loop of the context that is defined by the first parameter (e.g. pass an array reference
+ * as context and the index as instruction to make sure the stride is tested against the
+ * loop that envelops the reference the closest). Returns invariant offset on success.
*/
- bool IsUnitStride(HInstruction* instruction, /*out*/ HInstruction** offset) const;
+ bool IsUnitStride(HInstruction* context,
+ HInstruction* instruction,
+ /*out*/ HInstruction** offset) const;
/**
* Generates the trip count expression for the given loop. Code is generated in given block
diff --git a/compiler/optimizing/induction_var_range_test.cc b/compiler/optimizing/induction_var_range_test.cc
index fcdf8eb..d01d314 100644
--- a/compiler/optimizing/induction_var_range_test.cc
+++ b/compiler/optimizing/induction_var_range_test.cc
@@ -770,7 +770,7 @@
EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
EXPECT_EQ(1000, tc);
HInstruction* offset = nullptr;
- EXPECT_TRUE(range_.IsUnitStride(phi, &offset));
+ EXPECT_TRUE(range_.IsUnitStride(phi, phi, &offset));
EXPECT_TRUE(offset == nullptr);
HInstruction* tce = range_.GenerateTripCount(
loop_header_->GetLoopInformation(), graph_, loop_preheader_);
@@ -826,7 +826,7 @@
EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
EXPECT_EQ(1000, tc);
HInstruction* offset = nullptr;
- EXPECT_FALSE(range_.IsUnitStride(phi, &offset));
+ EXPECT_FALSE(range_.IsUnitStride(phi, phi, &offset));
HInstruction* tce = range_.GenerateTripCount(
loop_header_->GetLoopInformation(), graph_, loop_preheader_);
ASSERT_TRUE(tce != nullptr);
@@ -908,7 +908,7 @@
EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
EXPECT_EQ(0, tc); // unknown
HInstruction* offset = nullptr;
- EXPECT_TRUE(range_.IsUnitStride(phi, &offset));
+ EXPECT_TRUE(range_.IsUnitStride(phi, phi, &offset));
EXPECT_TRUE(offset == nullptr);
HInstruction* tce = range_.GenerateTripCount(
loop_header_->GetLoopInformation(), graph_, loop_preheader_);
@@ -994,7 +994,7 @@
EXPECT_TRUE(range_.IsFinite(loop_header_->GetLoopInformation(), &tc));
EXPECT_EQ(0, tc); // unknown
HInstruction* offset = nullptr;
- EXPECT_FALSE(range_.IsUnitStride(phi, &offset));
+ EXPECT_FALSE(range_.IsUnitStride(phi, phi, &offset));
HInstruction* tce = range_.GenerateTripCount(
loop_header_->GetLoopInformation(), graph_, loop_preheader_);
ASSERT_TRUE(tce != nullptr);
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 1a79601..bf18cc9 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -580,7 +580,7 @@
HInstruction* offset = nullptr;
if (TrySetVectorType(type, &restrictions) &&
node->loop_info->IsDefinedOutOfTheLoop(base) &&
- induction_range_.IsUnitStride(index, &offset) &&
+ induction_range_.IsUnitStride(instruction, index, &offset) &&
VectorizeUse(node, value, generate_code, type, restrictions)) {
if (generate_code) {
GenerateVecSub(index, offset);
@@ -633,7 +633,7 @@
HInstruction* offset = nullptr;
if (type == instruction->GetType() &&
node->loop_info->IsDefinedOutOfTheLoop(base) &&
- induction_range_.IsUnitStride(index, &offset)) {
+ induction_range_.IsUnitStride(instruction, index, &offset)) {
if (generate_code) {
GenerateVecSub(index, offset);
GenerateVecMem(instruction, vector_map_->Get(index), nullptr, type);
diff --git a/test/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java
index eee90ab..182c07d 100644
--- a/test/623-checker-loop-regressions/src/Main.java
+++ b/test/623-checker-loop-regressions/src/Main.java
@@ -270,6 +270,16 @@
}
}
+ // If vectorized, invariant stride should be recognized
+ // as a reduction, not a unit stride in outer loop.
+ static void reduc(int[] xx, int[] yy) {
+ for (int i0 = 0; i0 < 2; i0++) {
+ for (int i1 = 0; i1 < 469; i1++) {
+ xx[i0] -= (++yy[i1]);
+ }
+ }
+ }
+
public static void main(String[] args) {
expectEquals(10, earlyExitFirst(-1));
for (int i = 0; i <= 10; i++) {
@@ -335,6 +345,15 @@
expectEquals(2.0f, a[i]);
}
+ int[] xx = new int[2];
+ int[] yy = new int[469];
+ reduc(xx, yy);
+ expectEquals(-469, xx[0]);
+ expectEquals(-938, xx[1]);
+ for (int i = 0; i < 469; i++) {
+ expectEquals(2, yy[i]);
+ }
+
System.out.println("passed");
}