Skip to content

Commit 0a8ebdb

Browse files
committed
[MemCpyOpt] Remove handling for lifetime sizes
Split out from #150248: Since #150944 the size passed to lifetime.start/end is considered meaningless. The lifetime always applies to the whole alloca. Accordingly, remove checks of the lifetime size from MemCpyOpt.
1 parent c4f7d87 commit 0a8ebdb

File tree

4 files changed

+10
-122
lines changed

4 files changed

+10
-122
lines changed

llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,8 +1010,7 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,
10101010
// Lifetime of srcAlloca ends at lifetime.end.
10111011
if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
10121012
if (II->getIntrinsicID() == Intrinsic::lifetime_end &&
1013-
II->getArgOperand(1)->stripPointerCasts() == srcAlloca &&
1014-
cast<ConstantInt>(II->getArgOperand(0))->uge(srcSize))
1013+
II->getArgOperand(1) == srcAlloca)
10151014
break;
10161015
}
10171016

@@ -1384,39 +1383,17 @@ bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
13841383
return true;
13851384
}
13861385

1387-
/// Determine whether the pointer V had only undefined content (due to Def) up
1388-
/// to the given Size, either because it was freshly alloca'd or started its
1389-
/// lifetime.
1386+
/// Determine whether the pointer V had only undefined content (due to Def),
1387+
/// either because it was freshly alloca'd or started its lifetime.
13901388
static bool hasUndefContents(MemorySSA *MSSA, BatchAAResults &AA, Value *V,
1391-
MemoryDef *Def, Value *Size) {
1389+
MemoryDef *Def) {
13921390
if (MSSA->isLiveOnEntryDef(Def))
13931391
return isa<AllocaInst>(getUnderlyingObject(V));
13941392

1395-
if (auto *II = dyn_cast_or_null<IntrinsicInst>(Def->getMemoryInst())) {
1396-
if (II->getIntrinsicID() == Intrinsic::lifetime_start) {
1397-
auto *LTSize = cast<ConstantInt>(II->getArgOperand(0));
1398-
1399-
if (auto *CSize = dyn_cast<ConstantInt>(Size)) {
1400-
if (AA.isMustAlias(V, II->getArgOperand(1)) &&
1401-
LTSize->getZExtValue() >= CSize->getZExtValue())
1402-
return true;
1403-
}
1404-
1405-
// If the lifetime.start covers a whole alloca (as it almost always
1406-
// does) and we're querying a pointer based on that alloca, then we know
1407-
// the memory is definitely undef, regardless of how exactly we alias.
1408-
// The size also doesn't matter, as an out-of-bounds access would be UB.
1409-
if (auto *Alloca = dyn_cast<AllocaInst>(getUnderlyingObject(V))) {
1410-
if (getUnderlyingObject(II->getArgOperand(1)) == Alloca) {
1411-
const DataLayout &DL = Alloca->getDataLayout();
1412-
if (std::optional<TypeSize> AllocaSize =
1413-
Alloca->getAllocationSize(DL))
1414-
if (*AllocaSize == LTSize->getValue())
1415-
return true;
1416-
}
1417-
}
1418-
}
1419-
}
1393+
if (auto *II = dyn_cast_or_null<IntrinsicInst>(Def->getMemoryInst()))
1394+
if (II->getIntrinsicID() == Intrinsic::lifetime_start)
1395+
if (auto *Alloca = dyn_cast<AllocaInst>(getUnderlyingObject(V)))
1396+
return II->getArgOperand(1) == Alloca;
14201397

14211398
return false;
14221399
}
@@ -1428,13 +1405,12 @@ static bool hasUndefContents(MemorySSA *MSSA, BatchAAResults &AA, Value *V,
14281405
// which cannot deal with offsets), we use the full 0..CopySize range.
14291406
static bool overreadUndefContents(MemorySSA *MSSA, MemCpyInst *MemCpy,
14301407
MemIntrinsic *MemSrc, BatchAAResults &BAA) {
1431-
Value *CopySize = MemCpy->getLength();
14321408
MemoryLocation MemCpyLoc = MemoryLocation::getForSource(MemCpy);
14331409
MemoryUseOrDef *MemSrcAccess = MSSA->getMemoryAccess(MemSrc);
14341410
MemoryAccess *Clobber = MSSA->getWalker()->getClobberingMemoryAccess(
14351411
MemSrcAccess->getDefiningAccess(), MemCpyLoc, BAA);
14361412
if (auto *MD = dyn_cast<MemoryDef>(Clobber))
1437-
if (hasUndefContents(MSSA, BAA, MemCpy->getSource(), MD, CopySize))
1413+
if (hasUndefContents(MSSA, BAA, MemCpy->getSource(), MD))
14381414
return true;
14391415
return false;
14401416
}
@@ -1836,7 +1812,7 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
18361812
}
18371813
}
18381814

