Skip to content

Commit 4d859db

Browse files
authored
[MemCpyOpt] fix incorrect handling of lifetime markers (#143782)
Having lifetime markers should only increase the information available to LLVM, but it would instead rely on the callback to entirely give up if it encountered a lifetime marker that wasn't full size, but sub-optimal lifetime markers are not supposed to be forbidding optimizations that would otherwise apply if they were either absent or optimal. This pass wasn't tracking GEP offsets either, so it wasn't quite correctly handled either, although earlier sub-optimal checks that this size is the same as the alloca test made this safe in the past, and unlikely to have encountered anything else in the past.
1 parent 492b521 commit 4d859db

File tree

2 files changed

+8
-19
lines changed

2 files changed

+8
-19
lines changed

llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,11 +1593,8 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
15931593
// since both llvm.lifetime.start and llvm.lifetime.end intrinsics
15941594
// practically fill all the bytes of the alloca with an undefined
15951595
// value, although conceptually marked as alive/dead.
1596-
int64_t Size = cast<ConstantInt>(UI->getOperand(0))->getSExtValue();
1597-
if (Size < 0 || Size == DestSize) {
1598-
LifetimeMarkers.push_back(UI);
1599-
continue;
1600-
}
1596+
LifetimeMarkers.push_back(UI);
1597+
continue;
16011598
}
16021599
AAMetadataInstrs.insert(UI);
16031600

@@ -1614,9 +1611,8 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
16141611
return true;
16151612
};
16161613

1617-
// Check that dest has no Mod/Ref, from the alloca to the Store, except full
1618-
// size lifetime intrinsics. And collect modref inst for the reachability
1619-
// check.
1614+
// Check that dest has no Mod/Ref, from the alloca to the Store. And collect
1615+
// modref inst for the reachability check.
16201616
ModRefInfo DestModRef = ModRefInfo::NoModRef;
16211617
MemoryLocation DestLoc(DestAlloca, LocationSize::precise(Size));
16221618
SmallVector<BasicBlock *, 8> ReachabilityWorklist;

llvm/test/Transforms/MemCpyOpt/stack-move.ll

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,20 +1649,13 @@ loop_exit:
16491649
ret void
16501650
}
16511651

1652-
; Tests that failure because partial-sized lifetimes are counted as mod.
1652+
; Tests that partial-sized lifetimes are not inhibiting the optimizer
16531653
define void @partial_lifetime() {
16541654
; CHECK-LABEL: define void @partial_lifetime() {
1655-
; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1656-
; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1657-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1658-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr captures(none) [[DEST]])
1659-
; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1660-
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1661-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1662-
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 3, ptr captures(none) [[SRC]])
1655+
; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1656+
; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[DEST]], align 4
1657+
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
16631658
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1664-
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1665-
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
16661659
; CHECK-NEXT: ret void
16671660
;
16681661
%src = alloca %struct.Foo, align 4

0 commit comments

Comments
 (0)