Skip to content

Commit e79ca75

Browse files
committed
[MemCpyOpt] Fix MemorySSA preservation
moveUp() moves instructions, so we should move the corresponding memory accesses as well. We should also move the store instruction itself: Even though we'll end up removing it later, this gives us a correct MemoryDef to replace. The implementation is somewhat more complicated than it should be, because we also handle the case where P does not have a memory access due to a degnerate AA pipeline. Hopefully, the need for this will go away in the future, when the rest of the pass is based on MSSA. Differential Revision: https://reviews.llvm.org/D88778
1 parent 0ec1cf1 commit e79ca75

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

Diff for: llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

+33-4
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ bool MemCpyOptPass::moveUp(StoreInst *SI, Instruction *P, const LoadInst *LI) {
478478
Args.insert(Ptr);
479479

480480
// Instruction to lift before P.
481-
SmallVector<Instruction*, 8> ToLift;
481+
SmallVector<Instruction *, 8> ToLift{SI};
482482

483483
// Memory locations of lifted instructions.
484484
SmallVector<MemoryLocation, 8> MemLocs{StoreLoc};
@@ -549,10 +549,40 @@ bool MemCpyOptPass::moveUp(StoreInst *SI, Instruction *P, const LoadInst *LI) {
549549
}
550550
}
551551

552-
// We made it, we need to lift
552+
// Find MSSA insertion point. Normally P will always have a corresponding
553+
// memory access before which we can insert. However, with non-standard AA
554+
// pipelines, there may be a mismatch between AA and MSSA, in which case we
555+
// will scan for a memory access before P. In either case, we know for sure
556+
// that at least the load will have a memory access.
557+
// TODO: Simplify this once P will be determined by MSSA, in which case the
558+
// discrepancy can no longer occur.
559+
MemoryUseOrDef *MemInsertPoint = nullptr;
560+
if (MSSAU) {
561+
if (MemoryUseOrDef *MA = MSSAU->getMemorySSA()->getMemoryAccess(P)) {
562+
MemInsertPoint = cast<MemoryUseOrDef>(--MA->getIterator());
563+
} else {
564+
const Instruction *ConstP = P;
565+
for (const Instruction &I : make_range(++ConstP->getReverseIterator(),
566+
++LI->getReverseIterator())) {
567+
if (MemoryUseOrDef *MA = MSSAU->getMemorySSA()->getMemoryAccess(&I)) {
568+
MemInsertPoint = MA;
569+
break;
570+
}
571+
}
572+
}
573+
}
574+
575+
// We made it, we need to lift.
553576
for (auto *I : llvm::reverse(ToLift)) {
554577
LLVM_DEBUG(dbgs() << "Lifting " << *I << " before " << *P << "\n");
555578
I->moveBefore(P);
579+
if (MSSAU) {
580+
assert(MemInsertPoint && "Must have found insert point");
581+
if (MemoryUseOrDef *MA = MSSAU->getMemorySSA()->getMemoryAccess(I)) {
582+
MSSAU->moveAfter(MA, MemInsertPoint);
583+
MemInsertPoint = MA;
584+
}
585+
}
556586
}
557587

558588
return true;
@@ -636,9 +666,8 @@ bool MemCpyOptPass::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
636666
<< *M << "\n");
637667

638668
if (MSSAU) {
639-
assert(isa<MemoryDef>(MSSAU->getMemorySSA()->getMemoryAccess(P)));
640669
auto *LastDef =
641-
cast<MemoryDef>(MSSAU->getMemorySSA()->getMemoryAccess(P));
670+
cast<MemoryDef>(MSSAU->getMemorySSA()->getMemoryAccess(SI));
642671
auto *NewAccess =
643672
MSSAU->createMemoryAccessAfter(M, LastDef, LastDef);
644673
MSSAU->insertDef(cast<MemoryDef>(NewAccess), /*RenameUses=*/true);

Diff for: llvm/test/Transforms/MemCpyOpt/preserve-memssa.ll

+15
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,21 @@ entry:
148148
ret void
149149
}
150150

151+
define void @test8(%t* noalias %src, %t* %dst) {
152+
; CHECK-LABEL: @test8(
153+
; CHECK-NEXT: [[TMP1:%.*]] = bitcast %t* [[SRC:%.*]] to i8*
154+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast %t* [[DST:%.*]] to i8*
155+
; CHECK-NEXT: [[TMP3:%.*]] = bitcast %t* [[SRC]] to i8*
156+
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 [[TMP2]], i8* align 1 [[TMP3]], i64 8224, i1 false)
157+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[TMP1]], i8 0, i64 8224, i1 false)
158+
; CHECK-NEXT: ret void
159+
;
160+
%1 = load %t, %t* %src
161+
store %t zeroinitializer, %t* %src
162+
store %t %1, %t* %dst
163+
ret void
164+
}
165+
151166
declare void @clobber()
152167

153168
; Function Attrs: argmemonly nounwind willreturn

0 commit comments

Comments
 (0)