Skip to content

Commit e399dd6

Browse files
committed
[SimpleLoopUnswitch] Clear block and loop dispos after destroying loop.
SimpleLoopUnswitch may remove loops. Clear block and loop dispositions, to clean up invalid entries in the cache. Fixes #58136.
1 parent 635f93d commit e399dd6

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,7 +1820,8 @@ static SmallPtrSet<const BasicBlock *, 16> recomputeLoopBlockSet(Loop &L,
18201820
/// referenced).
18211821
static bool rebuildLoopAfterUnswitch(Loop &L, ArrayRef<BasicBlock *> ExitBlocks,
18221822
LoopInfo &LI,
1823-
SmallVectorImpl<Loop *> &HoistedLoops) {
1823+
SmallVectorImpl<Loop *> &HoistedLoops,
1824+
ScalarEvolution *SE) {
18241825
auto *PH = L.getLoopPreheader();
18251826

18261827
// Compute the actual parent loop from the exit blocks. Because we may have
@@ -2013,6 +2014,8 @@ static bool rebuildLoopAfterUnswitch(Loop &L, ArrayRef<BasicBlock *> ExitBlocks,
20132014
LI.removeLoop(llvm::find(LI, &L));
20142015
// markLoopAsDeleted for L should be triggered by the caller (it is typically
20152016
// done by using the UnswitchCB callback).
2017+
if (SE)
2018+
SE->forgetBlockAndLoopDispositions();
20162019
LI.destroy(&L);
20172020
return false;
20182021
}
@@ -2380,7 +2383,8 @@ static void unswitchNontrivialInvariants(
23802383
MSSAU->getMemorySSA()->verifyMemorySSA();
23812384

23822385
SmallVector<Loop *, 4> HoistedLoops;
2383-
bool IsStillLoop = rebuildLoopAfterUnswitch(L, ExitBlocks, LI, HoistedLoops);
2386+
bool IsStillLoop =
2387+
rebuildLoopAfterUnswitch(L, ExitBlocks, LI, HoistedLoops, SE);
23842388

23852389
if (MSSAU && VerifyMemorySSA)
23862390
MSSAU->getMemorySSA()->verifyMemorySSA();
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -passes="loop-mssa(loop-simplifycfg,require<iv-users>,licm,simple-loop-unswitch<nontrivial>)" -verify-scev -S %s | FileCheck %s
3+
target datalayout = "n16:32"
4+
5+
@glob = external global i16, align 1
6+
7+
; Test case for PR58136.
8+
define void @test() {
9+
; CHECK-LABEL: @test(
10+
; CHECK-NEXT: entry:
11+
; CHECK-NEXT: [[SRC:%.*]] = alloca i16, align 1
12+
; CHECK-NEXT: [[DST:%.*]] = alloca float, align 1
13+
; CHECK-NEXT: [[CALL:%.*]] = call i16 @foo()
14+
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i16 8509, [[CALL]]
15+
; CHECK-NEXT: [[L_1:%.*]] = load i16, ptr [[SRC]], align 1
16+
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i16 [[L_1]], 10
17+
; CHECK-NEXT: [[L_3:%.*]] = load i16, ptr [[SRC]], align 1
18+
; CHECK-NEXT: [[GLOB_PROMOTED:%.*]] = load i16, ptr @glob, align 1
19+
; CHECK-NEXT: [[DST_PROMOTED:%.*]] = load float, ptr [[DST]], align 1
20+
; CHECK-NEXT: br i1 [[C_1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
21+
; CHECK: entry.split.us:
22+
; CHECK-NEXT: br i1 [[C_2]], label [[ENTRY_SPLIT_US_SPLIT_US:%.*]], label [[ENTRY_SPLIT_US_SPLIT:%.*]]
23+
; CHECK: entry.split.us.split.us:
24+
; CHECK-NEXT: br label [[LOOP_HEADER_US_US:%.*]]
25+
; CHECK: loop.header.us.us:
26+
; CHECK-NEXT: [[MUL1_US_US:%.*]] = phi i16 [ [[MUL_US_US:%.*]], [[LOOP_HEADER_US_US]] ], [ [[GLOB_PROMOTED]], [[ENTRY_SPLIT_US_SPLIT_US]] ]
27+
; CHECK-NEXT: [[MUL_US_US]] = mul nsw i16 [[MUL1_US_US]], [[L_3]]
28+
; CHECK-NEXT: br label [[LOOP_HEADER_US_US]]
29+
; CHECK: entry.split.us.split:
30+
; CHECK-NEXT: br label [[LOOP_HEADER_US:%.*]]
31+
; CHECK: loop.header.us:
32+
; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]]
33+
; CHECK: exit.split.us:
34+
; CHECK-NEXT: [[DOTLCSSA_US:%.*]] = phi float [ [[DST_PROMOTED]], [[LOOP_HEADER_US]] ]
35+
; CHECK-NEXT: br label [[EXIT:%.*]]
36+
; CHECK: entry.split:
37+
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
38+
; CHECK: loop.header:
39+
; CHECK-NEXT: [[TMP0:%.*]] = phi float [ 1.000000e+01, [[LOOP_LATCH:%.*]] ], [ [[DST_PROMOTED]], [[ENTRY_SPLIT]] ]
40+
; CHECK-NEXT: [[MUL1:%.*]] = phi i16 [ [[MUL:%.*]], [[LOOP_LATCH]] ], [ [[GLOB_PROMOTED]], [[ENTRY_SPLIT]] ]
41+
; CHECK-NEXT: br i1 false, label [[LOOP_LATCH]], label [[EXIT_SPLIT:%.*]]
42+
; CHECK: loop.latch:
43+
; CHECK-NEXT: [[MUL]] = mul nsw i16 [[MUL1]], [[L_3]]
44+
; CHECK-NEXT: store i16 [[MUL]], ptr @glob, align 1
45+
; CHECK-NEXT: br label [[LOOP_HEADER]]
46+
; CHECK: exit.split:
47+
; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi float [ [[TMP0]], [[LOOP_HEADER]] ]
48+
; CHECK-NEXT: br label [[EXIT]]
49+
; CHECK: exit:
50+
; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi float [ [[DOTLCSSA]], [[EXIT_SPLIT]] ], [ [[DOTLCSSA_US]], [[EXIT_SPLIT_US]] ]
51+
; CHECK-NEXT: store float [[DOTUS_PHI]], ptr [[DST]], align 1
52+
; CHECK-NEXT: ret void
53+
;
54+
entry:
55+
%src = alloca i16, align 1
56+
%dst = alloca float, align 1
57+
br label %loop.header
58+
59+
loop.header:
60+
%call = call i16 @foo()
61+
%c.1 = icmp ugt i16 8509, %call
62+
br i1 %c.1, label %then.bb, label %merge.bb
63+
64+
then.bb:
65+
%l.1 = load i16, ptr %src, align 1
66+
%c.2 = icmp slt i16 %l.1, 10
67+
br label %merge.bb
68+
69+
merge.bb:
70+
%p = phi i1 [ false, %loop.header ], [ %c.2, %then.bb ]
71+
br i1 %p, label %loop.latch, label %exit
72+
73+
loop.latch:
74+
%l.2 = load i16, ptr @glob, align 1
75+
%l.3 = load i16, ptr %src, align 1
76+
%mul = mul nsw i16 %l.2, %l.3
77+
store i16 %mul, ptr @glob, align 1
78+
store float 10.0, ptr %dst, align 1
79+
br label %loop.header
80+
81+
exit:
82+
ret void
83+
}
84+
85+
declare i16 @foo() nounwind readnone

0 commit comments

Comments
 (0)