[llvm] 634ca73 - [ObjCARC] Require the function argument in the clang.arc.attachedcall bundle.
Ahmed Bougacha via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 28 12:42:06 PST 2022
Author: Ahmed Bougacha
Date: 2022-01-28T12:41:45-08:00
New Revision: 634ca7349d4a467b993321ff3152c2e044f1f487
URL: https://github.com/llvm/llvm-project/commit/634ca7349d4a467b993321ff3152c2e044f1f487
DIFF: https://github.com/llvm/llvm-project/commit/634ca7349d4a467b993321ff3152c2e044f1f487.diff
LOG: [ObjCARC] Require the function argument in the clang.arc.attachedcall bundle.
Currently, the clang.arc.attachedcall bundle takes an optional function
argument. Depending on whether the argument is present, calls with this
bundle have the following semantics:
- on x86, with the argument present, the call is lowered to:
call _target
mov rax, rdi
call _objc_retainAutoreleasedReturnValue
- on AArch64, without the argument, the call is lowered to:
bl _target
mov x29, x29
and the objc runtime call is expected to be emitted separately.
That's because, on x86, the objc runtime checks for both the mov and
the call on x86, and treats the combination as the ARC autorelease elision
marker.
But on AArch64, it only checks for the dedicated NOP marker, as that's
historically been sufficiently unique. Thanks to that, the runtime call
wasn't required to be adjacent to the NOP marker, so it wasn't emitted
as part of the bundle sequence.
This patch unifies both architectures: on AArch64, we now emit all
3 instructions for the bundle. This guarantees that the runtime call
is adjacent to the marker in the sequence, and that's information the
runtime can use to further optimize this.
This helps simplify some of the handling, in particular
BundledRetainClaimRVs, which no longer needs to know whether the bundle
is sufficient or not: it now always should be.
Note that this does not include an AutoUpgrade for the nullary bundles,
as they are only produced in ObjCContract as part of the obj/asm emission
pipeline, and are not expected to be in bitcode.
Differential Revision: https://reviews.llvm.org/D118214
Added:
Modified:
llvm/docs/LangRef.rst
llvm/include/llvm/Analysis/ObjCARCUtil.h
llvm/lib/IR/Verifier.cpp
llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.td
llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
llvm/lib/Transforms/ObjCARC/ObjCARC.h
llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
llvm/test/CodeGen/AArch64/call-rv-marker.ll
llvm/test/CodeGen/AArch64/expand-blr-rvmarker-pseudo.mir
llvm/test/CodeGen/AArch64/rvmarker-pseudo-expansion-and-outlining.mir
llvm/test/CodeGen/X86/call-rv-marker.ll
llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll
llvm/test/Transforms/ObjCARC/contract-rv-attr.ll
llvm/test/Verifier/operand-bundles.ll
Removed:
################################################################################
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 72a99cbfae62d..40f23205e531e 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -2485,13 +2485,11 @@ ObjC ARC Attached Call Operand Bundles
A ``"clang.arc.attachedcall"`` operand bundle on a call indicates the call is
implicitly followed by a marker instruction and a call to an ObjC runtime
-function that uses the result of the call. The operand bundle takes either the
+function that uses the result of the call. The operand bundle takes a mandatory
pointer to the runtime function (``@objc_retainAutoreleasedReturnValue`` or
-``@objc_unsafeClaimAutoreleasedReturnValue``) or no arguments. If the bundle
-doesn't take any arguments, only the marker instruction has to be emitted after
-the call; the runtime function calls don't have to be emitted since they already
-have been emitted. The return value of a call with this bundle is used by a call
-to ``@llvm.objc.clang.arc.noop.use`` unless the called function's return type is
+``@objc_unsafeClaimAutoreleasedReturnValue``).
+The return value of a call with this bundle is used by a call to
+``@llvm.objc.clang.arc.noop.use`` unless the called function's return type is
void, in which case the operand bundle is ignored.
.. code-block:: llvm
@@ -2501,11 +2499,8 @@ void, in which case the operand bundle is ignored.
call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_unsafeClaimAutoreleasedReturnValue) ]
- ; Only the marker instruction is inserted after the call to @foo.
- call i8* @foo() [ "clang.arc.attachedcall"() ]
-
The operand bundle is needed to ensure the call is immediately followed by the
-marker instruction or the ObjC runtime call in the final output.
+marker instruction and the ObjC runtime call in the final output.
.. _moduleasm:
diff --git a/llvm/include/llvm/Analysis/ObjCARCUtil.h b/llvm/include/llvm/Analysis/ObjCARCUtil.h
index 1d330ca58a872..385fa54229264 100644
--- a/llvm/include/llvm/Analysis/ObjCARCUtil.h
+++ b/llvm/include/llvm/Analysis/ObjCARCUtil.h
@@ -42,7 +42,7 @@ inline bool hasAttachedCallOpBundle(const CallBase *CB) {
/// which is the address of the ARC runtime function.
inline Optional<Function *> getAttachedARCFunction(const CallBase *CB) {
auto B = CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall);
- if (!B.hasValue() || B->Inputs.size() == 0)
+ if (!B)
return None;
return cast<Function>(B->Inputs[0]);
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index b84edb7894058..228eeaa772610 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5811,15 +5811,11 @@ void Verifier::verifyAttachedCallBundle(const CallBase &Call,
"void return type",
Call);
- Assert((BU.Inputs.empty() ||
- (BU.Inputs.size() == 1 && isa<Function>(BU.Inputs.front()))),
- "operand bundle \"clang.arc.attachedcall\" can take either no "
- "arguments or one function as an argument",
+ Assert(BU.Inputs.size() == 1 && isa<Function>(BU.Inputs.front()),
+ "operand bundle \"clang.arc.attachedcall\" requires one function as "
+ "an argument",
Call);
- if (BU.Inputs.empty())
- return;
-
auto *Fn = cast<Function>(BU.Inputs.front());
Intrinsic::ID IID = Fn->getIntrinsicID();
diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
index 109b739528bf4..b0f739cc26e69 100644
--- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
@@ -709,20 +709,24 @@ bool AArch64ExpandPseudo::expandSVESpillFill(MachineBasicBlock &MBB,
bool AArch64ExpandPseudo::expandCALL_RVMARKER(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
- // Expand CALL_RVMARKER pseudo to a branch, followed by the special `mov x29,
- // x29` marker. Mark the sequence as bundle, to avoid passes moving other code
- // in between.
+ // Expand CALL_RVMARKER pseudo to:
+ // - a branch to the call target, followed by
+ // - the special `mov x29, x29` marker, and
+ // - another branch, to the runtime function
+ // Mark the sequence as bundle, to avoid passes moving other code in between.
MachineInstr &MI = *MBBI;
MachineInstr *OriginalCall;
- MachineOperand &CallTarget = MI.getOperand(0);
+ MachineOperand &RVTarget = MI.getOperand(0);
+ MachineOperand &CallTarget = MI.getOperand(1);
assert((CallTarget.isGlobal() || CallTarget.isReg()) &&
"invalid operand for regular call");
+ assert(RVTarget.isGlobal() && "invalid operand for attached call");
unsigned Opc = CallTarget.isGlobal() ? AArch64::BL : AArch64::BLR;
OriginalCall = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc)).getInstr();
OriginalCall->addOperand(CallTarget);
- unsigned RegMaskStartIdx = 1;
+ unsigned RegMaskStartIdx = 2;
// Skip register arguments. Those are added during ISel, but are not
// needed for the concrete branch.
while (!MI.getOperand(RegMaskStartIdx).isRegMask()) {
@@ -736,17 +740,22 @@ bool AArch64ExpandPseudo::expandCALL_RVMARKER(
llvm::drop_begin(MI.operands(), RegMaskStartIdx))
OriginalCall->addOperand(MO);
- auto *Marker = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORRXrs))
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORRXrs))
.addReg(AArch64::FP, RegState::Define)
.addReg(AArch64::XZR)
.addReg(AArch64::FP)
- .addImm(0)
+ .addImm(0);
+
+ auto *RVCall = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::BL))
+ .add(RVTarget)
.getInstr();
+
if (MI.shouldUpdateCallSiteInfo())
- MBB.getParent()->moveCallSiteInfo(&MI, Marker);
+ MBB.getParent()->moveCallSiteInfo(&MI, OriginalCall);
+
MI.eraseFromParent();
finalizeBundle(MBB, OriginalCall->getIterator(),
- std::next(Marker->getIterator()));
+ std::next(RVCall->getIterator()));
return true;
}
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 9430c8c3bac4f..42a231b82d47b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -6475,12 +6475,18 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
unsigned CallOpc = AArch64ISD::CALL;
// Calls with operand bundle "clang.arc.attachedcall" are special. They should
- // be expanded to the call, directly followed by a special marker sequence.
- // Use the CALL_RVMARKER to do that.
+ // be expanded to the call, directly followed by a special marker sequence and
+ // a call to an ObjC library function. Use CALL_RVMARKER to do that.
if (CLI.CB && objcarc::hasAttachedCallOpBundle(CLI.CB)) {
assert(!IsTailCall &&
"tail calls cannot be marked with clang.arc.attachedcall");
CallOpc = AArch64ISD::CALL_RVMARKER;
+
+ // Add a target global address for the retainRV/claimRV runtime function
+ // just before the call target.
+ Function *ARCFn = *objcarc::getAttachedARCFunction(CLI.CB);
+ auto GA = DAG.getTargetGlobalAddress(ARCFn, DL, PtrVT);
+ Ops.insert(Ops.begin() + 1, GA);
}
// Returns a chain and a flag for retval copy to use.
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index c8a697c8b82fa..4ea70da56c237 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2324,8 +2324,8 @@ def : Pat<(AArch64call GPR64noip:$Rn),
(BLRNoIP GPR64noip:$Rn)>,
Requires<[SLSBLRMitigation]>;
-def : Pat<(AArch64call_rvmarker GPR64:$Rn),
- (BLR_RVMARKER GPR64:$Rn)>,
+def : Pat<(AArch64call_rvmarker (i64 tglobaladdr:$rvfunc), GPR64:$Rn),
+ (BLR_RVMARKER tglobaladdr:$rvfunc, GPR64:$Rn)>,
Requires<[NoSLSBLRMitigation]>;
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
index 1ca6ddabac5bc..126845bb3308c 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
@@ -123,20 +123,9 @@ BundledRetainClaimRVs::~BundledRetainClaimRVs() {
// can't be tail calls.
if (auto *CI = dyn_cast<CallInst>(CB))
CI->setTailCallKind(CallInst::TCK_NoTail);
-
- 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);
+ EraseInstruction(P.first);
}
RVCalls.clear();
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.h b/llvm/lib/Transforms/ObjCARC/ObjCARC.h
index 2b47bec7ffe82..62f88a8cc02ba 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARC.h
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.h
@@ -105,8 +105,7 @@ CallInst *createCallInstWithColors(
class BundledRetainClaimRVs {
public:
- BundledRetainClaimRVs(bool ContractPass, bool UseMarker)
- : ContractPass(ContractPass), UseMarker(UseMarker) {}
+ BundledRetainClaimRVs(bool ContractPass) : ContractPass(ContractPass) {}
~BundledRetainClaimRVs();
/// Insert a retainRV/claimRV call to the normal destination blocks of invokes
@@ -156,9 +155,6 @@ class BundledRetainClaimRVs {
DenseMap<CallInst *, CallBase *> RVCalls;
bool ContractPass;
-
- /// Indicates whether the target uses a special inline-asm marker.
- bool UseMarker;
};
} // end namespace objcarc
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
index 9e2832827686a..2985ae004d3cc 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
@@ -434,23 +434,20 @@ bool ObjCARCContract::tryToPeepholeInstruction(
LLVM_FALLTHROUGH;
case ARCInstKind::RetainRV:
case ARCInstKind::UnsafeClaimRV: {
- bool IsInstContainedInBundle = 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
+ // Return true if this is a bundled retainRV/claimRV call, which is always
+ // redundant with the attachedcall in the bundle, and is going to be erased
+ // at the end of this pass. This avoids 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.
+ if (BundledInsts->contains(Inst))
+ return true;
- // 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)
+ // If this isn't a bundled call, and the target doesn't need a special
+ // inline-asm marker, we're done: return now, and undo objc-arc-expand.
+ if (!RVInstMarker)
return false;
+ // The target needs a special inline-asm marker. Insert it.
+
BasicBlock::iterator BBI = Inst->getIterator();
BasicBlock *InstParent = Inst->getParent();
@@ -548,7 +545,7 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) {
AA = A;
DT = D;
PA.setAA(A);
- BundledRetainClaimRVs BRV(true, RVInstMarker);
+ BundledRetainClaimRVs BRV(/*ContractPass=*/true);
BundledInsts = &BRV;
std::pair<bool, bool> R = BundledInsts->insertAfterInvokes(F, DT);
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
index b6dc97f1e43f8..e1a000b31cf93 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
@@ -2459,7 +2459,7 @@ bool ObjCARCOpt::run(Function &F, AAResults &AA) {
return false;
Changed = CFGChanged = false;
- BundledRetainClaimRVs BRV(false, objcarc::getRVInstMarker(*F.getParent()));
+ BundledRetainClaimRVs BRV(/*ContractPass=*/false);
BundledInsts = &BRV;
LLVM_DEBUG(dbgs() << "<<< ObjCARCOpt: Visiting Function: " << F.getName()
diff --git a/llvm/test/CodeGen/AArch64/call-rv-marker.ll b/llvm/test/CodeGen/AArch64/call-rv-marker.ll
index 3f53b5b487279..d6ba82c5c375d 100644
--- a/llvm/test/CodeGen/AArch64/call-rv-marker.ll
+++ b/llvm/test/CodeGen/AArch64/call-rv-marker.ll
@@ -25,15 +25,29 @@ declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
@g = dso_local global i8* null, align 8
@fptr = dso_local global i8* ()* null, align 8
-define dso_local i8* @rv_marker_1() {
-; CHECK-LABEL: rv_marker_1:
+define dso_local i8* @rv_marker_1_retain() {
+; CHECK-LABEL: rv_marker_1_retain:
; CHECK: .cfi_offset w30, -16
; CHECK-NEXT: bl foo1
; SELDAG-NEXT: mov x29, x29
+; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue
; GISEL-NOT: mov x29, x29
;
entry:
- %call = call i8* @foo1() [ "clang.arc.attachedcall"() ]
+ %call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
+ ret i8* %call
+}
+
+define dso_local i8* @rv_marker_1_unsafeClaim() {
+; CHECK-LABEL: rv_marker_1_unsafeClaim:
+; CHECK: .cfi_offset w30, -16
+; CHECK-NEXT: bl foo1
+; SELDAG-NEXT: mov x29, x29
+; SELDAG-NEXT: bl objc_unsafeClaimAutoreleasedReturnValue
+; GISEL-NOT: mov x29, x29
+;
+entry:
+ %call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_unsafeClaimAutoreleasedReturnValue) ]
ret i8* %call
}
@@ -43,13 +57,14 @@ define dso_local void @rv_marker_2_select(i32 %c) {
; GISEL: csinc w0, w8, wzr, eq
; CHECK-NEXT: bl foo0
; SELDAG-NEXT: mov x29, x29
+; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue
; CHECK-NEXT: ldr x30, [sp], #16
; CHECK-NEXT: b foo2
;
entry:
%tobool.not = icmp eq i32 %c, 0
%.sink = select i1 %tobool.not, i32 2, i32 1
- %call1 = call i8* @foo0(i32 %.sink) [ "clang.arc.attachedcall"() ]
+ %call1 = call i8* @foo0(i32 %.sink) [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
tail call void @foo2(i8* %call1)
ret void
}
@@ -59,9 +74,10 @@ define dso_local void @rv_marker_3() personality i8* bitcast (i32 (...)* @__gxx_
; CHECK: .cfi_offset w30, -32
; CHECK-NEXT: bl foo1
; SELDAG-NEXT: mov x29, x29
+; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue
;
entry:
- %call = call i8* @foo1() [ "clang.arc.attachedcall"() ]
+ %call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
invoke void @objc_object(i8* %call) #5
to label %invoke.cont unwind label %lpad
@@ -81,13 +97,14 @@ define dso_local void @rv_marker_4() personality i8* bitcast (i32 (...)* @__gxx_
; CHECK: .Ltmp3:
; CHECK-NEXT: bl foo1
; SELDAG-NEXT: mov x29, x29
+; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue
; CHECK-NEXT: .Ltmp4:
;
entry:
%s = alloca %struct.S, align 1
%0 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 0
call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %0) #2
- %call = invoke i8* @foo1() [ "clang.arc.attachedcall"() ]
+ %call = invoke i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
to label %invoke.cont unwind label %lpad
invoke.cont: ; preds = %entry
@@ -122,12 +139,13 @@ define dso_local i8* @rv_marker_5_indirect_call() {
; CHECK-LABEL: rv_marker_5_indirect_call
; CHECK: ldr [[ADDR:x[0-9]+]], [
; CHECK-NEXT: blr [[ADDR]]
-; SLEDAG-NEXT: mov x29, x29
+; SELDAG-NEXT: mov x29, x29
+; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue
; GISEL-NOT: mov x29, x29
;
entry:
%0 = load i8* ()*, i8* ()** @fptr, align 8
- %call = call i8* %0() [ "clang.arc.attachedcall"() ]
+ %call = call i8* %0() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
tail call void @foo2(i8* %call)
ret i8* %call
}
@@ -141,9 +159,12 @@ define dso_local void @rv_marker_multiarg(i64 %a, i64 %b, i64 %c) {
; CHECK-NEXT: mov x2, [[TMP]]
; CHECK-NEXT: bl foo
; SELDAG-NEXT: mov x29, x29
+; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue
; GISEL-NOT: mov x29, x29
- call i8* @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"() ]
+ call i8* @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
ret void
}
+declare i8* @objc_retainAutoreleasedReturnValue(i8*)
+declare i8* @objc_unsafeClaimAutoreleasedReturnValue(i8*)
declare i32 @__gxx_personality_v0(...)
diff --git a/llvm/test/CodeGen/AArch64/expand-blr-rvmarker-pseudo.mir b/llvm/test/CodeGen/AArch64/expand-blr-rvmarker-pseudo.mir
index cd85066bdcb7b..986e6ddd7f2da 100644
--- a/llvm/test/CodeGen/AArch64/expand-blr-rvmarker-pseudo.mir
+++ b/llvm/test/CodeGen/AArch64/expand-blr-rvmarker-pseudo.mir
@@ -25,6 +25,7 @@
ret void
}
+ declare i8* @attachedcall()
...
---
@@ -33,6 +34,7 @@
# CHECK-NEXT: BUNDLE implicit-def $lr, implicit-def $w30, implicit-def $sp, implicit-def $wsp, implicit-def dead $x0, implicit-def $fp, implicit-def $w29, implicit $x0, implicit $sp, implicit $xzr, implicit $fp {
# CHECK-NEXT: BLR $x0, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
# CHECK-NEXT: ORRXrs $xzr, $fp, 0
+# CHECK-NEXT: BL @attachedcall, implicit-def $lr, implicit internal $sp
# CHECK-NEXT: }
# CHECK-NEXT: RET undef $lr, implicit killed $w0
#
@@ -44,7 +46,7 @@ body: |
bb.0:
liveins: $lr, $x0
- BLR_RVMARKER $x0, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
+ BLR_RVMARKER @attachedcall, $x0, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
RET_ReallyLR implicit killed $w0
...
@@ -53,6 +55,7 @@ body: |
# CHECK-NEXT: BUNDLE implicit-def $lr, implicit-def $w30, implicit-def $sp, implicit-def $wsp, implicit-def dead $x0, implicit-def $fp, implicit-def $w29, implicit $sp, implicit $x0, implicit $xzr, implicit $fp {
# CHECK-NEXT: BL @foo, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
# CHECK-NEXT: $fp = ORRXrs $xzr, $fp, 0
+# CHECK-NEXT: BL @attachedcall, implicit-def $lr, implicit internal $sp
# CHECK-NEXT: }
# CHECK-NEXT: RET undef $lr, implicit killed $w0
#
@@ -61,7 +64,7 @@ body: |
bb.0:
liveins: $lr, $x0
- BLR_RVMARKER @foo, $x0, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
+ BLR_RVMARKER @attachedcall, @foo, $x0, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
RET_ReallyLR implicit killed $w0
...
@@ -70,6 +73,7 @@ body: |
# CHECK-NEXT: BUNDLE implicit-def $lr, implicit-def $w30, implicit-def $sp, implicit-def $wsp, implicit-def $x0, implicit-def $w0, implicit-def $fp, implicit-def $w29, implicit $sp, implicit $x0, implicit $x1, implicit $x2, implicit $xzr, implicit $fp {
# CHECK-NEXT: BL @foo, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0, implicit $x1, implicit $x2, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $x0
# CHECK-NEXT: $fp = ORRXrs $xzr, $fp, 0
+# CHECK-NEXT: BL @attachedcall, implicit-def $lr, implicit internal $sp
# CHECK-NEXT: }
# CHECK-NEXT: RET undef $lr
#
@@ -78,7 +82,7 @@ body: |
bb.0:
liveins: $lr, $x0, $x1, $x2
- BLR_RVMARKER @foo, $x0, $x1, $x2, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $x0
+ BLR_RVMARKER @attachedcall, @foo, $x0, $x1, $x2, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $x0
RET_ReallyLR
...
@@ -87,6 +91,7 @@ body: |
# CHECK-NEXT: BUNDLE implicit-def $lr, implicit-def $w30, implicit-def $sp, implicit-def $wsp, implicit-def dead $x0, implicit-def $fp, implicit-def $w29, implicit $sp, implicit $w0, implicit $w1, implicit $xzr, implicit $fp {
# CHECK-NEXT: BL @foo, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0, implicit $w1, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
# CHECK-NEXT: $fp = ORRXrs $xzr, $fp, 0
+# CHECK-NEXT: BL @attachedcall, implicit-def $lr, implicit internal $sp
# CHECK-NEXT: }
# CHECK-NEXT: RET undef $lr, implicit killed $w0
#
@@ -95,7 +100,7 @@ body: |
bb.0:
liveins: $lr, $w0, $w1
- BLR_RVMARKER @foo, $w0, $w1, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
+ BLR_RVMARKER @attachedcall, @foo, $w0, $w1, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
RET_ReallyLR implicit killed $w0
...
@@ -105,6 +110,7 @@ body: |
# CHECK-NEXT: BUNDLE implicit-def $lr, implicit-def $w30, implicit-def $sp, implicit-def $wsp, implicit-def dead $x0, implicit-def $fp, implicit-def $w29, implicit $x8, implicit $sp, implicit $w0, implicit $w1, implicit $xzr, implicit $fp {
# CHECK-NEXT: BLR $x8, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0, implicit $w1, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
# CHECK-NEXT: $fp = ORRXrs $xzr, $fp, 0
+# CHECK-NEXT: BL @attachedcall, implicit-def $lr, implicit internal $sp
# CHECK-NEXT: }
# CHECK-NEXT: RET undef $lr, implicit killed $w0
#
@@ -113,6 +119,6 @@ body: |
bb.0:
liveins: $lr, $x8, $w0, $w1
- BLR_RVMARKER $x8, $w0, $w1, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
+ BLR_RVMARKER @attachedcall, $x8, $w0, $w1, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def dead $x0
RET_ReallyLR implicit killed $w0
...
diff --git a/llvm/test/CodeGen/AArch64/rvmarker-pseudo-expansion-and-outlining.mir b/llvm/test/CodeGen/AArch64/rvmarker-pseudo-expansion-and-outlining.mir
index be630915093e4..4c2f002d37d25 100644
--- a/llvm/test/CodeGen/AArch64/rvmarker-pseudo-expansion-and-outlining.mir
+++ b/llvm/test/CodeGen/AArch64/rvmarker-pseudo-expansion-and-outlining.mir
@@ -1,18 +1,20 @@
# RUN: llc -enable-machine-outliner -start-before=aarch64-expand-pseudo -mtriple=arm64-apple-ios -o - %s | FileCheck %s
#
# The calls to _cb1 & _cb2 should be followed by the marker instruction
-# 'mov x29, x29'. The marker should not get outlined.
+# 'mov x29, x29' and the attached call. Neither should get outlined.
#
# CHECK-LABEL: _fn1:
# CHECK: bb.0:
# CHECK: bl _cb1
# CHECK-NEXT: mov x29, x29
+# CHECK-NEXT: bl _attachedcall
# CHECK: b _OUTLINED_FUNCTION_0
#
# CHECK-LABEL: _fn2:
# CHECK: bb.0:
# CHECK: bl _cb2
# CHECK-NEXT: mov x29, x29
+# CHECK-NEXT: bl _attachedcall
# CHECK: b _OUTLINED_FUNCTION_0
#
# CHECK-LABEL: _OUTLINED_FUNCTION_0:
@@ -38,6 +40,8 @@
declare void @cb1()
declare void @cb2()
+
+ declare i8* @attachedcall()
...
---
name: fn1
@@ -48,7 +52,7 @@ body: |
bb.0:
liveins: $lr
- BLR_RVMARKER @cb1, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $x0
+ BLR_RVMARKER @attachedcall, @cb1, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $x0
$w12 = ORRWri $wzr, 1
$w12 = ORRWri $wzr, 1
$w12 = ORRWri $wzr, 1
@@ -67,7 +71,7 @@ body: |
bb.0:
liveins: $lr, $x19, $x20, $lr
- BLR_RVMARKER @cb2, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $x0
+ BLR_RVMARKER @attachedcall, @cb2, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $x0
$w12 = ORRWri $wzr, 1
$w12 = ORRWri $wzr, 1
$w12 = ORRWri $wzr, 1
diff --git a/llvm/test/CodeGen/X86/call-rv-marker.ll b/llvm/test/CodeGen/X86/call-rv-marker.ll
index 0848bec01723e..ea63873d811e2 100644
--- a/llvm/test/CodeGen/X86/call-rv-marker.ll
+++ b/llvm/test/CodeGen/X86/call-rv-marker.ll
@@ -38,8 +38,8 @@ entry:
ret i8* %call
}
-define i8* @rv_marker_1_claim() {
-; CHECK-LABEL: rv_marker_1_claim:
+define i8* @rv_marker_1_unsafeClaim() {
+; CHECK-LABEL: rv_marker_1_unsafeClaim:
; CHECK: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: callq _foo1
diff --git a/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll b/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll
index fb3dbc0272f44..efcbdca40b30e 100644
--- a/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll
+++ b/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll
@@ -51,12 +51,12 @@ invoke.cont: ; preds = %entry
}
; CHECK-LABEL: define dso_local void @"?test_attr_claimRV@@YAXXZ"()
-; CHECK: %[[CALL4:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "clang.arc.attachedcall"() ]
-; CHECK: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL4]])
+; CHECK: %[[CALL4:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
+; CHECK-NEXT: ret void
; CHECK: %[[V1:.*]] = cleanuppad
-; CHECK: %[[CALL:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "funclet"(token %[[V1]]), "clang.arc.attachedcall"() ]
-; CHECK: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL]]) [ "funclet"(token %[[V1]]) ]
+; CHECK: %[[CALL:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "funclet"(token %[[V1]]), "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
+; CHECK-NEXT: cleanupret from %[[V1]] unwind to caller
define dso_local void @"?test_attr_claimRV@@YAXXZ"() local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
entry:
diff --git a/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll b/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll
index d601e988fdb32..f8dc18741157f 100644
--- a/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll
+++ b/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll
@@ -2,8 +2,8 @@
; RUN: opt -passes=objc-arc-contract -S < %s | FileCheck %s
; CHECK-LABEL: define void @test0() {
-; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"() ]
-; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL]])
+; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
+; CHECK-NOT: call i8* @llvm.objc.retainAutoreleasedReturnValue(
define void @test0() {
%call1 = call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
@@ -11,8 +11,8 @@ define void @test0() {
}
; CHECK-LABEL: define void @test1() {
-; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"() ]
-; CHECK: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL]])
+; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
+; CHECK-NOT: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(
define void @test1() {
%call1 = call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
@@ -20,15 +20,15 @@ define void @test1() {
}
; CHECK-LABEL:define i8* @test2(
-; CHECK: %[[CALL1:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"() ]
+; CHECK: %[[V0:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
-; CHECK: %[[V0:.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL1]])
-; CHECK-NEXT: br
+; CHECK-NOT: = call i8* @llvm.objc.retainAutoreleasedReturnValue(
+; CHECK: br
-; CHECK: %[[CALL3:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"() ]
+; CHECK: %[[V2:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
-; CHECK: %[[V2:.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL3]])
-; CHECK-NEXT: br
+; CHECK-NOT: = call i8* @llvm.objc.retainAutoreleasedReturnValue(
+; CHECK: br
; CHECK: %[[RETVAL:.*]] = phi i8* [ %[[V0]], {{.*}} ], [ %[[V2]], {{.*}} ]
; CHECK: ret i8* %[[RETVAL]]
diff --git a/llvm/test/Verifier/operand-bundles.ll b/llvm/test/Verifier/operand-bundles.ll
index 06b452de910c4..d6c48687b76f8 100644
--- a/llvm/test/Verifier/operand-bundles.ll
+++ b/llvm/test/Verifier/operand-bundles.ll
@@ -66,15 +66,17 @@ define void @f_gc_transition(i32* %ptr) {
}
define void @f_clang_arc_attachedcall() {
-; CHECK: Multiple "clang.arc.attachedcall" operand bundles
+; CHECK: requires one function as an argument
+; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"() ]
+; CHECK-NEXT: Multiple "clang.arc.attachedcall" operand bundles
; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue), "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
; CHECK-NEXT: must call a function returning a pointer
; CHECK-NEXT: call i8 @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
; CHECK-NEXT: or a non-returning function
; CHECK-NEXT: call void @g() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
-; CHECK-NEXT: can take either no arguments
+; CHECK-NEXT: requires one function as an argument
; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* null) ]
-; CHECK-NEXT: can take either no arguments
+; CHECK-NEXT: requires one function as an argument
; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
; CHECK-NEXT: invalid function argument
; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i8 ()* @foo1) ]
More information about the llvm-commits
mailing list