[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.
This commit is contained in:
Nikita Popov 2024-01-24 10:15:42 +01:00 committed by GitHub
parent 33ecef9812
commit a7a1b8b17e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 107 additions and 19 deletions

View File

@ -692,25 +692,9 @@ void MemorySSAUpdater::updateForClonedLoop(const LoopBlocksRPO &LoopBlocks,
continue;
// Determine incoming value and add it as incoming from IncBB.
if (MemoryUseOrDef *IncMUD = dyn_cast<MemoryUseOrDef>(IncomingAccess)) {
if (!MSSA->isLiveOnEntryDef(IncMUD)) {
Instruction *IncI = IncMUD->getMemoryInst();
assert(IncI && "Found MemoryUseOrDef with no Instruction.");
if (Instruction *NewIncI =
cast_or_null<Instruction>(VMap.lookup(IncI))) {
IncMUD = MSSA->getMemoryAccess(NewIncI);
assert(IncMUD &&
"MemoryUseOrDef cannot be null, all preds processed.");
}
}
NewPhi->addIncoming(IncMUD, IncBB);
} else {
MemoryPhi *IncPhi = cast<MemoryPhi>(IncomingAccess);
if (MemoryAccess *NewDefPhi = MPhiMap.lookup(IncPhi))
NewPhi->addIncoming(NewDefPhi, IncBB);
else
NewPhi->addIncoming(IncPhi, IncBB);
}
NewPhi->addIncoming(
getNewDefiningAccessForClone(IncomingAccess, VMap, MPhiMap, MSSA),
IncBB);
}
if (auto *SingleAccess = onlySingleValue(NewPhi)) {
MPhiMap[Phi] = SingleAccess;

View File

@ -115,3 +115,107 @@ split:
exit:
ret void
}
; Variants of the above test with swapped branch destinations.
define void @test1_swapped(i1 %c) {
; CHECK-LABEL: define void @test1_swapped(
; CHECK-SAME: i1 [[C:%.*]]) {
; CHECK-NEXT: start:
; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]
; CHECK-NEXT: br i1 [[C_FR]], label [[START_SPLIT_US:%.*]], label [[START_SPLIT:%.*]]
; CHECK: start.split.us:
; CHECK-NEXT: br label [[LOOP_US:%.*]]
; CHECK: loop.us:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[LOOP_US]]
; CHECK: start.split:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
start:
br label %loop
loop:
%fn = load ptr, ptr @vtable, align 8
call void %fn()
br i1 %c, label %loop, label %exit
exit:
ret void
}
define void @test2_swapped(i1 %c, ptr %p) {
; CHECK-LABEL: define void @test2_swapped(
; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]
; CHECK-NEXT: br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]
; CHECK: .split.us:
; CHECK-NEXT: br label [[LOOP_US:%.*]]
; CHECK: loop.us:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @bar()
; CHECK-NEXT: br label [[LOOP_US]]
; CHECK: .split:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @bar()
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
br label %loop
loop:
%fn = load ptr, ptr @vtable, align 8
call void %fn()
call void @bar()
br i1 %c, label %loop, label %exit
exit:
ret void
}
define void @test3_swapped(i1 %c, ptr %p) {
; CHECK-LABEL: define void @test3_swapped(
; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]
; CHECK-NEXT: br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]
; CHECK: .split.us:
; CHECK-NEXT: br label [[LOOP_US:%.*]]
; CHECK: loop.us:
; CHECK-NEXT: br label [[SPLIT_US:%.*]]
; CHECK: split.us:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @bar()
; CHECK-NEXT: br label [[LOOP_US]]
; CHECK: .split:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br label [[SPLIT:%.*]]
; CHECK: split:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @bar()
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
br label %loop
loop:
%fn = load ptr, ptr @vtable, align 8
br label %split
split:
call void %fn()
call void @bar()
br i1 %c, label %loop, label %exit
exit:
ret void
}