Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 2 additions & 32 deletions lib/IRGen/GenObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,47 +150,17 @@ llvm::InlineAsm *IRGenModule::getObjCRetainAutoreleasedReturnValueMarker() {
/// Reclaim an autoreleased return value.
llvm::Value *irgen::emitObjCRetainAutoreleasedReturnValue(IRGenFunction &IGF,
llvm::Value *value) {
auto &IGM = IGF.IGM;
// Call the inline-assembly marker if we need one.
if (auto marker = IGM.getObjCRetainAutoreleasedReturnValueMarker()) {
if (auto marker = IGF.IGM.getObjCRetainAutoreleasedReturnValueMarker()) {
IGF.Builder.CreateAsmCall(marker, {});
}

const auto &triple = IGF.IGM.Context.LangOpts.Target;
const auto &arch = triple.getArch();

// FIXME: Do this on all targets and at -O0 too. This can be enabled only if
// the target backend knows how to handle the operand bundle.
// Don't use clang.arc.attachedcall on non-darwin platforms for now. On these
// platforms we have a workaround in-place to deal with the un-availability of
// a arc runtime -- we have implemented objc_retainAutoreleasedReturnValue in
// a library (src/swift/DispatchStubs.cc) as swift_retain.
// Using clang.arc.attachedcall enables a LLVM optimization that can transform
// objc_retainAutoreleasedReturnValue into objc_retain in some circumstances.
// There is no objc_retain stub defined and we would run into missing symbol
// errors.
if (IGM.getOptions().shouldOptimize() && triple.isOSDarwin() &&
(arch == llvm::Triple::aarch64 ||
arch == llvm::Triple::x86_64)) {
auto EP = llvm::Intrinsic::getDeclaration(&IGM.Module,
(llvm::Intrinsic::ID)llvm::Intrinsic::objc_retainAutoreleasedReturnValue);
llvm::Value *bundleArgs[] = {EP};
llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs);
auto *oldCall = cast<llvm::CallBase>(value);
llvm::CallBase *newCall = llvm::CallBase::addOperandBundle(
oldCall, llvm::LLVMContext::OB_clang_arc_attachedcall, OB, oldCall);
newCall->copyMetadata(*oldCall);
oldCall->replaceAllUsesWith(newCall);
oldCall->eraseFromParent();
auto noop = IGF.Builder.CreateIntrinsicCall(llvm::Intrinsic::objc_clang_arc_noop_use, newCall);
noop->addFnAttr(llvm::Attribute::NoUnwind);
return newCall;
}
CastToInt8PtrTy savedType(IGF, value);

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

const llvm::Triple &triple = IGF.IGM.Context.LangOpts.Target;
if (triple.getArch() == llvm::Triple::x86_64) {
// Don't tail call objc_retainAutoreleasedReturnValue. This blocks the
// autoreleased return optimization.
Expand Down
6 changes: 3 additions & 3 deletions test/IRGen/objc_retainAutoreleasedReturnValue.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %target-swift-frontend -module-name objc_retainAutoreleasedReturnValue -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s
// 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
// RUN: %target-swift-frontend -module-name objc_retainAutoreleasedReturnValue -O -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s --check-prefix=OPT

// REQUIRES: objc_interop
// REQUIRES: CPU=x86_64
Expand Down Expand Up @@ -32,6 +32,6 @@ public func test(_ dict: NSDictionary) {

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