[LoopRotate] Fix incorrect SCEV invalidation in loop rotation

LoopRotate only invalidates innermost loops while the changes that it makes may
also affert any of this parents. With patch rL329047, SCEV becomes much smarter
about calculation of exit counts for outer loops, so we cannot assume that they are
not affected.

Differential Revision: https://reviews.llvm.org/D45945

llvm-svn: 330582
This commit is contained in:
Max Kazantsev 2018-04-23 12:33:31 +00:00
parent 0a334a8668
commit 91f481665e
2 changed files with 125 additions and 2 deletions

View File

@ -259,9 +259,10 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
return false;
// Anything ScalarEvolution may know about this loop or the PHI nodes
// in its header will soon be invalidated.
// in its header will soon be invalidated, and it can also affect its parent
// loops as well.
if (SE)
SE->forgetLoop(L);
SE->forgetTopmostLoop(L);
DEBUG(dbgs() << "LoopRotation: rotating "; L->dump());
@ -476,6 +477,12 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
DEBUG(dbgs() << "LoopRotation: into "; L->dump());
#ifndef NDEBUG
// Make sure that after all our transforms SE is correct.
if (SE)
SE->verify();
#endif
++NumRotated;
return true;
}

View File

@ -0,0 +1,116 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -indvars -verify -loop-rotate -loop-idiom < %s | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
; Verify that we invalidate SCEV properly.
define void @test_01() {
; CHECK-LABEL: @test_01(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LBL1:%.*]]
; CHECK: lbl1:
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: br i1 false, label [[FOR_BODY3_LR_PH:%.*]], label [[FOR_COND_FOR_END5_CRIT_EDGE:%.*]]
; CHECK: for.body3.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY3:%.*]]
; CHECK: for.cond1:
; CHECK-NEXT: br i1 false, label [[FOR_BODY3]], label [[FOR_COND1_FOR_END5_CRIT_EDGE:%.*]]
; CHECK: for.body3:
; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[FOR_COND1:%.*]]
; CHECK: if.then:
; CHECK-NEXT: br label [[LBL1]]
; CHECK: for.cond.for.end5_crit_edge:
; CHECK-NEXT: br label [[FOR_END5:%.*]]
; CHECK: for.cond1.for.end5_crit_edge:
; CHECK-NEXT: br label [[FOR_END5]]
; CHECK: for.end5:
; CHECK-NEXT: ret void
;
entry:
br label %lbl1
lbl1: ; preds = %if.then, %entry
br label %for.cond
for.cond: ; preds = %lbl1
br label %for.cond1
for.cond1: ; preds = %if.end, %for.cond
br i1 false, label %for.body3, label %for.end5
for.body3: ; preds = %for.cond1
br i1 false, label %if.then, label %if.end
if.then: ; preds = %for.body3
br label %lbl1
if.end: ; preds = %for.body3
br label %for.cond1
for.end5: ; preds = %for.cond1
ret void
}
define void @test_02() {
; CHECK-LABEL: @test_02(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LBL1:%.*]]
; CHECK: lbl1:
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_END7:%.*]]
; CHECK: if.then:
; CHECK-NEXT: br i1 false, label [[FOR_BODY_LR_PH:%.*]], label [[IF_THEN_FOR_END6_CRIT_EDGE:%.*]]
; CHECK: for.body.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: br i1 false, label [[IF_THEN3:%.*]], label [[IF_END:%.*]]
; CHECK: if.then3:
; CHECK-NEXT: br label [[LBL1]]
; CHECK: if.end:
; CHECK-NEXT: br label [[FOR_COND4:%.*]]
; CHECK: for.cond4:
; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[FOR_COND1_FOR_END6_CRIT_EDGE:%.*]]
; CHECK: if.then.for.end6_crit_edge:
; CHECK-NEXT: br label [[FOR_END6:%.*]]
; CHECK: for.cond1.for.end6_crit_edge:
; CHECK-NEXT: br label [[FOR_END6]]
; CHECK: for.end6:
; CHECK-NEXT: ret void
; CHECK: if.end7:
; CHECK-NEXT: unreachable
;
entry:
br label %lbl1
lbl1: ; preds = %if.then3, %entry
br label %for.cond
for.cond: ; preds = %lbl1
br i1 false, label %if.then, label %if.end7
if.then: ; preds = %for.cond
br label %for.cond1
for.cond1: ; preds = %for.cond4, %if.then
br i1 undef, label %for.body, label %for.end6
for.body: ; preds = %for.cond1
br i1 false, label %if.then3, label %if.end
if.then3: ; preds = %for.body
br label %lbl1
if.end: ; preds = %for.body
br label %for.cond4
for.cond4: ; preds = %if.end
br label %for.cond1
for.end6: ; preds = %for.cond1
ret void
if.end7: ; preds = %for.cond
unreachable
}