[objc-arc] Updated ObjCARCOpts to use ARCRuntimeEntryPoints.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185741 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael Gottesman 2013-07-06 01:39:23 +00:00
parent 7ec67156b0
commit 50951c7f79

View File

@ -26,6 +26,7 @@
#define DEBUG_TYPE "objc-arc-opts" #define DEBUG_TYPE "objc-arc-opts"
#include "ObjCARC.h" #include "ObjCARC.h"
#include "ARCRuntimeEntryPoints.h"
#include "DependencyAnalysis.h" #include "DependencyAnalysis.h"
#include "ObjCARCAliasAnalysis.h" #include "ObjCARCAliasAnalysis.h"
#include "ProvenanceAnalysis.h" #include "ProvenanceAnalysis.h"
@ -1127,6 +1128,7 @@ namespace {
class ObjCARCOpt : public FunctionPass { class ObjCARCOpt : public FunctionPass {
bool Changed; bool Changed;
ProvenanceAnalysis PA; ProvenanceAnalysis PA;
ARCRuntimeEntryPoints EP;
// This is used to track if a pointer is stored into an alloca. // This is used to track if a pointer is stored into an alloca.
DenseSet<const Value *> MultiOwnersSet; DenseSet<const Value *> MultiOwnersSet;
@ -1134,21 +1136,6 @@ namespace {
/// A flag indicating whether this optimization pass should run. /// A flag indicating whether this optimization pass should run.
bool Run; bool Run;
/// Declarations for ObjC runtime functions, for use in creating calls to
/// them. These are initialized lazily to avoid cluttering up the Module
/// with unused declarations.
/// Declaration for ObjC runtime function objc_autoreleaseReturnValue.
Constant *AutoreleaseRVCallee;
/// Declaration for ObjC runtime function objc_release.
Constant *ReleaseCallee;
/// Declaration for ObjC runtime function objc_retain.
Constant *RetainCallee;
/// Declaration for ObjC runtime function objc_retainBlock.
Constant *RetainBlockCallee;
/// Declaration for ObjC runtime function objc_autorelease.
Constant *AutoreleaseCallee;
/// Flags which determine whether each of the interesting runtine functions /// Flags which determine whether each of the interesting runtine functions
/// is in fact used in the current function. /// is in fact used in the current function.
unsigned UsedInThisFunction; unsigned UsedInThisFunction;
@ -1171,12 +1158,6 @@ namespace {
unsigned ARCAnnotationProvenanceSourceMDKind; unsigned ARCAnnotationProvenanceSourceMDKind;
#endif // ARC_ANNOATIONS #endif // ARC_ANNOATIONS
Constant *getAutoreleaseRVCallee(Module *M);
Constant *getReleaseCallee(Module *M);
Constant *getRetainCallee(Module *M);
Constant *getRetainBlockCallee(Module *M);
Constant *getAutoreleaseCallee(Module *M);
bool IsRetainBlockOptimizable(const Instruction *Inst); bool IsRetainBlockOptimizable(const Instruction *Inst);
bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV); bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV);
@ -1288,85 +1269,6 @@ bool ObjCARCOpt::IsRetainBlockOptimizable(const Instruction *Inst) {
return true; return true;
} }
Constant *ObjCARCOpt::getAutoreleaseRVCallee(Module *M) {
if (!AutoreleaseRVCallee) {
LLVMContext &C = M->getContext();
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
Type *Params[] = { I8X };
FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false);
AttributeSet Attribute =
AttributeSet().addAttribute(M->getContext(), AttributeSet::FunctionIndex,
Attribute::NoUnwind);
AutoreleaseRVCallee =
M->getOrInsertFunction("objc_autoreleaseReturnValue", FTy,
Attribute);
}
return AutoreleaseRVCallee;
}
Constant *ObjCARCOpt::getReleaseCallee(Module *M) {
if (!ReleaseCallee) {
LLVMContext &C = M->getContext();
Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
AttributeSet Attribute =
AttributeSet().addAttribute(M->getContext(), AttributeSet::FunctionIndex,
Attribute::NoUnwind);
ReleaseCallee =
M->getOrInsertFunction(
"objc_release",
FunctionType::get(Type::getVoidTy(C), Params, /*isVarArg=*/false),
Attribute);
}
return ReleaseCallee;
}
Constant *ObjCARCOpt::getRetainCallee(Module *M) {
if (!RetainCallee) {
LLVMContext &C = M->getContext();
Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
AttributeSet Attribute =
AttributeSet().addAttribute(M->getContext(), AttributeSet::FunctionIndex,
Attribute::NoUnwind);
RetainCallee =
M->getOrInsertFunction(
"objc_retain",
FunctionType::get(Params[0], Params, /*isVarArg=*/false),
Attribute);
}
return RetainCallee;
}
Constant *ObjCARCOpt::getRetainBlockCallee(Module *M) {
if (!RetainBlockCallee) {
LLVMContext &C = M->getContext();
Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
// objc_retainBlock is not nounwind because it calls user copy constructors
// which could theoretically throw.
RetainBlockCallee =
M->getOrInsertFunction(
"objc_retainBlock",
FunctionType::get(Params[0], Params, /*isVarArg=*/false),
AttributeSet());
}
return RetainBlockCallee;
}
Constant *ObjCARCOpt::getAutoreleaseCallee(Module *M) {
if (!AutoreleaseCallee) {
LLVMContext &C = M->getContext();
Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
AttributeSet Attribute =
AttributeSet().addAttribute(M->getContext(), AttributeSet::FunctionIndex,
Attribute::NoUnwind);
AutoreleaseCallee =
M->getOrInsertFunction(
"objc_autorelease",
FunctionType::get(Params[0], Params, /*isVarArg=*/false),
Attribute);
}
return AutoreleaseCallee;
}
/// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is /// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is
/// not a return value. Or, if it can be paired with an /// not a return value. Or, if it can be paired with an
/// objc_autoreleaseReturnValue, delete the pair and return true. /// objc_autoreleaseReturnValue, delete the pair and return true.
@ -1420,7 +1322,8 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
"objc_retain since the operand is not a return value.\n" "objc_retain since the operand is not a return value.\n"
"Old = " << *RetainRV << "\n"); "Old = " << *RetainRV << "\n");
cast<CallInst>(RetainRV)->setCalledFunction(getRetainCallee(F.getParent())); Constant *NewDecl = EP.get(ARCRuntimeEntryPoints::EPT_Retain);
cast<CallInst>(RetainRV)->setCalledFunction(NewDecl);
DEBUG(dbgs() << "New = " << *RetainRV << "\n"); DEBUG(dbgs() << "New = " << *RetainRV << "\n");
@ -1457,8 +1360,8 @@ ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV,
"Old = " << *AutoreleaseRV << "\n"); "Old = " << *AutoreleaseRV << "\n");
CallInst *AutoreleaseRVCI = cast<CallInst>(AutoreleaseRV); CallInst *AutoreleaseRVCI = cast<CallInst>(AutoreleaseRV);
AutoreleaseRVCI-> Constant *NewDecl = EP.get(ARCRuntimeEntryPoints::EPT_Autorelease);
setCalledFunction(getAutoreleaseCallee(F.getParent())); AutoreleaseRVCI->setCalledFunction(NewDecl);
AutoreleaseRVCI->setTailCall(false); // Never tail call objc_autorelease. AutoreleaseRVCI->setTailCall(false); // Never tail call objc_autorelease.
Class = IC_Autorelease; Class = IC_Autorelease;
@ -1492,7 +1395,8 @@ ObjCARCOpt::OptimizeRetainBlockCall(Function &F, Instruction *Inst,
DEBUG(dbgs() << "Strength reduced retainBlock => retain.\n"); DEBUG(dbgs() << "Strength reduced retainBlock => retain.\n");
DEBUG(dbgs() << "Old: " << *Inst << "\n"); DEBUG(dbgs() << "Old: " << *Inst << "\n");
CallInst *RetainBlock = cast<CallInst>(Inst); CallInst *RetainBlock = cast<CallInst>(Inst);
RetainBlock->setCalledFunction(getRetainCallee(F.getParent())); Constant *NewDecl = EP.get(ARCRuntimeEntryPoints::EPT_Retain);
RetainBlock->setCalledFunction(NewDecl);
// Remove copy_on_escape metadata. // Remove copy_on_escape metadata.
RetainBlock->setMetadata(CopyOnEscapeMDKind, 0); RetainBlock->setMetadata(CopyOnEscapeMDKind, 0);
Class = IC_Retain; Class = IC_Retain;
@ -1601,9 +1505,10 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
// Create the declaration lazily. // Create the declaration lazily.
LLVMContext &C = Inst->getContext(); LLVMContext &C = Inst->getContext();
CallInst *NewCall =
CallInst::Create(getReleaseCallee(F.getParent()), Constant *Decl = EP.get(ARCRuntimeEntryPoints::EPT_Release);
Call->getArgOperand(0), "", Call); CallInst *NewCall = CallInst::Create(Decl, Call->getArgOperand(0), "",
Call);
NewCall->setMetadata(ImpreciseReleaseMDKind, MDNode::get(C, None)); NewCall->setMetadata(ImpreciseReleaseMDKind, MDNode::get(C, None));
DEBUG(dbgs() << "Replacing autorelease{,RV}(x) with objc_release(x) " DEBUG(dbgs() << "Replacing autorelease{,RV}(x) with objc_release(x) "
@ -2519,8 +2424,8 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
Instruction *InsertPt = *PI; Instruction *InsertPt = *PI;
Value *MyArg = ArgTy == ParamTy ? Arg : Value *MyArg = ArgTy == ParamTy ? Arg :
new BitCastInst(Arg, ParamTy, "", InsertPt); new BitCastInst(Arg, ParamTy, "", InsertPt);
CallInst *Call = Constant *Decl = EP.get(ARCRuntimeEntryPoints::EPT_Retain);
CallInst::Create(getRetainCallee(M), MyArg, "", InsertPt); CallInst *Call = CallInst::Create(Decl, MyArg, "", InsertPt);
Call->setDoesNotThrow(); Call->setDoesNotThrow();
Call->setTailCall(); Call->setTailCall();
@ -2533,8 +2438,8 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
Instruction *InsertPt = *PI; Instruction *InsertPt = *PI;
Value *MyArg = ArgTy == ParamTy ? Arg : Value *MyArg = ArgTy == ParamTy ? Arg :
new BitCastInst(Arg, ParamTy, "", InsertPt); new BitCastInst(Arg, ParamTy, "", InsertPt);
CallInst *Call = CallInst::Create(getReleaseCallee(M), MyArg, Constant *Decl = EP.get(ARCRuntimeEntryPoints::EPT_Release);
"", InsertPt); CallInst *Call = CallInst::Create(Decl, MyArg, "", InsertPt);
// Attach a clang.imprecise_release metadata tag, if appropriate. // Attach a clang.imprecise_release metadata tag, if appropriate.
if (MDNode *M = ReleasesToMove.ReleaseMetadata) if (MDNode *M = ReleasesToMove.ReleaseMetadata)
Call->setMetadata(ImpreciseReleaseMDKind, M); Call->setMetadata(ImpreciseReleaseMDKind, M);
@ -2892,9 +2797,8 @@ void ObjCARCOpt::OptimizeWeakCalls(Function &F) {
Changed = true; Changed = true;
// If the load has a builtin retain, insert a plain retain for it. // If the load has a builtin retain, insert a plain retain for it.
if (Class == IC_LoadWeakRetained) { if (Class == IC_LoadWeakRetained) {
CallInst *CI = Constant *Decl = EP.get(ARCRuntimeEntryPoints::EPT_Retain);
CallInst::Create(getRetainCallee(F.getParent()), EarlierCall, CallInst *CI = CallInst::Create(Decl, EarlierCall, "", Call);
"", Call);
CI->setTailCall(); CI->setTailCall();
} }
// Zap the fully redundant load. // Zap the fully redundant load.
@ -2922,9 +2826,8 @@ void ObjCARCOpt::OptimizeWeakCalls(Function &F) {
Changed = true; Changed = true;
// If the load has a builtin retain, insert a plain retain for it. // If the load has a builtin retain, insert a plain retain for it.
if (Class == IC_LoadWeakRetained) { if (Class == IC_LoadWeakRetained) {
CallInst *CI = Constant *Decl = EP.get(ARCRuntimeEntryPoints::EPT_Retain);
CallInst::Create(getRetainCallee(F.getParent()), EarlierCall, CallInst *CI = CallInst::Create(Decl, EarlierCall, "", Call);
"", Call);
CI->setTailCall(); CI->setTailCall();
} }
// Zap the fully redundant load. // Zap the fully redundant load.
@ -3238,12 +3141,8 @@ bool ObjCARCOpt::doInitialization(Module &M) {
// they are not, because they return their argument value. And objc_release // they are not, because they return their argument value. And objc_release
// calls finalizers which can have arbitrary side effects. // calls finalizers which can have arbitrary side effects.
// These are initialized lazily. // Initialize our runtime entry point cache.
AutoreleaseRVCallee = 0; EP.Initialize(&M);
ReleaseCallee = 0;
RetainCallee = 0;
RetainBlockCallee = 0;
AutoreleaseCallee = 0;
return false; return false;
} }