Fix performance regression.
Rationale:
One "improvement" overlooked in the previous CL hoists
a try-test out of the optimization to make sure we don't
change HIR when not needed. However, the try-test may
affect the outcome of the test, so that was bad, bad!
Bug: 64091002
Test: test-art-host
Change-Id: Icf5f73e7cbeb209ee5fa5f6c1bef64fe127bb2fd
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 4143462..027ba77 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -490,13 +490,18 @@
for (HInstructionIterator it(header->GetPhis()); !it.Done(); it.Advance()) {
HPhi* phi = it.Current()->AsPhi();
if (TrySetPhiInduction(phi, /*restrict_uses*/ true) &&
- CanRemoveCycle() &&
TryAssignLastValue(node->loop_info, phi, preheader, /*collect_loop_uses*/ false)) {
- simplified_ = true;
- for (HInstruction* i : *iset_) {
- RemoveFromCycle(i);
+ // Note that it's ok to have replaced uses after the loop with the last value, without
+ // being able to remove the cycle. Environment uses (which are the reason we may not be
+ // able to remove the cycle) within the loop will still hold the right value. We must
+ // have tried first, however, to replace outside uses.
+ if (CanRemoveCycle()) {
+ simplified_ = true;
+ for (HInstruction* i : *iset_) {
+ RemoveFromCycle(i);
+ }
+ DCHECK(CheckInductionSetFullyRemoved(iset_));
}
- DCHECK(CheckInductionSetFullyRemoved(iset_));
}
}
}
diff --git a/test/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java
index fc7bcb2..0e85612 100644
--- a/test/623-checker-loop-regressions/src/Main.java
+++ b/test/623-checker-loop-regressions/src/Main.java
@@ -441,6 +441,29 @@
}
}
+ /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none
+ /// CHECK-DAG: Phi loop:<<Loop1>> outer_loop:none
+ /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:none
+ //
+ /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+ //
+ /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (after)
+ /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none
+ /// CHECK-NOT: Phi
+ static int feedsIntoDeopt(int[] a) {
+ // Reduction should be removed.
+ int r = 0;
+ for (int i = 0; i < 100; i++) {
+ r += 10;
+ }
+ // Even though uses feed into deopts of BCE.
+ for (int i = 1; i < 100; i++) {
+ a[i] = a[i - 1];
+ }
+ return r;
+ }
+
public static void main(String[] args) {
expectEquals(10, earlyExitFirst(-1));
for (int i = 0; i <= 10; i++) {
@@ -556,6 +579,13 @@
inductionMax(yy);
+ int[] f = new int[100];
+ f[0] = 11;
+ expectEquals(1000, feedsIntoDeopt(f));
+ for (int i = 0; i < 100; i++) {
+ expectEquals(11, f[i]);
+ }
+
System.out.println("passed");
}