Skip to content

Commit a7a1b8b

Browse files
authored
[MSSAUpdater] Handle simplified accesses when updating phis (#78272)
This is a followup to #76819. After those changes, we can still run into an assertion failure for a slight variation of the test case: When fixing up MemoryPhis, we map the incoming access to the access of the cloned instruction -- which may now no longer exist. Fix this by reusing the getNewDefiningAccessForClone() helper, which will look upwards for a new defining access in that case.
1 parent 33ecef9 commit a7a1b8b

File tree

2 files changed

+107
-19
lines changed

2 files changed

+107
-19
lines changed

llvm/lib/Analysis/MemorySSAUpdater.cpp

+3-19
Original file line numberDiff line numberDiff line change
@@ -692,25 +692,9 @@ void MemorySSAUpdater::updateForClonedLoop(const LoopBlocksRPO &LoopBlocks,
692692
continue;
693693

694694
// Determine incoming value and add it as incoming from IncBB.
695-
if (MemoryUseOrDef *IncMUD = dyn_cast<MemoryUseOrDef>(IncomingAccess)) {
696-
if (!MSSA->isLiveOnEntryDef(IncMUD)) {
697-
Instruction *IncI = IncMUD->getMemoryInst();
698-
assert(IncI && "Found MemoryUseOrDef with no Instruction.");
699-
if (Instruction *NewIncI =
700-
cast_or_null<Instruction>(VMap.lookup(IncI))) {
701-
IncMUD = MSSA->getMemoryAccess(NewIncI);
702-
assert(IncMUD &&
703-
"MemoryUseOrDef cannot be null, all preds processed.");
704-
}
705-
}
706-
NewPhi->addIncoming(IncMUD, IncBB);
707-
} else {
708-
MemoryPhi *IncPhi = cast<MemoryPhi>(IncomingAccess);
709-
if (MemoryAccess *NewDefPhi = MPhiMap.lookup(IncPhi))
710-
NewPhi->addIncoming(NewDefPhi, IncBB);
711-
else
712-
NewPhi->addIncoming(IncPhi, IncBB);
713-
}
695+
NewPhi->addIncoming(
696+
getNewDefiningAccessForClone(IncomingAccess, VMap, MPhiMap, MSSA),
697+
IncBB);
714698
}
715699
if (auto *SingleAccess = onlySingleValue(NewPhi)) {
716700
MPhiMap[Phi] = SingleAccess;

llvm/test/Transforms/SimpleLoopUnswitch/memssa-readnone-access.ll

+104
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,107 @@ split:
115115
exit:
116116
ret void
117117
}
118+
119+
; Variants of the above test with swapped branch destinations.
120+
121+
define void @test1_swapped(i1 %c) {
122+
; CHECK-LABEL: define void @test1_swapped(
123+
; CHECK-SAME: i1 [[C:%.*]]) {
124+
; CHECK-NEXT: start:
125+
; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]
126+
; CHECK-NEXT: br i1 [[C_FR]], label [[START_SPLIT_US:%.*]], label [[START_SPLIT:%.*]]
127+
; CHECK: start.split.us:
128+
; CHECK-NEXT: br label [[LOOP_US:%.*]]
129+
; CHECK: loop.us:
130+
; CHECK-NEXT: call void @foo()
131+
; CHECK-NEXT: br label [[LOOP_US]]
132+
; CHECK: start.split:
133+
; CHECK-NEXT: br label [[LOOP:%.*]]
134+
; CHECK: loop:
135+
; CHECK-NEXT: call void @foo()
136+
; CHECK-NEXT: br label [[EXIT:%.*]]
137+
; CHECK: exit:
138+
; CHECK-NEXT: ret void
139+
;
140+
start:
141+
br label %loop
142+
143+
loop:
144+
%fn = load ptr, ptr @vtable, align 8
145+
call void %fn()
146+
br i1 %c, label %loop, label %exit
147+
148+
exit:
149+
ret void
150+
}
151+
152+
define void @test2_swapped(i1 %c, ptr %p) {
153+
; CHECK-LABEL: define void @test2_swapped(
154+
; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
155+
; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]
156+
; CHECK-NEXT: br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]
157+
; CHECK: .split.us:
158+
; CHECK-NEXT: br label [[LOOP_US:%.*]]
159+
; CHECK: loop.us:
160+
; CHECK-NEXT: call void @foo()
161+
; CHECK-NEXT: call void @bar()
162+
; CHECK-NEXT: br label [[LOOP_US]]
163+
; CHECK: .split:
164+
; CHECK-NEXT: br label [[LOOP:%.*]]
165+
; CHECK: loop:
166+
; CHECK-NEXT: call void @foo()
167+
; CHECK-NEXT: call void @bar()
168+
; CHECK-NEXT: br label [[EXIT:%.*]]
169+
; CHECK: exit:
170+
; CHECK-NEXT: ret void
171+
;
172+
br label %loop
173+
174+
loop:
175+
%fn = load ptr, ptr @vtable, align 8
176+
call void %fn()
177+
call void @bar()
178+
br i1 %c, label %loop, label %exit
179+
180+
exit:
181+
ret void
182+
}
183+
184+
define void @test3_swapped(i1 %c, ptr %p) {
185+
; CHECK-LABEL: define void @test3_swapped(
186+
; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
187+
; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]
188+
; CHECK-NEXT: br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]
189+
; CHECK: .split.us:
190+
; CHECK-NEXT: br label [[LOOP_US:%.*]]
191+
; CHECK: loop.us:
192+
; CHECK-NEXT: br label [[SPLIT_US:%.*]]
193+
; CHECK: split.us:
194+
; CHECK-NEXT: call void @foo()
195+
; CHECK-NEXT: call void @bar()
196+
; CHECK-NEXT: br label [[LOOP_US]]
197+
; CHECK: .split:
198+
; CHECK-NEXT: br label [[LOOP:%.*]]
199+
; CHECK: loop:
200+
; CHECK-NEXT: br label [[SPLIT:%.*]]
201+
; CHECK: split:
202+
; CHECK-NEXT: call void @foo()
203+
; CHECK-NEXT: call void @bar()
204+
; CHECK-NEXT: br label [[EXIT:%.*]]
205+
; CHECK: exit:
206+
; CHECK-NEXT: ret void
207+
;
208+
br label %loop
209+
210+
loop:
211+
%fn = load ptr, ptr @vtable, align 8
212+
br label %split
213+
214+
split:
215+
call void %fn()
216+
call void @bar()
217+
br i1 %c, label %loop, label %exit
218+
219+
exit:
220+
ret void
221+
}

0 commit comments

Comments
 (0)