Skip to content

Commit f429795

Browse files
ahatanakacachemeifyoucan
authored andcommitted
Do not call replaceAllUsesWith to upgrade calls to ARC runtime functions
to intrinsic calls This fixes a bug in r368311. It turns out that the ARC runtime functions in the IR can have pointer parameter types that are not i8* or i8**. Instead of RAUWing normal functions with intrinsics, manually bitcast the arguments before passing them to the intrinsic functions and bitcast the return value back to the type of the original call instruction. This recommits r368634, which was reverted in r368637. The loop in the patch was iterating over uses of a function and deleting function calls inside it, which caused bots to crash. rdar://problem/54125406 Differential Revision: https://reviews.llvm.org/D66047 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368646 91177308-0d34-0410-b5e6-96231b3b80d8 apple-llvm-split-commit: 1f0f94789f0e816ac1eb0f232d9b594a2b2ee290 apple-llvm-split-dir: llvm/
1 parent 3bac3c9 commit f429795

File tree

4 files changed

+92
-9
lines changed

4 files changed

+92
-9
lines changed

llvm/lib/IR/AutoUpgrade.cpp

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3654,6 +3654,8 @@ bool llvm::UpgradeRetainReleaseMarker(Module &M) {
36543654
}
36553655

36563656
void llvm::UpgradeARCRuntimeCalls(Module &M) {
3657+
// This lambda converts normal function calls to ARC runtime functions to
3658+
// intrinsic calls.
36573659
auto UpgradeToIntrinsic = [&](const char *OldFunc,
36583660
llvm::Intrinsic::ID IntrinsicFunc) {
36593661
Function *Fn = M.getFunction(OldFunc);
@@ -3662,11 +3664,44 @@ void llvm::UpgradeARCRuntimeCalls(Module &M) {
36623664
return;
36633665

36643666
Function *NewFn = llvm::Intrinsic::getDeclaration(&M, IntrinsicFunc);
3665-
Fn->replaceAllUsesWith(NewFn);
3666-
Fn->eraseFromParent();
3667+
3668+
for (auto I = Fn->user_begin(), E = Fn->user_end(); I != E;) {
3669+
CallInst *CI = dyn_cast<CallInst>(*I++);
3670+
if (!CI || CI->getCalledFunction() != Fn)
3671+
continue;
3672+
3673+
IRBuilder<> Builder(CI->getParent(), CI->getIterator());
3674+
FunctionType *NewFuncTy = NewFn->getFunctionType();
3675+
SmallVector<Value *, 2> Args;
3676+
3677+
for (unsigned I = 0, E = CI->getNumArgOperands(); I != E; ++I) {
3678+
Value *Arg = CI->getArgOperand(I);
3679+
// Bitcast argument to the parameter type of the new function if it's
3680+
// not a variadic argument.
3681+
if (I < NewFuncTy->getNumParams())
3682+
Arg = Builder.CreateBitCast(Arg, NewFuncTy->getParamType(I));
3683+
Args.push_back(Arg);
3684+
}
3685+
3686+
// Create a call instruction that calls the new function.
3687+
CallInst *NewCall = Builder.CreateCall(NewFuncTy, NewFn, Args);
3688+
NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind());
3689+
NewCall->setName(CI->getName());
3690+
3691+
// Bitcast the return value back to the type of the old call.
3692+
Value *NewRetVal = Builder.CreateBitCast(NewCall, CI->getType());
3693+
3694+
if (!CI->use_empty())
3695+
CI->replaceAllUsesWith(NewRetVal);
3696+
CI->eraseFromParent();
3697+
}
3698+
3699+
if (Fn->use_empty())
3700+
Fn->eraseFromParent();
36673701
};
36683702

3669-
// Unconditionally convert "clang.arc.use" to "llvm.objc.clang.arc.use".
3703+
// Unconditionally convert a call to "clang.arc.use" to a call to
3704+
// "llvm.objc.clang.arc.use".
36703705
UpgradeToIntrinsic("clang.arc.use", llvm::Intrinsic::objc_clang_arc_use);
36713706

36723707
// Return if the bitcode doesn't have the arm64 retainAutoreleasedReturnValue
144 Bytes
Binary file not shown.

llvm/test/Bitcode/upgrade-arc-runtime-calls.ll

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,62 @@
88
; RUN: llvm-dis < %S/upgrade-arc-runtime-calls.bc | FileCheck -check-prefixes=ARC %s
99
; RUN: llvm-dis < %S/upgrade-mrr-runtime-calls.bc | FileCheck -check-prefixes=MRR %s
1010

11-
// ARC: define void @testRuntimeCalls(i8* %[[A:.*]], i8** %[[B:.*]], i8** %[[C:.*]]) {
11+
define void @testRuntimeCalls(i8* %a, i8** %b, i8** %c, i32* %d, i32** %e) personality i32 (...)* @__gxx_personality_v0 {
12+
entry:
13+
%v0 = tail call i8* @objc_autorelease(i8* %a) #0
14+
tail call void @objc_autoreleasePoolPop(i8* %a) #0
15+
%v1 = tail call i8* @objc_autoreleasePoolPush() #0
16+
%v2 = tail call i8* @objc_autoreleaseReturnValue(i8* %a) #0
17+
tail call void @objc_copyWeak(i8** %b, i8** %c) #0
18+
tail call void @objc_destroyWeak(i8** %b) #0
19+
%v3 = tail call i32* @objc_initWeak(i32** %e, i32* %d) #0
20+
%v4 = tail call i8* @objc_loadWeak(i8** %b) #0
21+
%v5 = tail call i8* @objc_loadWeakRetained(i8** %b) #0
22+
tail call void @objc_moveWeak(i8** %b, i8** %c) #0
23+
tail call void @objc_release(i8* %a) #0
24+
%v6 = tail call i8* @objc_retain(i8* %a) #0
25+
%v7 = tail call i8* @objc_retainAutorelease(i8* %a) #0
26+
%v8 = tail call i8* @objc_retainAutoreleaseReturnValue(i8* %a) #0
27+
%v9 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %a) #0
28+
%v10 = tail call i8* @objc_retainBlock(i8* %a) #0
29+
tail call void @objc_storeStrong(i8** %b, i8* %a) #0
30+
%v11 = tail call i8* @objc_storeWeak(i8** %b, i8* %a) #0
31+
tail call void (...) @clang.arc.use(i8* %a) #0
32+
%v12 = tail call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %a) #0
33+
%v13 = tail call i8* @objc_retainedObject(i8* %a) #0
34+
%v14 = tail call i8* @objc_unretainedObject(i8* %a) #0
35+
%v15 = tail call i8* @objc_unretainedPointer(i8* %a) #0
36+
%v16 = tail call i8* @objc_retain.autorelease(i8* %a) #0
37+
%v17 = tail call i32 @objc_sync.enter(i8* %a) #0
38+
%v18 = tail call i32 @objc_sync.exit(i8* %a) #0
39+
tail call void @objc_arc_annotation_topdown_bbstart(i8** %b, i8** %c) #0
40+
tail call void @objc_arc_annotation_topdown_bbend(i8** %b, i8** %c) #0
41+
tail call void @objc_arc_annotation_bottomup_bbstart(i8** %b, i8** %c) #0
42+
tail call void @objc_arc_annotation_bottomup_bbend(i8** %b, i8** %c) #0
43+
invoke void @objc_autoreleasePoolPop(i8* %a)
44+
to label %normalBlock unwind label %unwindBlock
45+
normalBlock:
46+
ret void
47+
unwindBlock:
48+
%ll = landingpad { i8*, i32 }
49+
cleanup
50+
ret void
51+
}
52+
53+
// Check that auto-upgrader converts function calls to intrinsic calls. Note that
54+
// the auto-upgrader doesn't touch invoke instructions.
55+
56+
// ARC: define void @testRuntimeCalls(i8* %[[A:.*]], i8** %[[B:.*]], i8** %[[C:.*]], i32* %[[D:.*]], i32** %[[E:.*]]) personality
1257
// ARC: %[[V0:.*]] = tail call i8* @llvm.objc.autorelease(i8* %[[A]])
1358
// ARC-NEXT: tail call void @llvm.objc.autoreleasePoolPop(i8* %[[A]])
1459
// ARC-NEXT: %[[V1:.*]] = tail call i8* @llvm.objc.autoreleasePoolPush()
1560
// ARC-NEXT: %[[V2:.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[A]])
1661
// ARC-NEXT: tail call void @llvm.objc.copyWeak(i8** %[[B]], i8** %[[C]])
1762
// ARC-NEXT: tail call void @llvm.objc.destroyWeak(i8** %[[B]])
18-
// ARC-NEXT: %[[V3:.*]] = tail call i8* @llvm.objc.initWeak(i8** %[[B]], i8* %[[A]])
63+
// ARC-NEXT: %[[V100:.*]] = bitcast i32** %[[E]] to i8**
64+
// ARC-NEXT: %[[V101:.*]] = bitcast i32* %[[D]] to i8*
65+
// ARC-NEXT: %[[V102:.*]] = tail call i8* @llvm.objc.initWeak(i8** %[[V100]], i8* %[[V101]])
66+
// ARC-NEXT: %[[V103:.*]] = bitcast i8* %[[V102]] to i32*
1967
// ARC-NEXT: %[[V4:.*]] = tail call i8* @llvm.objc.loadWeak(i8** %[[B]])
2068
// ARC-NEXT: %[[V5:.*]] = tail call i8* @llvm.objc.loadWeakRetained(i8** %[[B]])
2169
// ARC-NEXT: tail call void @llvm.objc.moveWeak(i8** %[[B]], i8** %[[C]])
@@ -39,16 +87,16 @@
3987
// ARC-NEXT: tail call void @llvm.objc.arc.annotation.topdown.bbend(i8** %[[B]], i8** %[[C]])
4088
// ARC-NEXT: tail call void @llvm.objc.arc.annotation.bottomup.bbstart(i8** %[[B]], i8** %[[C]])
4189
// ARC-NEXT: tail call void @llvm.objc.arc.annotation.bottomup.bbend(i8** %[[B]], i8** %[[C]])
42-
// ARC-NEXT: ret void
90+
// ARC-NEXT: invoke void @objc_autoreleasePoolPop(i8* %[[A]])
4391

