Skip to content

Commit 05f1e31

Browse files
authored
[MemorySSAUpdater] Fix iterator invalidation bug in applyInsertUpdates (#139370)
This patch defers resetting optimized accesses until all uses are replaced, to avoid invalidating the iterator. Closes #139103. Closes #139289. Closes #139308.
1 parent 77d1db6 commit 05f1e31

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

llvm/lib/Analysis/MemorySSAUpdater.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,9 @@ void MemorySSAUpdater::applyInsertUpdates(ArrayRef<CFGUpdate> Updates,
11191119
if (auto DefsList = MSSA->getWritableBlockDefs(BlockWithDefsToReplace)) {
11201120
for (auto &DefToReplaceUses : *DefsList) {
11211121
BasicBlock *DominatingBlock = DefToReplaceUses.getBlock();
1122+
// We defer resetting optimized accesses until all uses are replaced, to
1123+
// avoid invalidating the iterator.
1124+
SmallVector<MemoryUseOrDef *, 4> ResetOptimized;
11221125
for (Use &U : llvm::make_early_inc_range(DefToReplaceUses.uses())) {
11231126
MemoryAccess *Usr = cast<MemoryAccess>(U.getUser());
11241127
if (MemoryPhi *UsrPhi = dyn_cast<MemoryPhi>(Usr)) {
@@ -1135,10 +1138,13 @@ void MemorySSAUpdater::applyInsertUpdates(ArrayRef<CFGUpdate> Updates,
11351138
assert(IDom && "Block must have a valid IDom.");
11361139
U.set(GetLastDef(IDom->getBlock()));
11371140
}
1138-
cast<MemoryUseOrDef>(Usr)->resetOptimized();
1141+
ResetOptimized.push_back(cast<MemoryUseOrDef>(Usr));
11391142
}
11401143
}
11411144
}
1145+
1146+
for (auto *Usr : ResetOptimized)
1147+
Usr->resetOptimized();
11421148
}
11431149
}
11441150
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
; RUN: opt -disable-output -passes="loop-mssa(licm,loop-rotate,licm,simple-loop-unswitch<nontrivial>),print<memoryssa>" -verify-memoryssa < %s 2>&1 | FileCheck %s
2+
3+
; Make sure that we update MSSA correctly in this case.
4+
5+
; CHECK-LABEL: MemorySSA for function: test
6+
; CHECK: for.header2.preheader:
7+
; CHECK-NEXT: 11 = MemoryPhi({entry.split,liveOnEntry},{for.header,9})
8+
; CHECK: for.body.us:
9+
; CHECK-NEXT: 7 = MemoryPhi({for.header2.preheader.split.us,11},{for.header2.us,9})
10+
; CHECK-NEXT: 8 = MemoryDef(7)->7
11+
; CHECK-NEXT: store i32 0, ptr %p, align 4
12+
; CHECK-NEXT: 9 = MemoryDef(8)->8
13+
; CHECK-NEXT: store i8 0, ptr %p, align 1
14+
15+
define void @test(ptr %p, i1 %cond) {
16+
entry:
17+
br label %for.header
18+
19+
for.header:
20+
br i1 false, label %exit.loopexit1, label %for.header2.preheader
21+
22+
for.header2.preheader:
23+
br label %for.body
24+
25+
for.header2:
26+
br i1 false, label %for.latch, label %for.body
27+
28+
for.body:
29+
store i32 0, ptr %p, align 4
30+
store i8 0, ptr %p, align 1
31+
br i1 %cond, label %for.header2, label %exit.loopexit
32+
33+
for.latch:
34+
br i1 false, label %for.inc, label %exit.loopexit1
35+
36+
for.inc:
37+
br label %for.header
38+
39+
exit.loopexit:
40+
br label %exit
41+
42+
exit.loopexit1:
43+
br label %exit
44+
45+
exit:
46+
ret void
47+
}

0 commit comments

Comments
 (0)