[llvm] r258970 - Add support for objc_unsafeClaimAutoreleasedReturnValue to the
John McCall via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 27 11:05:09 PST 2016
Author: rjmccall
Date: Wed Jan 27 13:05:08 2016
New Revision: 258970
URL: http://llvm.org/viewvc/llvm-project?rev=258970&view=rev
Log:
Add support for objc_unsafeClaimAutoreleasedReturnValue to the
ObjC ARC Optimizer.
The main implication of this is:
1. Ensuring that we treat it conservatively in terms of optimization.
2. We put the ASM marker on it so that the runtime can recognize
objc_unsafeClaimAutoreleasedReturnValue from releaseRV.
<rdar://problem/21567064>
Patch by Michael Gottesman!
Modified:
llvm/trunk/include/llvm/Analysis/ObjCARCAnalysisUtils.h
llvm/trunk/include/llvm/Analysis/ObjCARCInstKind.h
llvm/trunk/lib/Analysis/ObjCARCInstKind.cpp
llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp
llvm/trunk/test/Transforms/ObjCARC/basic.ll
llvm/trunk/test/Transforms/ObjCARC/contract-marker.ll
llvm/trunk/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll
Modified: llvm/trunk/include/llvm/Analysis/ObjCARCAnalysisUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ObjCARCAnalysisUtils.h?rev=258970&r1=258969&r2=258970&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ObjCARCAnalysisUtils.h (original)
+++ llvm/trunk/include/llvm/Analysis/ObjCARCAnalysisUtils.h Wed Jan 27 13:05:08 2016
@@ -54,6 +54,7 @@ inline bool ModuleHasARC(const Module &M
M.getNamedValue("objc_release") ||
M.getNamedValue("objc_autorelease") ||
M.getNamedValue("objc_retainAutoreleasedReturnValue") ||
+ M.getNamedValue("objc_unsafeClaimAutoreleasedReturnValue") ||
M.getNamedValue("objc_retainBlock") ||
M.getNamedValue("objc_autoreleaseReturnValue") ||
M.getNamedValue("objc_autoreleasePoolPush") ||
Modified: llvm/trunk/include/llvm/Analysis/ObjCARCInstKind.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ObjCARCInstKind.h?rev=258970&r1=258969&r2=258970&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ObjCARCInstKind.h (original)
+++ llvm/trunk/include/llvm/Analysis/ObjCARCInstKind.h Wed Jan 27 13:05:08 2016
@@ -30,6 +30,7 @@ namespace objcarc {
enum class ARCInstKind {
Retain, ///< objc_retain
RetainRV, ///< objc_retainAutoreleasedReturnValue
+ ClaimRV, ///< objc_unsafeClaimAutoreleasedReturnValue
RetainBlock, ///< objc_retainBlock
Release, ///< objc_release
Autorelease, ///< objc_autorelease
Modified: llvm/trunk/lib/Analysis/ObjCARCInstKind.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ObjCARCInstKind.cpp?rev=258970&r1=258969&r2=258970&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ObjCARCInstKind.cpp (original)
+++ llvm/trunk/lib/Analysis/ObjCARCInstKind.cpp Wed Jan 27 13:05:08 2016
@@ -34,6 +34,8 @@ raw_ostream &llvm::objcarc::operator<<(r
return OS << "ARCInstKind::Retain";
case ARCInstKind::RetainRV:
return OS << "ARCInstKind::RetainRV";
+ case ARCInstKind::ClaimRV:
+ return OS << "ARCInstKind::ClaimRV";
case ARCInstKind::RetainBlock:
return OS << "ARCInstKind::RetainBlock";
case ARCInstKind::Release:
@@ -103,6 +105,8 @@ ARCInstKind llvm::objcarc::GetFunctionCl
return StringSwitch<ARCInstKind>(F->getName())
.Case("objc_retain", ARCInstKind::Retain)
.Case("objc_retainAutoreleasedReturnValue", ARCInstKind::RetainRV)
+ .Case("objc_unsafeClaimAutoreleasedReturnValue",
+ ARCInstKind::ClaimRV)
.Case("objc_retainBlock", ARCInstKind::RetainBlock)
.Case("objc_release", ARCInstKind::Release)
.Case("objc_autorelease", ARCInstKind::Autorelease)
@@ -350,6 +354,7 @@ bool llvm::objcarc::IsUser(ARCInstKind C
case ARCInstKind::StoreStrong:
case ARCInstKind::Call:
case ARCInstKind::None:
+ case ARCInstKind::ClaimRV:
return false;
}
llvm_unreachable("covered switch isn't covered?");
@@ -385,6 +390,7 @@ bool llvm::objcarc::IsRetain(ARCInstKind
case ARCInstKind::Call:
case ARCInstKind::User:
case ARCInstKind::None:
+ case ARCInstKind::ClaimRV:
return false;
}
llvm_unreachable("covered switch isn't covered?");
@@ -398,6 +404,7 @@ bool llvm::objcarc::IsAutorelease(ARCIns
return true;
case ARCInstKind::Retain:
case ARCInstKind::RetainRV:
+ case ARCInstKind::ClaimRV:
case ARCInstKind::RetainBlock:
case ARCInstKind::Release:
case ARCInstKind::AutoreleasepoolPush:
@@ -429,6 +436,7 @@ bool llvm::objcarc::IsForwarding(ARCInst
switch (Class) {
case ARCInstKind::Retain:
case ARCInstKind::RetainRV:
+ case ARCInstKind::ClaimRV:
case ARCInstKind::Autorelease:
case ARCInstKind::AutoreleaseRV:
case ARCInstKind::NoopCast:
@@ -463,6 +471,7 @@ bool llvm::objcarc::IsNoopOnNull(ARCInst
switch (Class) {
case ARCInstKind::Retain:
case ARCInstKind::RetainRV:
+ case ARCInstKind::ClaimRV:
case ARCInstKind::Release:
case ARCInstKind::Autorelease:
case ARCInstKind::AutoreleaseRV:
@@ -498,6 +507,7 @@ bool llvm::objcarc::IsAlwaysTail(ARCInst
switch (Class) {
case ARCInstKind::Retain:
case ARCInstKind::RetainRV:
+ case ARCInstKind::ClaimRV:
case ARCInstKind::AutoreleaseRV:
return true;
case ARCInstKind::Release:
@@ -538,6 +548,7 @@ bool llvm::objcarc::IsNeverTail(ARCInstK
return true;
case ARCInstKind::Retain:
case ARCInstKind::RetainRV:
+ case ARCInstKind::ClaimRV:
case ARCInstKind::AutoreleaseRV:
case ARCInstKind::Release:
case ARCInstKind::RetainBlock:
@@ -572,6 +583,7 @@ bool llvm::objcarc::IsNoThrow(ARCInstKin
switch (Class) {
case ARCInstKind::Retain:
case ARCInstKind::RetainRV:
+ case ARCInstKind::ClaimRV:
case ARCInstKind::Release:
case ARCInstKind::Autorelease:
case ARCInstKind::AutoreleaseRV:
@@ -616,6 +628,7 @@ bool llvm::objcarc::CanInterruptRV(ARCIn
return true;
case ARCInstKind::Retain:
case ARCInstKind::RetainRV:
+ case ARCInstKind::ClaimRV:
case ARCInstKind::Release:
case ARCInstKind::AutoreleasepoolPush:
case ARCInstKind::RetainBlock:
@@ -668,6 +681,7 @@ bool llvm::objcarc::CanDecrementRefCount
case ARCInstKind::StoreStrong:
case ARCInstKind::CallOrUser:
case ARCInstKind::Call:
+ case ARCInstKind::ClaimRV:
return true;
}
Modified: llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp?rev=258970&r1=258969&r2=258970&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp (original)
+++ llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp Wed Jan 27 13:05:08 2016
@@ -66,7 +66,7 @@ namespace {
/// The inline asm string to insert between calls and RetainRV calls to make
/// the optimization work on targets which need it.
- const MDString *RetainRVMarker;
+ const MDString *RVInstMarker;
/// The set of inserted objc_storeStrong calls. If at the end of walking the
/// function we have found no alloca instructions, these calls can be marked
@@ -423,16 +423,16 @@ bool ObjCARCContract::tryToPeepholeInstr
return false;
// If we succeed in our optimization, fall through.
// FALLTHROUGH
- case ARCInstKind::RetainRV: {
+ case ARCInstKind::RetainRV:
+ case ARCInstKind::ClaimRV: {
// If we're compiling for a target which needs a special inline-asm
- // marker to do the retainAutoreleasedReturnValue optimization,
- // insert it now.
- if (!RetainRVMarker)
+ // marker to do the return value optimization, insert it now.
+ if (!RVInstMarker)
return false;
BasicBlock::iterator BBI = Inst->getIterator();
BasicBlock *InstParent = Inst->getParent();
- // Step up to see if the call immediately precedes the RetainRV call.
+ // Step up to see if the call immediately precedes the RV call.
// If it's an invoke, we have to cross a block boundary. And we have
// to carefully dodge no-op instructions.
do {
@@ -447,14 +447,14 @@ bool ObjCARCContract::tryToPeepholeInstr
} while (IsNoopInstruction(&*BBI));
if (&*BBI == GetArgRCIdentityRoot(Inst)) {
- DEBUG(dbgs() << "Adding inline asm marker for "
- "retainAutoreleasedReturnValue optimization.\n");
+ DEBUG(dbgs() << "Adding inline asm marker for the return value "
+ "optimization.\n");
Changed = true;
- InlineAsm *IA =
- InlineAsm::get(FunctionType::get(Type::getVoidTy(Inst->getContext()),
- /*isVarArg=*/false),
- RetainRVMarker->getString(),
- /*Constraints=*/"", /*hasSideEffects=*/true);
+ InlineAsm *IA = InlineAsm::get(
+ FunctionType::get(Type::getVoidTy(Inst->getContext()),
+ /*isVarArg=*/false),
+ RVInstMarker->getString(),
+ /*Constraints=*/"", /*hasSideEffects=*/true);
CallInst::Create(IA, "", Inst);
}
decline_rv_optimization:
@@ -650,15 +650,15 @@ bool ObjCARCContract::doInitialization(M
EP.init(&M);
- // Initialize RetainRVMarker.
- RetainRVMarker = nullptr;
+ // Initialize RVInstMarker.
+ RVInstMarker = nullptr;
if (NamedMDNode *NMD =
M.getNamedMetadata("clang.arc.retainAutoreleasedReturnValueMarker"))
if (NMD->getNumOperands() == 1) {
const MDNode *N = NMD->getOperand(0);
if (N->getNumOperands() == 1)
if (const MDString *S = dyn_cast<MDString>(N->getOperand(0)))
- RetainRVMarker = S;
+ RVInstMarker = S;
}
return false;
Modified: llvm/trunk/test/Transforms/ObjCARC/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/basic.ll?rev=258970&r1=258969&r2=258970&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/basic.ll (original)
+++ llvm/trunk/test/Transforms/ObjCARC/basic.ll Wed Jan 27 13:05:08 2016
@@ -4,6 +4,7 @@ target datalayout = "e-p:64:64:64"
declare i8* @objc_retain(i8*)
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
+declare i8* @objc_unsafeClaimAutoreleasedReturnValue(i8*)
declare void @objc_release(i8*)
declare i8* @objc_autorelease(i8*)
declare i8* @objc_autoreleaseReturnValue(i8*)
@@ -2568,6 +2569,27 @@ if.then:
br label %return
return: ; preds = %if.then, %entry
+ %retval = phi i8* [ %s, %if.then ], [ null, %entry ]
+ %q = call i8* @objc_autoreleaseReturnValue(i8* %retval) nounwind
+ ret i8* %retval
+}
+
+; CHECK-LABEL: define i8* @test65d(
+; CHECK: if.then:
+; CHECK-NOT: @objc_autorelease
+; CHECK: return:
+; CHECK: call i8* @objc_autoreleaseReturnValue(
+; CHECK: }
+define i8* @test65d(i1 %x) {
+entry:
+ br i1 %x, label %return, label %if.then
+
+if.then: ; preds = %entry
+ %c = call i8* @returner()
+ %s = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %c) nounwind
+ br label %return
+
+return: ; preds = %if.then, %entry
%retval = phi i8* [ %s, %if.then ], [ null, %entry ]
%q = call i8* @objc_autoreleaseReturnValue(i8* %retval) nounwind
ret i8* %retval
Modified: llvm/trunk/test/Transforms/ObjCARC/contract-marker.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-marker.ll?rev=258970&r1=258969&r2=258970&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-marker.ll (original)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-marker.ll Wed Jan 27 13:05:08 2016
@@ -1,9 +1,9 @@
; RUN: opt -S -objc-arc-contract < %s | FileCheck %s
-; CHECK: define void @foo() {
+; CHECK-LABEL: define void @foo() {
; CHECK: %call = tail call i32* @qux()
; CHECK-NEXT: %tcall = bitcast i32* %call to i8*
-; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue", ""()
+; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for return value optimization", ""()
; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %tcall) [[NUW:#[0-9]+]]
; CHECK: }
@@ -16,12 +16,30 @@ entry:
ret void
}
+; CHECK-LABEL: define void @foo2() {
+; CHECK: %call = tail call i32* @qux()
+; CHECK-NEXT: %tcall = bitcast i32* %call to i8*
+; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for return value optimization", ""()
+; CHECK-NEXT: %0 = tail call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %tcall) [[NUW:#[0-9]+]]
+; CHECK: }
+
+define void @foo2() {
+entry:
+ %call = tail call i32* @qux()
+ %tcall = bitcast i32* %call to i8*
+ %0 = tail call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %tcall) nounwind
+ tail call void @bar(i8* %0)
+ ret void
+}
+
+
declare i32* @qux()
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
+declare i8* @objc_unsafeClaimAutoreleasedReturnValue(i8*)
declare void @bar(i8*)
!clang.arc.retainAutoreleasedReturnValueMarker = !{!0}
-!0 = !{!"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"}
+!0 = !{!"mov\09r7, r7\09\09@ marker for return value optimization"}
; CHECK: attributes [[NUW]] = { nounwind }
Modified: llvm/trunk/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll?rev=258970&r1=258969&r2=258970&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll (original)
+++ llvm/trunk/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll Wed Jan 27 13:05:08 2016
@@ -5,6 +5,7 @@ declare i8* @objc_retain(i8* %x)
declare i8* @objc_autorelease(i8* %x)
declare i8* @objc_autoreleaseReturnValue(i8* %x)
declare i8* @objc_retainAutoreleasedReturnValue(i8* %x)
+declare i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %x)
declare i8* @tmp(i8*)
; Never tail call objc_autorelease.
@@ -85,5 +86,19 @@ entry:
ret i8* %tmp0
}
+; Always tail call objc_unsafeClaimAutoreleasedReturnValue.
+; CHECK: define i8* @test6(i8* %x) [[NUW]] {
+; CHECK: %tmp0 = tail call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %y) [[NUW]]
+; CHECK: %tmp1 = tail call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %z) [[NUW]]
+; CHECK: }
+define i8* @test6(i8* %x) nounwind {
+entry:
+ %y = call i8* @tmp(i8* %x)
+ %tmp0 = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %y)
+ %z = call i8* @tmp(i8* %x)
+ %tmp1 = tail call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %z)
+ ret i8* %x
+}
+
; CHECK: attributes [[NUW]] = { nounwind }
More information about the llvm-commits
mailing list