Skip to content

Commit f4b39a5

Browse files
clin111Fznamznon
authored andcommitted
Patch bug in 9a45e4b. Prevent SSA breaks when lifetime intrinsics are moved.
1 parent 2629cbb commit f4b39a5

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,14 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,
931931
return false;
932932
}
933933

934+
// Code below tries to move the lifetime marker before "C". Check the
935+
// correctness of this motion.
936+
if (SkippedLifetimeStart && SkippedLifetimeStart->getNumOperands() == 3) {
937+
auto *LiveI = cast<Instruction>(SkippedLifetimeStart->getOperand(1));
938+
if (!DT->dominates(LiveI, C))
939+
return false;
940+
}
941+
934942
// Check that accessing the first srcSize bytes of dest will not cause a
935943
// trap. Otherwise the transform is invalid since it might cause a trap
936944
// to occur earlier than it otherwise would.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -passes="memcpyopt" -S %s | FileCheck %s
3+
4+
; memcpyopt lifetime skipping, is moving the lifetime.start before the def
5+
; of %tm3.
6+
7+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
8+
target triple = "x86_64-unknown-linux-gnu"
9+
10+
%struct.foo = type { ptr, ptr, i64, i64 }
11+
12+
declare dso_local i32 @pluto(...)
13+
14+
define dso_local void @wombat(ptr %meow) local_unnamed_addr {
15+
; CHECK-LABEL: @wombat(
16+
; CHECK-NEXT: bb:
17+
; CHECK-NEXT: [[TM:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8
18+
; CHECK-NEXT: [[TM1:%.*]] = alloca [[STRUCT_FOO]], align 8
19+
; CHECK-NEXT: [[TM2:%.*]] = bitcast ptr [[TM1]] to ptr
20+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(32) [[TM2]], ptr noundef nonnull align 8 dereferenceable(32) [[MEOW:%.*]], i64 32, i1 false)
21+
; CHECK-NEXT: [[TM3:%.*]] = bitcast ptr [[TM]] to ptr
22+
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[TM3]])
23+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TM3]], ptr align 8 [[MEOW]], i64 32, i1 false)
24+
; CHECK-NEXT: ret void
25+
;
26+
bb:
27+
%tm = alloca %struct.foo, align 8
28+
%tm1 = alloca %struct.foo, align 8
29+
%tm2 = bitcast ptr %tm1 to ptr
30+
call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(32) %tm2, ptr noundef nonnull align 8 dereferenceable(32) %meow, i64 32, i1 false)
31+
%tm3 = bitcast ptr %tm to ptr
32+
call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %tm3)
33+
call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(32) %tm3, ptr noundef nonnull align 8 dereferenceable(32) %tm2, i64 32, i1 false)
34+
ret void
35+
}
36+
37+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
38+
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
39+
40+
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
41+
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #2
42+
43+
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
44+
attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

0 commit comments

Comments
 (0)