1839-
if (hasUndefContents(MSSA, BAA, M->getSource(), MD, M->getLength())) {
1815+
if (hasUndefContents(MSSA, BAA, M->getSource(), MD)) {
18401816
LLVM_DEBUG(dbgs() << "Removed memcpy from undef\n");
18411817
eraseInstruction(M);
18421818
++NumMemCpyInstr;

llvm/test/Transforms/MemCpyOpt/capturing-func.ll

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,28 +67,6 @@ define void @test_lifetime_end() {
6767
ret void
6868
}
6969

70-
; Lifetime of %ptr2 does not end, because of size mismatch.
71-
define void @test_lifetime_not_end() {
72-
; CHECK-LABEL: define {{[^@]+}}@test_lifetime_not_end() {
73-
; CHECK-NEXT: [[PTR1:%.*]] = alloca i8, align 1
74-
; CHECK-NEXT: [[PTR2:%.*]] = alloca i8, align 1
75-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 1, ptr [[PTR2]])
76-
; CHECK-NEXT: call void @foo(ptr [[PTR2]])
77-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[PTR1]], ptr [[PTR2]], i32 1, i1 false)
78-
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 0, ptr [[PTR2]])
79-
; CHECK-NEXT: call void @foo(ptr [[PTR1]])
80-
; CHECK-NEXT: ret void
81-
;
82-
%ptr1 = alloca i8
83-
%ptr2 = alloca i8
84-
call void @llvm.lifetime.start.p0(i64 1, ptr %ptr2)
85-
call void @foo(ptr %ptr2)
86-
call void @llvm.memcpy.p0.p0.i32(ptr %ptr1, ptr %ptr2, i32 1, i1 false)
87-
call void @llvm.lifetime.end.p0(i64 0, ptr %ptr2)
88-
call void @foo(ptr %ptr1)
89-
ret void
90-
}
91-
9270
; Lifetime of %ptr2 ends before any potential use of the capture because we
9371
; return from the function.
9472
define void @test_function_end() {

llvm/test/Transforms/MemCpyOpt/memcpy-undef.ll

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,6 @@ define void @test2(ptr sret(i8) noalias nocapture %out) nounwind noinline ssp uw
3838
ret void
3939
}
4040

41-
; Check that the memcpy is not removed.
42-
define void @test3(ptr sret(i8) noalias nocapture %out) nounwind noinline ssp uwtable {
43-
; CHECK-LABEL: @test3(
44-
; CHECK-NEXT: [[IN:%.*]] = alloca i64, align 8
45-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[IN]])
46-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[OUT:%.*]], ptr [[IN]], i64 8, i1 false)
47-
; CHECK-NEXT: ret void
48-
;
49-
%in = alloca i64
50-
call void @llvm.lifetime.start.p0(i64 4, ptr %in)
51-
call void @llvm.memcpy.p0.p0.i64(ptr %out, ptr %in, i64 8, i1 false)
52-
ret void
53-
}
54-
5541
; Check that the memcpy is not removed.
5642
define void @test_lifetime_may_alias(ptr %src, ptr %dst) {
5743
; CHECK-LABEL: @test_lifetime_may_alias(
@@ -96,38 +82,6 @@ define void @test_lifetime_partial_alias_2(ptr noalias %dst) {
9682
ret void
9783
}
9884

99-
; lifetime.start on part of alloca, copy in range.
100-
define void @test_lifetime_partial_alias_3(ptr noalias %dst) {
101-
; CHECK-LABEL: @test_lifetime_partial_alias_3(
102-
; CHECK-NEXT: [[A:%.*]] = alloca [16 x i8], align 1
103-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr [[A]])
104-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 8
105-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST:%.*]], ptr [[GEP]], i64 4, i1 false)
106-
; CHECK-NEXT: ret void
107-
;
108-
%a = alloca [16 x i8]
109-
call void @llvm.lifetime.start.p0(i64 12, ptr %a)
110-
%gep = getelementptr i8, ptr %a, i64 8
111-
call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %gep, i64 4, i1 false)
112-
ret void
113-
}
114-
115-
; lifetime.start on part of alloca, copy out of range.
116-
define void @test_lifetime_partial_alias_4(ptr noalias %dst) {
117-
; CHECK-LABEL: @test_lifetime_partial_alias_4(
118-
; CHECK-NEXT: [[A:%.*]] = alloca [16 x i8], align 1
119-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr [[A]])
120-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 8
121-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST:%.*]], ptr [[GEP]], i64 8, i1 false)
122-
; CHECK-NEXT: ret void
123-
;
124-
%a = alloca [16 x i8]
125-
call void @llvm.lifetime.start.p0(i64 12, ptr %a)
126-
%gep = getelementptr i8, ptr %a, i64 8
127-
call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %gep, i64 8, i1 false)
128-
ret void
129-
}
130-
13185
declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
13286

13387
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) nounwind

llvm/test/Transforms/MemCpyOpt/memset-memcpy-oversized.ll

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,6 @@ define void @test_alloca_with_lifetimes(ptr %result) {
3737
ret void
3838
}
3939

40-
; memcpy size is larger than lifetime, don't optimize.
41-
define void @test_copy_larger_than_lifetime_size(ptr %result) {
42-
; CHECK-LABEL: @test_copy_larger_than_lifetime_size(
43-
; CHECK-NEXT: [[A:%.*]] = alloca [[T:%.*]], align 8
44-
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr [[A]])
45-
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false)
46-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A]], i64 16, i1 false)
47-
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr [[A]])
48-
; CHECK-NEXT: call void @free(ptr [[A]])
49-
; CHECK-NEXT: ret void
50-
;
51-
%a = alloca %T, align 8
52-
call void @llvm.lifetime.start.p0(i64 12, ptr %a)
53-
call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false)
54-
call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)
55-
call void @llvm.lifetime.end.p0(i64 12, ptr %a)
56-
call void @free(ptr %a)
57-
ret void
58-
}
59-
6040
; The trailing bytes are not known to be undef, we can't ignore them.
6141
define void @test_not_undef_memory(ptr %result, ptr %input) {
6242
; CHECK-LABEL: @test_not_undef_memory(

0 commit comments

Comments
 (0)