Skip to content

Commit aa52e82

Browse files
author
git apple-llvm automerger
committed
Merge commit '810148cb0769' from llvm.org/main into next
2 parents 0d6598d + 810148c commit aa52e82

File tree

6 files changed

+124
-3
lines changed

6 files changed

+124
-3
lines changed

llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum class ARCRuntimeEntryPointKind {
4242
Autorelease,
4343
StoreStrong,
4444
RetainRV,
45+
ClaimRV,
4546
UnsafeClaimRV,
4647
RetainAutorelease,
4748
RetainAutoreleaseRV,
@@ -62,6 +63,7 @@ class ARCRuntimeEntryPoints {
6263
Autorelease = nullptr;
6364
StoreStrong = nullptr;
6465
RetainRV = nullptr;
66+
ClaimRV = nullptr;
6567
UnsafeClaimRV = nullptr;
6668
RetainAutorelease = nullptr;
6769
RetainAutoreleaseRV = nullptr;
@@ -87,6 +89,9 @@ class ARCRuntimeEntryPoints {
8789
case ARCRuntimeEntryPointKind::RetainRV:
8890
return getIntrinsicEntryPoint(RetainRV,
8991
Intrinsic::objc_retainAutoreleasedReturnValue);
92+
case ARCRuntimeEntryPointKind::ClaimRV:
93+
return getIntrinsicEntryPoint(
94+
ClaimRV, Intrinsic::objc_claimAutoreleasedReturnValue);
9095
case ARCRuntimeEntryPointKind::UnsafeClaimRV:
9196
return getIntrinsicEntryPoint(
9297
UnsafeClaimRV, Intrinsic::objc_unsafeClaimAutoreleasedReturnValue);
@@ -126,6 +131,9 @@ class ARCRuntimeEntryPoints {
126131
/// Declaration for objc_retainAutoreleasedReturnValue().
127132
Function *RetainRV = nullptr;
128133

134+
/// Declaration for objc_claimAutoreleasedReturnValue().
135+
Function *ClaimRV = nullptr;
136+
129137
/// Declaration for objc_unsafeClaimAutoreleasedReturnValue().
130138
Function *UnsafeClaimRV = nullptr;
131139

llvm/lib/Transforms/ObjCARC/ObjCARC.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,37 @@ BundledRetainClaimRVs::~BundledRetainClaimRVs() {
101101
// can't be tail calls.
102102
if (auto *CI = dyn_cast<CallInst>(CB))
103103
CI->setTailCallKind(CallInst::TCK_NoTail);
104+
105+
// We can also do one final optimization: modify the bundle in the
106+
// annotated call, to change the bundle operand from
107+
// objc_retainAutoreleasedReturnValue
108+
// to:
109+
// objc_claimAutoreleasedReturnValue
110+
// allowing the marker to be omitted from the bundle expansion later.
111+
//
112+
// Note that, confusingly, ClaimRV is semantically equivalent to RetainRV,
113+
// and only differs in that it doesn't require the marker.
114+
// The bundle provides the guarantee that we're emitting the ClaimRV call
115+
// adjacent to the original call, and providing that guarantee is the
116+
// only difference between ClaimRV and RetainRV.
117+
//
118+
// UnsafeClaimRV has a different RC contract entirely.
119+
120+
// Find the clang.arc.attachedcall bundle, and rewrite its operand.
121+
if (UseClaimRV) {
122+
for (auto OBI : CB->bundle_op_infos()) {
123+
auto OBU = CB->operandBundleFromBundleOpInfo(OBI);
124+
if (OBU.getTagID() == LLVMContext::OB_clang_arc_attachedcall &&
125+
OBU.Inputs[0] == EP.get(ARCRuntimeEntryPointKind::RetainRV)) {
126+
CB->setOperand(OBI.Begin,
127+
EP.get(ARCRuntimeEntryPointKind::ClaimRV));
128+
break;
129+
}
130+
}
131+
}
104132
}
105133

134+
// Erase the RV call we emitted earlier: it's already in the bundle.
106135
EraseInstruction(P.first);
107136
}
108137

llvm/lib/Transforms/ObjCARC/ObjCARC.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#ifndef LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H
2323
#define LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H
2424

25+
#include "ARCRuntimeEntryPoints.h"
2526
#include "llvm/Analysis/ObjCARCAnalysisUtils.h"
2627
#include "llvm/Analysis/ObjCARCUtil.h"
2728
#include "llvm/IR/EHPersonalities.h"
@@ -104,7 +105,9 @@ CallInst *createCallInstWithColors(
104105

105106
class BundledRetainClaimRVs {
106107
public:
107-
BundledRetainClaimRVs(bool ContractPass) : ContractPass(ContractPass) {}
108+
BundledRetainClaimRVs(ARCRuntimeEntryPoints &EP, bool ContractPass,
109+
bool UseClaimRV)
110+
: EP(EP), ContractPass(ContractPass), UseClaimRV(UseClaimRV) {}
108111
~BundledRetainClaimRVs();
109112

110113
/// Insert a retainRV/claimRV call to the normal destination blocks of invokes
@@ -155,7 +158,9 @@ class BundledRetainClaimRVs {
155158
/// A map of inserted retainRV/claimRV calls to annotated calls/invokes.
156159
DenseMap<CallInst *, CallBase *> RVCalls;
157160

161+
ARCRuntimeEntryPoints &EP;
158162
bool ContractPass;
163+
bool UseClaimRV;
159164
};
160165

161166
} // end namespace objcarc

llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "llvm/InitializePasses.h"
4343
#include "llvm/Support/Debug.h"
4444
#include "llvm/Support/raw_ostream.h"
45+
#include "llvm/TargetParser/Triple.h"
4546
#include "llvm/Transforms/ObjCARC.h"
4647

4748
using namespace llvm;
@@ -52,6 +53,11 @@ using namespace llvm::objcarc;
5253
STATISTIC(NumPeeps, "Number of calls peephole-optimized");
5354
STATISTIC(NumStoreStrongs, "Number objc_storeStrong calls formed");
5455

56+
static cl::opt<cl::boolOrDefault> UseObjCClaimRV(
57+
"arc-contract-use-objc-claim-rv",
58+
cl::desc(
59+
"Enable generation of calls to objc_claimAutoreleasedReturnValue"));
60+
5561
//===----------------------------------------------------------------------===//
5662
// Declarations
5763
//===----------------------------------------------------------------------===//
@@ -74,6 +80,9 @@ class ObjCARCContract {
7480
/// A flag indicating whether this optimization pass should run.
7581
bool Run;
7682

83+
/// Whether objc_claimAutoreleasedReturnValue is available.
84+
bool HasClaimRV = false;
85+
7786
/// The inline asm string to insert between calls and RetainRV calls to make
7887
/// the optimization work on targets which need it.
7988
const MDString *RVInstMarker;
@@ -517,6 +526,39 @@ bool ObjCARCContract::tryToPeepholeInstruction(
517526
}
518527
}
519528

529+
/// Should we use objc_claimAutoreleasedReturnValue?
530+
static bool useClaimRuntimeCall(Module &M) {
531+
// Let the flag override our OS-based default.
532+
if (UseObjCClaimRV != cl::BOU_UNSET)
533+
return UseObjCClaimRV == cl::BOU_TRUE;
534+
535+
Triple TT(M.getTargetTriple());
536+
537+
// On x86_64, claimARV doesn't make sense, as the marker isn't actually a nop
538+
// there (it's needed by the calling convention).
539+
if (!TT.isAArch64())
540+
return false;
541+
542+
unsigned Major = TT.getOSMajorVersion();
543+
switch (TT.getOS()) {
544+
default:
545+
return false;
546+
case Triple::IOS:
547+
case Triple::TvOS:
548+
return Major >= 16;
549+
case Triple::WatchOS:
550+
return Major >= 9;
551+
case Triple::BridgeOS:
552+
return Major >= 7;
553+
case Triple::MacOSX:
554+
return Major >= 13;
555+
case Triple::Darwin:
556+
return Major >= 21;
557+
}
558+
559+
return false;
560+
}
561+
520562
//===----------------------------------------------------------------------===//
521563
// Top Level Driver
522564
//===----------------------------------------------------------------------===//
@@ -528,6 +570,8 @@ bool ObjCARCContract::init(Module &M) {
528570

529571
EP.init(&M);
530572

573+
HasClaimRV = useClaimRuntimeCall(M);
574+
531575
// Initialize RVInstMarker.
532576
RVInstMarker = getRVInstMarker(M);
533577

@@ -545,7 +589,7 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) {
545589
AA = A;
546590
DT = D;
547591
PA.setAA(A);
548-
BundledRetainClaimRVs BRV(/*ContractPass=*/true);
592+
BundledRetainClaimRVs BRV(EP, /*ContractPass=*/true, HasClaimRV);
549593
BundledInsts = &BRV;
550594

551595
std::pair<bool, bool> R = BundledInsts->insertAfterInvokes(F, DT);

llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2423,7 +2423,7 @@ bool ObjCARCOpt::run(Function &F, AAResults &AA) {
24232423
return false;
24242424

24252425
Changed = CFGChanged = false;
2426-
BundledRetainClaimRVs BRV(/*ContractPass=*/false);
2426+
BundledRetainClaimRVs BRV(EP, /*ContractPass=*/false, /*UseClaimRV=*/false);
24272427
BundledInsts = &BRV;
24282428

24292429
LLVM_DEBUG(dbgs() << "<<< ObjCARCOpt: Visiting Function: " << F.getName()
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
; RUN: opt -passes=objc-arc-contract -arc-contract-use-objc-claim-rv=1 -S < %s | FileCheck %s --check-prefixes=CHECK,CLAIM
2+
; RUN: opt -passes=objc-arc-contract -arc-contract-use-objc-claim-rv=0 -S < %s | FileCheck %s --check-prefixes=CHECK,RETAIN
3+
4+
; CHECK-LABEL: define void @test0() {
5+
; CLAIM: %[[CALL:.*]] = notail call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.claimAutoreleasedReturnValue) ]
6+
; RETAIN: %[[CALL:.*]] = notail call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
7+
; CHECK-NEXT: ret void
8+
9+
define void @test0() {
10+
%call1 = call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
11+
ret void
12+
}
13+
14+
; CHECK-LABEL: define void @test1() {
15+
; CHECK: %[[CALL:.*]] = notail call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
16+
; CHECK-NEXT: ret void
17+
18+
define void @test1() {
19+
%call1 = call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
20+
ret void
21+
}
22+
23+
; CHECK-LABEL: define void @test2() {
24+
; CLAIM: %[[CALL:.*]] = notail call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.claimAutoreleasedReturnValue), "otherbundle"() ]
25+
; RETAIN: %[[CALL:.*]] = notail call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue), "otherbundle"() ]
26+
; CHECK-NEXT: ret void
27+
28+
define void @test2() {
29+
%call1 = call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue), "otherbundle"() ]
30+
ret void
31+
}
32+
33+
declare ptr @foo()
34+
declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
35+
declare ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr)

0 commit comments

Comments
 (0)