Minor induction variable analysis changes.
Rationale:
Few extra comments, added replacement of loop control functionality.
All in preparation of bigger loop optimizations CL.
Change-Id: Ie2243c3c8b57b2901654b05fb200e9d80a0cb641
Test: test-art
diff --git a/compiler/optimizing/induction_var_analysis.cc b/compiler/optimizing/induction_var_analysis.cc
index 129c2a9..c501ccf 100644
--- a/compiler/optimizing/induction_var_analysis.cc
+++ b/compiler/optimizing/induction_var_analysis.cc
@@ -714,10 +714,12 @@
case kCondGE: op = kGE; break;
default: LOG(FATAL) << "CONDITION UNREACHABLE";
}
+ // Associate trip count with control instruction, rather than the condition (even
+ // though it's its use) since former provides a convenient use-free placeholder.
+ HInstruction* control = loop->GetHeader()->GetLastInstruction();
InductionInfo* taken_test = CreateInvariantOp(op, lower_expr, upper_expr);
- AssignInfo(loop,
- loop->GetHeader()->GetLastInstruction(),
- CreateTripCount(tcKind, trip_count, taken_test, type));
+ DCHECK(control->IsIf());
+ AssignInfo(loop, control, CreateTripCount(tcKind, trip_count, taken_test, type));
}
bool HInductionVarAnalysis::IsTaken(InductionInfo* lower_expr,
diff --git a/compiler/optimizing/induction_var_analysis_test.cc b/compiler/optimizing/induction_var_analysis_test.cc
index 580d24b..292bc4e 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 induction information of the trip-count of loop at depth d.
+ std::string GetTripCount(int d) {
+ HInstruction* control = loop_header_[d]->GetLastInstruction();
+ DCHECK(control->IsIf());
+ return GetInductionInfo(control, d);
+ }
+
// Returns true if instructions have identical induction.
bool HaveSameInduction(HInstruction* instruction1, HInstruction* instruction2) {
return HInductionVarAnalysis::InductionEqual(
@@ -239,8 +246,7 @@
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());
+ EXPECT_STREQ("((100) (TC-loop) ((0) < (100)))", GetTripCount(0).c_str());
}
TEST_F(InductionVarAnalysisTest, FindDerivedInduction) {
@@ -579,8 +585,7 @@
}
EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(increment_[d], d).c_str());
// Trip-count.
- EXPECT_STREQ("((100) (TC-loop) ((0) < (100)))",
- GetInductionInfo(loop_header_[d]->GetLastInstruction(), d).c_str());
+ EXPECT_STREQ("((100) (TC-loop) ((0) < (100)))", GetTripCount(d).c_str());
}
}
@@ -607,8 +612,7 @@
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());
+ EXPECT_STREQ("((100) (TC-loop) ((0) < (100)))", GetTripCount(0).c_str());
}
TEST_F(InductionVarAnalysisTest, ByteLoopControl1) {
@@ -626,8 +630,7 @@
EXPECT_STREQ("((1) * i + ((-128) + (1))):PrimByte", GetInductionInfo(increment_[0], 0).c_str());
// Trip-count.
- EXPECT_STREQ("(((127) - (-128)) (TC-loop) ((-128) < (127)))",
- GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
+ EXPECT_STREQ("(((127) - (-128)) (TC-loop) ((-128) < (127)))", GetTripCount(0).c_str());
}
TEST_F(InductionVarAnalysisTest, ByteLoopControl2) {
@@ -645,7 +648,7 @@
EXPECT_STREQ("((1) * i + ((-128) + (1))):PrimByte", GetInductionInfo(increment_[0], 0).c_str());
// Trip-count undefined.
- EXPECT_STREQ("", GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
+ EXPECT_STREQ("", GetTripCount(0).c_str());
}
TEST_F(InductionVarAnalysisTest, ShortLoopControl1) {
@@ -664,8 +667,7 @@
EXPECT_STREQ("((1) * i + ((-32768) + (1))):PrimShort",
GetInductionInfo(increment_[0], 0).c_str());
// Trip-count.
- EXPECT_STREQ("(((32767) - (-32768)) (TC-loop) ((-32768) < (32767)))",
- GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
+ EXPECT_STREQ("(((32767) - (-32768)) (TC-loop) ((-32768) < (32767)))", GetTripCount(0).c_str());
}
TEST_F(InductionVarAnalysisTest, ShortLoopControl2) {
@@ -684,7 +686,7 @@
EXPECT_STREQ("((1) * i + ((-32768) + (1))):PrimShort",
GetInductionInfo(increment_[0], 0).c_str());
// Trip-count undefined.
- EXPECT_STREQ("", GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
+ EXPECT_STREQ("", GetTripCount(0).c_str());
}
TEST_F(InductionVarAnalysisTest, CharLoopControl1) {
@@ -701,8 +703,7 @@
EXPECT_STREQ("((1) * i + (1)):PrimChar", GetInductionInfo(increment_[0], 0).c_str());
// Trip-count.
- EXPECT_STREQ("((65535) (TC-loop) ((0) < (65535)))",
- GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
+ EXPECT_STREQ("((65535) (TC-loop) ((0) < (65535)))", GetTripCount(0).c_str());
}
TEST_F(InductionVarAnalysisTest, CharLoopControl2) {
@@ -719,7 +720,7 @@
EXPECT_STREQ("((1) * i + (1)):PrimChar", GetInductionInfo(increment_[0], 0).c_str());
// Trip-count undefined.
- EXPECT_STREQ("", GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
+ EXPECT_STREQ("", GetTripCount(0).c_str());
}
} // namespace art
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc
index 18e6f5c..cd8b7c7 100644
--- a/compiler/optimizing/induction_var_range.cc
+++ b/compiler/optimizing/induction_var_range.cc
@@ -106,6 +106,12 @@
return instruction;
}
+/** Helper method to obtain loop's control instruction. */
+static HInstruction* GetLoopControl(HLoopInformation* loop) {
+ DCHECK(loop != nullptr);
+ return loop->GetHeader()->GetLastInstruction();
+}
+
//
// Public class methods.
//
@@ -179,7 +185,7 @@
/*out*/HInstruction** lower,
/*out*/HInstruction** upper) {
bool is_last_value = false;
- int64_t s = 0;
+ int64_t stride_value = 0;
bool b1, b2; // unused
if (!GenerateCode(context,
instruction,
@@ -189,7 +195,7 @@
lower,
upper,
nullptr,
- &s,
+ &stride_value,
&b1,
&b2)) {
LOG(FATAL) << "Failed precondition: CanGenerateRange()";
@@ -232,7 +238,9 @@
nullptr,
nullptr,
nullptr, // nothing generated yet
- &stride_value, &needs_finite_test, &needs_taken_test)
+ &stride_value,
+ &needs_finite_test,
+ &needs_taken_test)
&& !needs_finite_test && !needs_taken_test;
}
@@ -265,7 +273,10 @@
for (HLoopInformation* lp = instruction->GetBlock()->GetLoopInformation(); // closest enveloping loop
lp != nullptr;
lp = lp->GetPreHeader()->GetLoopInformation()) {
+ // Update instruction's information.
ReplaceInduction(induction_analysis_->LookupInfo(lp, instruction), fetch, replacement);
+ // Update loop's trip-count information.
+ ReplaceInduction(induction_analysis_->LookupInfo(lp, GetLoopControl(lp)), fetch, replacement);
}
}
@@ -308,13 +319,13 @@
/*out*/ HLoopInformation** loop,
/*out*/ HInductionVarAnalysis::InductionInfo** info,
/*out*/ HInductionVarAnalysis::InductionInfo** trip) const {
- HLoopInformation* l = context->GetBlock()->GetLoopInformation(); // closest enveloping loop
- if (l != nullptr) {
- HInductionVarAnalysis::InductionInfo* i = induction_analysis_->LookupInfo(l, instruction);
+ HLoopInformation* lp = context->GetBlock()->GetLoopInformation(); // closest enveloping loop
+ if (lp != nullptr) {
+ HInductionVarAnalysis::InductionInfo* i = induction_analysis_->LookupInfo(lp, instruction);
if (i != nullptr) {
- *loop = l;
+ *loop = lp;
*info = i;
- *trip = induction_analysis_->LookupInfo(l, l->GetHeader()->GetLastInstruction());
+ *trip = induction_analysis_->LookupInfo(lp, GetLoopControl(lp));
return true;
}
}
@@ -878,7 +889,8 @@
} else if (stride_value == -1) {
oper = new (graph->GetArena()) HSub(type, opb, opa);
} else {
- HInstruction* mul = new (graph->GetArena()) HMul(type, graph->GetIntConstant(stride_value), opa);
+ HInstruction* mul = new (graph->GetArena()) HMul(
+ type, graph->GetIntConstant(stride_value), opa);
oper = new (graph->GetArena()) HAdd(type, Insert(block, mul), opb);
}
*result = Insert(block, oper);