Skip to content

Commit 2568e45

Browse files
committed
Use clang.arc.attachedcall for emission of objc_retainAutoreleasedReturnValue
rdar://110019256
1 parent 85396f2 commit 2568e45

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

lib/IRGen/GenObjC.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,17 +150,38 @@ llvm::InlineAsm *IRGenModule::getObjCRetainAutoreleasedReturnValueMarker() {
150150
/// Reclaim an autoreleased return value.
151151
llvm::Value *irgen::emitObjCRetainAutoreleasedReturnValue(IRGenFunction &IGF,
152152
llvm::Value *value) {
153+
auto &IGM = IGF.IGM;
153154
// Call the inline-assembly marker if we need one.
154-
if (auto marker = IGF.IGM.getObjCRetainAutoreleasedReturnValueMarker()) {
155+
if (auto marker = IGM.getObjCRetainAutoreleasedReturnValueMarker()) {
155156
IGF.Builder.CreateAsmCall(marker, {});
156157
}
157158

159+
const auto &triple = IGF.IGM.Context.LangOpts.Target;
160+
const auto &arch = triple.getArch();
161+
162+
// FIXME: Do this on all targets and at -O0 too. This can be enabled only if
163+
// the target backend knows how to handle the operand bundle.
164+
if (IGM.getOptions().shouldOptimize() && (arch == llvm::Triple::aarch64 ||
165+
arch == llvm::Triple::x86_64)) {
166+
auto EP = llvm::Intrinsic::getDeclaration(&IGM.Module,
167+
(llvm::Intrinsic::ID)llvm::Intrinsic::objc_retainAutoreleasedReturnValue);
168+
llvm::Value *bundleArgs[] = {EP};
169+
llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs);
170+
auto *oldCall = cast<llvm::CallBase>(value);
171+
llvm::CallBase *newCall = llvm::CallBase::addOperandBundle(
172+
oldCall, llvm::LLVMContext::OB_clang_arc_attachedcall, OB, oldCall);
173+
newCall->copyMetadata(*oldCall);
174+
oldCall->replaceAllUsesWith(newCall);
175+
oldCall->eraseFromParent();
176+
auto noop = IGF.Builder.CreateIntrinsicCall(llvm::Intrinsic::objc_clang_arc_noop_use, newCall);
177+
noop->addFnAttr(llvm::Attribute::NoUnwind);
178+
return newCall;
179+
}
158180
CastToInt8PtrTy savedType(IGF, value);
159181

160182
auto call = IGF.Builder.CreateIntrinsicCall(
161183
llvm::Intrinsic::objc_retainAutoreleasedReturnValue, value);
162184

163-
const llvm::Triple &triple = IGF.IGM.Context.LangOpts.Target;
164185
if (triple.getArch() == llvm::Triple::x86_64) {
165186
// Don't tail call objc_retainAutoreleasedReturnValue. This blocks the
166187
// autoreleased return optimization.

test/IRGen/objc_retainAutoreleasedReturnValue.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %target-swift-frontend -module-name objc_retainAutoreleasedReturnValue -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s
2-
// RUN: %target-swift-frontend -module-name objc_retainAutoreleasedReturnValue -O -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s --check-prefix=OPT
2+
// RUN: %target-swift-frontend -module-name objc_retainAutoreleasedReturnValue -O -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir -disable-llvm-optzns | %FileCheck %s --check-prefix=OPT
33

44
// REQUIRES: objc_interop
55
// REQUIRES: CPU=x86_64
@@ -32,6 +32,6 @@ public func test(_ dict: NSDictionary) {
3232

3333
// OPT-LABEL: define {{.*}}swiftcc void @"$s34objc_retainAutoreleasedReturnValue10useClosureyySo12NSDictionaryC_yADXEtF09$s34objc_bcd16Value4testyySo12H10CFyADXEfU_Tf1nc_n"(ptr %0)
3434
// OPT: entry:
35-
// OPT: call {{.*}}@objc_msgSend
36-
// OPT: notail call ptr @llvm.objc.retainAutoreleasedReturnValue
35+
// OPT: [[R:%.*]] = call ptr @objc_msgSend({{.*}}) [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue)
36+
// OPT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[R]])
3737
// OPT: ret void

0 commit comments

Comments
 (0)