44-
// MRR: define void @testRuntimeCalls(i8* %[[A:.*]], i8** %[[B:.*]], i8** %[[C:.*]]) {
92+
// MRR: define void @testRuntimeCalls(i8* %[[A:.*]], i8** %[[B:.*]], i8** %[[C:.*]], i32* %[[D:.*]], i32** %[[E:.*]]) personality
4593
// MRR: %[[V0:.*]] = tail call i8* @objc_autorelease(i8* %[[A]])
4694
// MRR-NEXT: tail call void @objc_autoreleasePoolPop(i8* %[[A]])
4795
// MRR-NEXT: %[[V1:.*]] = tail call i8* @objc_autoreleasePoolPush()
4896
// MRR-NEXT: %[[V2:.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* %[[A]])
4997
// MRR-NEXT: tail call void @objc_copyWeak(i8** %[[B]], i8** %[[C]])
5098
// MRR-NEXT: tail call void @objc_destroyWeak(i8** %[[B]])
51-
// MRR-NEXT: %[[V3:.*]] = tail call i8* @objc_initWeak(i8** %[[B]], i8* %[[A]])
99+
// MRR-NEXT: %[[V3:.*]] = tail call i32* @objc_initWeak(i32** %[[E]], i32* %[[D]])
52100
// MRR-NEXT: %[[V4:.*]] = tail call i8* @objc_loadWeak(i8** %[[B]])
53101
// MRR-NEXT: %[[V5:.*]] = tail call i8* @objc_loadWeakRetained(i8** %[[B]])
54102
// MRR-NEXT: tail call void @objc_moveWeak(i8** %[[B]], i8** %[[C]])
@@ -72,4 +120,4 @@
72120
// MRR-NEXT: tail call void @objc_arc_annotation_topdown_bbend(i8** %[[B]], i8** %[[C]])
73121
// MRR-NEXT: tail call void @objc_arc_annotation_bottomup_bbstart(i8** %[[B]], i8** %[[C]])
74122
// MRR-NEXT: tail call void @objc_arc_annotation_bottomup_bbend(i8** %[[B]], i8** %[[C]])
75-
// MRR-NEXT: ret void
123+
// MRR-NEXT: invoke void @objc_autoreleasePoolPop(i8* %[[A]])
160 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)