forked from OSchip/llvm-project
[ObjC][ARC] Handle operand bundle "clang.arc.attachedcall" on targets
that don't use the inline asm marker This patch makes the changes to the ARC middle-end passes that are needed to handle operand bundle "clang.arc.attachedcall" on targets that don't use the inline asm marker for the retainRV/autoreleaseRV handshake (e.g., x86-64). Note that anyone who wants to use the operand bundle on their target has to teach their backend to handle the operand bundle. The x86-64 backend already knows about the operand bundle (see https://reviews.llvm.org/D94597). Differential Revision: https://reviews.llvm.org/D111334
This commit is contained in:
parent
92c9b340be
commit
8f8d9f743d
|
@ -124,14 +124,19 @@ BundledRetainClaimRVs::~BundledRetainClaimRVs() {
|
|||
if (auto *CI = dyn_cast<CallInst>(CB))
|
||||
CI->setTailCallKind(CallInst::TCK_NoTail);
|
||||
|
||||
// Remove the ARC intrinsic function operand from the operand bundle.
|
||||
OperandBundleDef OB("clang.arc.attachedcall", None);
|
||||
auto *NewCB = CallBase::Create(CB, OB, CB);
|
||||
CB->replaceAllUsesWith(NewCB);
|
||||
CB->eraseFromParent();
|
||||
} else {
|
||||
EraseInstruction(P.first);
|
||||
if (UseMarker) {
|
||||
// Remove the retainRV/claimRV function operand from the operand bundle
|
||||
// to reflect the fact that the backend is responsible for emitting only
|
||||
// the marker instruction, but not the retainRV/claimRV call.
|
||||
OperandBundleDef OB("clang.arc.attachedcall", None);
|
||||
auto *NewCB = CallBase::Create(CB, OB, CB);
|
||||
CB->replaceAllUsesWith(NewCB);
|
||||
CB->eraseFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ContractPass || !UseMarker)
|
||||
EraseInstruction(P.first);
|
||||
}
|
||||
|
||||
RVCalls.clear();
|
||||
|
|
|
@ -105,7 +105,8 @@ CallInst *createCallInstWithColors(
|
|||
|
||||
class BundledRetainClaimRVs {
|
||||
public:
|
||||
BundledRetainClaimRVs(bool ContractPass) : ContractPass(ContractPass) {}
|
||||
BundledRetainClaimRVs(bool ContractPass, bool UseMarker)
|
||||
: ContractPass(ContractPass), UseMarker(UseMarker) {}
|
||||
~BundledRetainClaimRVs();
|
||||
|
||||
/// Insert a retainRV/claimRV call to the normal destination blocks of invokes
|
||||
|
@ -155,6 +156,9 @@ private:
|
|||
DenseMap<CallInst *, CallBase *> RVCalls;
|
||||
|
||||
bool ContractPass;
|
||||
|
||||
/// Indicates whether the target uses a special inline-asm marker.
|
||||
bool UseMarker;
|
||||
};
|
||||
|
||||
} // end namespace objcarc
|
||||
|
|
|
@ -434,13 +434,21 @@ bool ObjCARCContract::tryToPeepholeInstruction(
|
|||
LLVM_FALLTHROUGH;
|
||||
case ARCInstKind::RetainRV:
|
||||
case ARCInstKind::ClaimRV: {
|
||||
// If we're compiling for a target which needs a special inline-asm
|
||||
// marker to do the return value optimization and the retainRV/claimRV call
|
||||
// wasn't bundled with a call, insert the marker now.
|
||||
if (!RVInstMarker)
|
||||
return false;
|
||||
bool IsInstContainedInBundle = BundledInsts->contains(Inst);
|
||||
|
||||
if (BundledInsts->contains(Inst))
|
||||
// Return now if the target doesn't need a special inline-asm marker. Return
|
||||
// true if this is a bundled retainRV/claimRV call, which is going to be
|
||||
// erased at the end of this pass, to avoid undoing objc-arc-expand and
|
||||
// replacing uses of the retainRV/claimRV call's argument with its result.
|
||||
if (!RVInstMarker)
|
||||
return IsInstContainedInBundle;
|
||||
|
||||
// The target needs a special inline-asm marker.
|
||||
|
||||
// We don't have to emit the marker if this is a bundled call since the
|
||||
// backend is responsible for emitting it. Return false to undo
|
||||
// objc-arc-expand.
|
||||
if (IsInstContainedInBundle)
|
||||
return false;
|
||||
|
||||
BasicBlock::iterator BBI = Inst->getIterator();
|
||||
|
@ -540,7 +548,7 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) {
|
|||
AA = A;
|
||||
DT = D;
|
||||
PA.setAA(A);
|
||||
BundledRetainClaimRVs BRV(true);
|
||||
BundledRetainClaimRVs BRV(true, RVInstMarker);
|
||||
BundledInsts = &BRV;
|
||||
|
||||
std::pair<bool, bool> R = BundledInsts->insertAfterInvokes(F, DT);
|
||||
|
|
|
@ -2461,7 +2461,7 @@ bool ObjCARCOpt::run(Function &F, AAResults &AA) {
|
|||
return false;
|
||||
|
||||
Changed = CFGChanged = false;
|
||||
BundledRetainClaimRVs BRV(false);
|
||||
BundledRetainClaimRVs BRV(false, objcarc::getRVInstMarker(*F.getParent()));
|
||||
BundledInsts = &BRV;
|
||||
|
||||
LLVM_DEBUG(dbgs() << "<<< ObjCARCOpt: Visiting Function: " << F.getName()
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
|
||||
; RUN: opt -passes=objc-arc-contract -S < %s | FileCheck %s
|
||||
|
||||
; CHECK-LABEL: define void @test0() {
|
||||
; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
|
||||
; CHECK-NEXT: ret void
|
||||
|
||||
define void @test0() {
|
||||
%call1 = call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define void @test1() {
|
||||
; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
|
||||
; CHECK-NEXT: ret void
|
||||
|
||||
define void @test1() {
|
||||
%call1 = call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i8* @foo()
|
||||
declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
|
||||
declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)
|
Loading…
Reference in New Issue