Skip to content

Commit 0216e23

Browse files
author
git apple-llvm automerger
committed
Merge commit '4450780182d3' from apple/stable/20190619 into swift/master
2 parents 618992f + 4450780 commit 0216e23

File tree

2 files changed

+92
-1
lines changed

2 files changed

+92
-1
lines changed

llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,33 @@ void ObjCARCOpt::getAnalysisUsage(AnalysisUsage &AU) const {
588588
AU.setPreservesCFG();
589589
}
590590

591+
static bool isSafeBetweenRVCalls(const Instruction *I) {
592+
if (IsNoopInstruction(I))
593+
return true;
594+
595+
auto *CB = dyn_cast<CallBase>(I);
596+
if (!CB)
597+
return false;
598+
599+
Intrinsic::ID IID = CB->getIntrinsicID();
600+
if (IID == Intrinsic::not_intrinsic)
601+
return false;
602+
603+
switch (IID) {
604+
case Intrinsic::lifetime_start:
605+
case Intrinsic::lifetime_end:
606+
// The inliner adds new lifetime markers as part of the return sequence,
607+
// which should be skipped when looking for paired return RV call.
608+
LLVM_FALLTHROUGH;
609+
case Intrinsic::stacksave:
610+
case Intrinsic::stackrestore:
611+
// If the inlined code contains dynamic allocas, the above applies as well.
612+
return true;
613+
default:
614+
return false;
615+
}
616+
}
617+
591618
/// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is
592619
/// not a return value. Or, if it can be paired with an
593620
/// objc_autoreleaseReturnValue, delete the pair and return true.
@@ -634,7 +661,7 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
634661
if (I != Begin) {
635662
do
636663
--I;
637-
while (I != Begin && IsNoopInstruction(&*I));
664+
while (I != Begin && isSafeBetweenRVCalls(&*I));
638665
if (GetBasicARCInstKind(&*I) == ARCInstKind::AutoreleaseRV &&
639666
EquivalentArgs.count(GetArgRCIdentityRoot(&*I))) {
640667
Changed = true;

llvm/test/Transforms/ObjCARC/post-inlining.ll

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,67 @@ entry:
4646
call void @use_pointer(i8* %p)
4747
ret void
4848
}
49+
50+
; Check that we can delete the autoreleaseRV+retainAutoreleasedRV pair even in
51+
; presence of instructions added by the inliner as part of the return sequence.
52+
53+
; 1) Noop instructions: bitcasts and zero-indices GEPs.
54+
55+
; CHECK-LABEL: define i8* @testNoop(
56+
; CHECK: entry:
57+
; CHECK-NEXT: %noop0 = bitcast i8* %call.i to i64*
58+
; CHECK-NEXT: %noop1 = getelementptr i8, i8* %call.i, i32 0
59+
; CHECK-NEXT: ret i8* %call.i
60+
; CHECK-NEXT: }
61+
define i8* @testNoop(i8* %call.i) {
62+
entry:
63+
%0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind
64+
%noop0 = bitcast i8* %call.i to i64*
65+
%noop1 = getelementptr i8, i8* %call.i, i32 0
66+
%1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call.i) nounwind
67+
ret i8* %call.i
68+
}
69+
70+
; 2) Lifetime markers.
71+
72+
declare void @llvm.lifetime.start.p0i8(i64, i8*)
73+
declare void @llvm.lifetime.end.p0i8(i64, i8*)
74+
75+
; CHECK-LABEL: define i8* @testLifetime(
76+
; CHECK: entry:
77+
; CHECK-NEXT: %obj = alloca i8
78+
; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* %obj)
79+
; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* %obj)
80+
; CHECK-NEXT: ret i8* %call.i
81+
; CHECK-NEXT: }
82+
define i8* @testLifetime(i8* %call.i) {
83+
entry:
84+
%obj = alloca i8
85+
call void @llvm.lifetime.start.p0i8(i64 8, i8* %obj)
86+
%0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind
87+
call void @llvm.lifetime.end.p0i8(i64 8, i8* %obj)
88+
%1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call.i) nounwind
89+
ret i8* %call.i
90+
}
91+
92+
; 3) Dynamic alloca markers.
93+
94+
declare i8* @llvm.stacksave()
95+
declare void @llvm.stackrestore(i8*)
96+
97+
; CHECK-LABEL: define i8* @testStack(
98+
; CHECK: entry:
99+
; CHECK-NEXT: %save = tail call i8* @llvm.stacksave()
100+
; CHECK-NEXT: %obj = alloca i8, i8 %arg
101+
; CHECK-NEXT: call void @llvm.stackrestore(i8* %save)
102+
; CHECK-NEXT: ret i8* %call.i
103+
; CHECK-NEXT: }
104+
define i8* @testStack(i8* %call.i, i8 %arg) {
105+
entry:
106+
%save = tail call i8* @llvm.stacksave()
107+
%obj = alloca i8, i8 %arg
108+
%0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind
109+
call void @llvm.stackrestore(i8* %save)
110+
%1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call.i) nounwind
111+
ret i8* %call.i
112+
}

0 commit comments

Comments
 (0)