Skip to content

Commit e209178

Browse files
[SimplifyIndVar] LCSSA form is destroyed by simplifyLoopIVs, preserve it (llvm#78696)
In LoopUnroll, peelLoop is called on the loop. After the loop is peeled it calls simplifyLoopAfterUnroll on the loop. This call to simplifyLoopAfterUnroll doesn't preserve the LCSSA form of the parent loop and thus during the next call to peelLoop the LCSSA form is already broken. LoopPeel util takes in the PreserveLCSSA argument and it passes on the same argument to simplifyLoop which checks if the loop is in a valid LCSSA form, when (PreserveLCSSA = true). This causes an assert in simplifyLoop when (PreserveLCSSA = true), as during the last call LCSSA for the loop wasn't preserved, and thus crashes at the following assert. assert(L->isRecursivelyLCSSAForm(*DT, *LI) && "Requested to preserve LCSSA, but it's already broken."); Upon debugging, it is evident that simplifyLoopIVs call inside simplifyLoopAfterUnroll breaks the LCSSA form. This patch fixes llvm#77118, it checks if the replacement of IV Users with Loop Invariant preserves the LCSSA form. If it does not, it emits the required LCSSA Phi instructions.
1 parent 40fae67 commit e209178

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

llvm/lib/Transforms/Utils/SimplifyIndVar.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/Support/Debug.h"
2626
#include "llvm/Support/raw_ostream.h"
2727
#include "llvm/Transforms/Utils/Local.h"
28+
#include "llvm/Transforms/Utils/LoopUtils.h"
2829
#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
2930

3031
using namespace llvm;
@@ -643,10 +644,21 @@ bool SimplifyIndvar::replaceIVUserWithLoopInvariant(Instruction *I) {
643644
}
644645

645646
auto *Invariant = Rewriter.expandCodeFor(S, I->getType(), IP);
647+
bool NeedToEmitLCSSAPhis = false;
648+
if (!LI->replacementPreservesLCSSAForm(I, Invariant))
649+
NeedToEmitLCSSAPhis = true;
646650

647651
I->replaceAllUsesWith(Invariant);
648652
LLVM_DEBUG(dbgs() << "INDVARS: Replace IV user: " << *I
649653
<< " with loop invariant: " << *S << '\n');
654+
655+
if (NeedToEmitLCSSAPhis) {
656+
SmallVector<Instruction *, 1> NeedsLCSSAPhis;
657+
NeedsLCSSAPhis.push_back(cast<Instruction>(Invariant));
658+
formLCSSAForInstructions(NeedsLCSSAPhis, *DT, *LI, SE);
659+
LLVM_DEBUG(dbgs() << " INDVARS: Replacement breaks LCSSA form"
660+
<< " inserting LCSSA Phis" << '\n');
661+
}
650662
++NumFoldedUser;
651663
Changed = true;
652664
DeadInsts.emplace_back(I);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; RUN: opt -passes=loop-unroll -unroll-peel-count=2 -S -disable-output -debug-only=loop-unroll < %s 2>&1 | FileCheck %s
2+
; REQUIRES: asserts
3+
4+
define void @test() {
5+
; CHECK-LABEL: Loop Unroll: F[test] Loop %loop3
6+
; CHECK-NEXT: Loop Size = 7
7+
; CHECK-NEXT: PEELING loop %loop3 with iteration count 2!
8+
; CHECK-NEXT: Loop Unroll: F[test] Loop %loop2
9+
; CHECK-NEXT: Loop Size = 28
10+
; CHECK-NEXT: PEELING loop %loop2 with iteration count 2!
11+
; CHECK-NEXT: Loop Unroll: F[test] Loop %loop4
12+
; CHECK-NEXT: Loop Size = 3
13+
; CHECK-NEXT: PEELING loop %loop4 with iteration count 2!
14+
; CHECK-NEXT: Loop Unroll: F[test] Loop %loop1
15+
; CHECK-NEXT: Loop Size = 95
16+
; CHECK-NEXT: PEELING loop %loop1 with iteration count 2!
17+
entry:
18+
br label %loop1
19+
20+
loop1:
21+
%phi = phi i32 [ 1, %entry ], [ 0, %loop1.latch ]
22+
br label %loop2
23+
24+
loop2:
25+
%phi3 = phi i64 [ 0, %loop1 ], [ %sext, %loop2.latch ]
26+
br label %loop3
27+
28+
loop3:
29+
%phi5 = phi i64 [ %phi3, %loop2 ], [ %sext, %loop3.latch ]
30+
%phi6 = phi i32 [ 1, %loop2 ], [ %add10, %loop3.latch ]
31+
%trunc = trunc i64 %phi5 to i32
32+
br i1 true, label %loop3.latch, label %exit
33+
34+
loop3.latch:
35+
%add = add i32 1, %phi
36+
%sext = sext i32 %add to i64
37+
%add10 = add i32 %phi6, 1
38+
%icmp = icmp ugt i32 %add10, 2
39+
br i1 %icmp, label %loop2.latch, label %loop3
40+
41+
loop2.latch:
42+
br i1 false, label %loop4.preheader, label %loop2
43+
44+
loop4.preheader:
45+
br label %loop4
46+
47+
loop4:
48+
br i1 false, label %loop1.latch, label %loop4
49+
50+
loop1.latch:
51+
br label %loop1
52+
53+
exit:
54+
%phi8 = phi i32 [ %trunc, %loop3 ]
55+
ret void
56+
}

0 commit comments

Comments
 (0)