Skip to content

Commit 025e431

Browse files
authored
[LoopFusion] Forget loop and block dispositions after latch merge (#166233)
Merging the latches of loops may affect the dispositions, so they should be forgotten after the merge. This patch fixed the crash in loop fusion [#164082](#164082).
1 parent 8cd2244 commit 025e431

File tree

2 files changed

+75
-6
lines changed

2 files changed

+75
-6
lines changed

llvm/lib/Transforms/Scalar/LoopFuse.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,14 +1796,16 @@ struct LoopFuser {
17961796
// mergeLatch may remove the only block in FC1.
17971797
SE.forgetLoop(FC1.L);
17981798
SE.forgetLoop(FC0.L);
1799-
// Forget block dispositions as well, so that there are no dangling
1800-
// pointers to erased/free'ed blocks.
1801-
SE.forgetBlockAndLoopDispositions();
18021799

18031800
// Move instructions from FC0.Latch to FC1.Latch.
18041801
// Note: mergeLatch requires an updated DT.
18051802
mergeLatch(FC0, FC1);
18061803

1804+
// Forget block dispositions as well, so that there are no dangling
1805+
// pointers to erased/free'ed blocks. It should be done after mergeLatch()
1806+
// since merging the latches may affect the dispositions.
1807+
SE.forgetBlockAndLoopDispositions();
1808+
18071809
// Merge the loops.
18081810
SmallVector<BasicBlock *, 8> Blocks(FC1.L->blocks());
18091811
for (BasicBlock *BB : Blocks) {
@@ -2092,14 +2094,16 @@ struct LoopFuser {
20922094
// mergeLatch may remove the only block in FC1.
20932095
SE.forgetLoop(FC1.L);
20942096
SE.forgetLoop(FC0.L);
2095-
// Forget block dispositions as well, so that there are no dangling
2096-
// pointers to erased/free'ed blocks.
2097-
SE.forgetBlockAndLoopDispositions();
20982097

20992098
// Move instructions from FC0.Latch to FC1.Latch.
21002099
// Note: mergeLatch requires an updated DT.
21012100
mergeLatch(FC0, FC1);
21022101

2102+
// Forget block dispositions as well, so that there are no dangling
2103+
// pointers to erased/free'ed blocks. It should be done after mergeLatch()
2104+
// since merging the latches may affect the dispositions.
2105+
SE.forgetBlockAndLoopDispositions();
2106+
21032107
// Merge the loops.
21042108
SmallVector<BasicBlock *, 8> Blocks(FC1.L->blocks());
21052109
for (BasicBlock *BB : Blocks) {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
; REQUIRES: asserts
2+
; RUN: opt -passes=loop-fusion -disable-output -stats < %s 2>&1 | FileCheck -check-prefix=STAT %s
3+
; STAT: 1 loop-fusion - Loops fused
4+
5+
; C Code
6+
;
7+
;; for (int i = 0; i < 100; ++i)
8+
;; Array[i][i] = -i;
9+
;; for (int row = 0; row < 100; ++row)
10+
;; for (int col = 0; col < 100; ++col)
11+
;; if (col != row)
12+
;; Array[row][col] = row + col;
13+
;
14+
; Loop fusion should not crash anymore as now forgetBlockAndLoopDispositions()
15+
; is trigerred after mergeLatch() during the fusion.
16+
17+
define i32 @forget_dispositions() nounwind {
18+
entry:
19+
%Array = alloca [100 x [100 x i32]], align 4
20+
br label %for.body
21+
22+
for.body: ; preds = %for.body, %entry
23+
%indvars.iv33 = phi i64 [ 0, %entry ], [ %indvars.iv.next34, %for.body ]
24+
%0 = trunc i64 %indvars.iv33 to i32
25+
%sub = sub i32 0, %0
26+
%arrayidx2 = getelementptr inbounds [100 x [100 x i32]], ptr %Array, i64 0, i64 %indvars.iv33, i64 %indvars.iv33
27+
store i32 %sub, ptr %arrayidx2, align 4
28+
%indvars.iv.next34 = add i64 %indvars.iv33, 1
29+
%lftr.wideiv35 = trunc i64 %indvars.iv.next34 to i32
30+
%exitcond36 = icmp eq i32 %lftr.wideiv35, 100
31+
br i1 %exitcond36, label %for.cond6.preheader, label %for.body
32+
33+
for.cond6.preheader: ; preds = %for.body, %for.inc17
34+
%indvars.iv29 = phi i64 [ %indvars.iv.next30, %for.inc17 ], [ 0, %for.body ]
35+
br label %for.body8
36+
37+
for.body8: ; preds = %for.inc14, %for.cond6.preheader
38+
%indvars.iv = phi i64 [ 0, %for.cond6.preheader ], [ %indvars.iv.next, %for.inc14 ]
39+
%1 = trunc i64 %indvars.iv to i32
40+
%2 = trunc i64 %indvars.iv29 to i32
41+
%cmp9 = icmp eq i32 %1, %2
42+
br i1 %cmp9, label %for.inc14, label %if.then
43+
44+
if.then: ; preds = %for.body8
45+
%3 = add i64 %indvars.iv, %indvars.iv29
46+
%arrayidx13 = getelementptr inbounds [100 x [100 x i32]], ptr %Array, i64 0, i64 %indvars.iv29, i64 %indvars.iv
47+
%4 = trunc i64 %3 to i32
48+
store i32 %4, ptr %arrayidx13, align 4
49+
br label %for.inc14
50+
51+
for.inc14: ; preds = %for.body8, %if.then
52+
%indvars.iv.next = add i64 %indvars.iv, 1
53+
%lftr.wideiv27 = trunc i64 %indvars.iv.next to i32
54+
%exitcond28 = icmp eq i32 %lftr.wideiv27, 100
55+
br i1 %exitcond28, label %for.inc17, label %for.body8
56+
57+
for.inc17: ; preds = %for.inc14
58+
%indvars.iv.next30 = add i64 %indvars.iv29, 1
59+
%lftr.wideiv31 = trunc i64 %indvars.iv.next30 to i32
60+
%exitcond32 = icmp eq i32 %lftr.wideiv31, 100
61+
br i1 %exitcond32, label %for.exit, label %for.cond6.preheader
62+
63+
for.exit: ; preds = %for.inc17
64+
ret i32 0
65+
}

0 commit comments

Comments
 (0)