diff options
Diffstat (limited to 'llvm/lib/Transforms/ObjCARC')
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARC.h | 12 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp | 15 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp | 40 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 73 |
7 files changed, 72 insertions, 81 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h b/llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h index e1e95cd6a4075..258dc92408150 100644 --- a/llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h +++ b/llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h @@ -22,19 +22,15 @@ #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H #define LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H -#include "llvm/ADT/StringRef.h" #include "llvm/IR/Attributes.h" -#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> namespace llvm { class Function; -class LLVMContext; +class Module; namespace objcarc { diff --git a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp index e8f8fb6f3a7c0..46bc586fe688a 100644 --- a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp +++ b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp @@ -95,10 +95,9 @@ bool llvm::objcarc::CanUse(const Instruction *Inst, const Value *Ptr, // of any other dynamic reference-counted pointers. if (!IsPotentialRetainableObjPtr(ICI->getOperand(1), *PA.getAA())) return false; - } else if (auto CS = ImmutableCallSite(Inst)) { + } else if (const auto *CS = dyn_cast<CallBase>(Inst)) { // For calls, just check the arguments (and not the callee operand). - for (ImmutableCallSite::arg_iterator OI = CS.arg_begin(), - OE = CS.arg_end(); OI != OE; ++OI) { + for (auto OI = CS->arg_begin(), OE = CS->arg_end(); OI != OE; ++OI) { const Value *Op = *OI; if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op, DL)) diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.h b/llvm/lib/Transforms/ObjCARC/ObjCARC.h index d465630800b9a..b496842fcfc5d 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARC.h +++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.h @@ -22,24 +22,12 @@ #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H #define LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H -#include "llvm/ADT/StringSwitch.h" -#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/ObjCARCAnalysisUtils.h" #include "llvm/Analysis/ObjCARCInstKind.h" -#include "llvm/Analysis/Passes.h" #include "llvm/Transforms/Utils/Local.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/Module.h" -#include "llvm/Pass.h" #include "llvm/Transforms/ObjCARC.h" namespace llvm { -class raw_ostream; -} - -namespace llvm { namespace objcarc { /// Erase the given instruction. diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp index 7a01ec967fb5d..ac1db27f5e64c 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp @@ -41,7 +41,7 @@ namespace { void getAnalysisUsage(AnalysisUsage &AU) const override; bool runOnModule(Module &M) override; - static bool MayAutorelease(ImmutableCallSite CS, unsigned Depth = 0); + static bool MayAutorelease(const CallBase &CB, unsigned Depth = 0); static bool OptimizeBB(BasicBlock *BB); public: @@ -68,18 +68,17 @@ void ObjCARCAPElim::getAnalysisUsage(AnalysisUsage &AU) const { /// Interprocedurally determine if calls made by the given call site can /// possibly produce autoreleases. -bool ObjCARCAPElim::MayAutorelease(ImmutableCallSite CS, unsigned Depth) { - if (const Function *Callee = CS.getCalledFunction()) { +bool ObjCARCAPElim::MayAutorelease(const CallBase &CB, unsigned Depth) { + if (const Function *Callee = CB.getCalledFunction()) { if (!Callee->hasExactDefinition()) return true; for (const BasicBlock &BB : *Callee) { for (const Instruction &I : BB) - if (ImmutableCallSite JCS = ImmutableCallSite(&I)) + if (const CallBase *JCB = dyn_cast<CallBase>(&I)) // This recursion depth limit is arbitrary. It's just great // enough to cover known interesting testcases. - if (Depth < 3 && - !JCS.onlyReadsMemory() && - MayAutorelease(JCS, Depth + 1)) + if (Depth < 3 && !JCB->onlyReadsMemory() && + MayAutorelease(*JCB, Depth + 1)) return true; } return false; @@ -115,7 +114,7 @@ bool ObjCARCAPElim::OptimizeBB(BasicBlock *BB) { Push = nullptr; break; case ARCInstKind::CallOrUser: - if (MayAutorelease(ImmutableCallSite(Inst))) + if (MayAutorelease(cast<CallBase>(*Inst))) Push = nullptr; break; default: diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp index ecf8220ae95da..7fd4857c44903 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp @@ -33,6 +33,7 @@ #include "llvm/Analysis/EHPersonalities.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Operator.h" #include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" @@ -47,10 +48,6 @@ using namespace llvm::objcarc; STATISTIC(NumPeeps, "Number of calls peephole-optimized"); STATISTIC(NumStoreStrongs, "Number objc_storeStrong calls formed"); -static cl::opt<unsigned> MaxBBSize("arc-contract-max-bb-size", cl::Hidden, - cl::desc("Maximum basic block size to discover the dominance relation of " - "two instructions in the same basic block"), cl::init(65535)); - //===----------------------------------------------------------------------===// // Declarations //===----------------------------------------------------------------------===// @@ -119,8 +116,7 @@ namespace { /// return value. We do this late so we do not disrupt the dataflow analysis in /// ObjCARCOpt. bool ObjCARCContract::optimizeRetainCall(Function &F, Instruction *Retain) { - ImmutableCallSite CS(GetArgRCIdentityRoot(Retain)); - const Instruction *Call = CS.getInstruction(); + const auto *Call = dyn_cast<CallBase>(GetArgRCIdentityRoot(Retain)); if (!Call) return false; if (Call->getParent() != Retain->getParent()) @@ -534,6 +530,7 @@ bool ObjCARCContract::tryToPeepholeInstruction( return true; case ARCInstKind::IntrinsicUser: // Remove calls to @llvm.objc.clang.arc.use(...). + Changed = true; Inst->eraseFromParent(); return true; default: @@ -580,23 +577,6 @@ bool ObjCARCContract::runOnFunction(Function &F) { SmallPtrSet<Instruction *, 4> DependingInstructions; SmallPtrSet<const BasicBlock *, 4> Visited; - // Cache the basic block size. - DenseMap<const BasicBlock *, unsigned> BBSizeMap; - - // A lambda that lazily computes the size of a basic block and determines - // whether the size exceeds MaxBBSize. - auto IsLargeBB = [&](const BasicBlock *BB) { - unsigned BBSize; - auto I = BBSizeMap.find(BB); - - if (I != BBSizeMap.end()) - BBSize = I->second; - else - BBSize = BBSizeMap[BB] = BB->size(); - - return BBSize > MaxBBSize; - }; - for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E;) { Instruction *Inst = &*I++; @@ -614,7 +594,7 @@ bool ObjCARCContract::runOnFunction(Function &F) { // and such; to do the replacement, the argument must have type i8*. // Function for replacing uses of Arg dominated by Inst. - auto ReplaceArgUses = [Inst, IsLargeBB, this](Value *Arg) { + auto ReplaceArgUses = [Inst, this](Value *Arg) { // If we're compiling bugpointed code, don't get in trouble. if (!isa<Instruction>(Arg) && !isa<Argument>(Arg)) return; @@ -626,17 +606,6 @@ bool ObjCARCContract::runOnFunction(Function &F) { Use &U = *UI++; unsigned OperandNo = U.getOperandNo(); - // Don't replace the uses if Inst and the user belong to the same basic - // block and the size of the basic block is large. We don't want to call - // DominatorTree::dominate in that case. We can remove this check if we - // can use OrderedBasicBlock to compute the dominance relation between - // two instructions, but that's not currently possible since it doesn't - // recompute the instruction ordering when new instructions are inserted - // to the basic block. - if (Inst->getParent() == cast<Instruction>(U.getUser())->getParent() && - IsLargeBB(Inst->getParent())) - continue; - // If the call's return value dominates a use of the call's argument // value, rewrite the use to use the return value. We check for // reachability here because an unreachable call is considered to @@ -689,7 +658,6 @@ bool ObjCARCContract::runOnFunction(Function &F) { } }; - Value *Arg = cast<CallInst>(Inst)->getArgOperand(0); Value *OrigArg = Arg; diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp index 205d8ddf151de..f8d872a7c9956 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp @@ -30,9 +30,7 @@ #include "llvm/IR/Value.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" -#include "llvm/PassAnalysisSupport.h" #include "llvm/PassRegistry.h" -#include "llvm/PassSupport.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp index b80c1675050bf..cb1fa804fa114 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -43,7 +43,6 @@ #include "llvm/Analysis/ObjCARCInstKind.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -610,8 +609,7 @@ bool ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) { // Check for the argument being from an immediately preceding call or invoke. const Value *Arg = GetArgRCIdentityRoot(RetainRV); - ImmutableCallSite CS(Arg); - if (const Instruction *Call = CS.getInstruction()) { + if (const Instruction *Call = dyn_cast<CallBase>(Arg)) { if (Call->getParent() == RetainRV->getParent()) { BasicBlock::const_iterator I(Call); ++I; @@ -678,6 +676,7 @@ bool ObjCARCOpt::OptimizeInlinedAutoreleaseRVCall( // Delete the RV pair, starting with the AutoreleaseRV. AutoreleaseRV->replaceAllUsesWith( cast<CallInst>(AutoreleaseRV)->getArgOperand(0)); + Changed = true; EraseInstruction(AutoreleaseRV); if (Class == ARCInstKind::RetainRV) { // AutoreleaseRV and RetainRV cancel out. Delete the RetainRV. @@ -877,23 +876,49 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { optimizeDelayedAutoreleaseRV(); } +/// This function returns true if the value is inert. An ObjC ARC runtime call +/// taking an inert operand can be safely deleted. +static bool isInertARCValue(Value *V, SmallPtrSet<Value *, 1> &VisitedPhis) { + V = V->stripPointerCasts(); + + if (IsNullOrUndef(V)) + return true; + + // See if this is a global attribute annotated with an 'objc_arc_inert'. + if (auto *GV = dyn_cast<GlobalVariable>(V)) + if (GV->hasAttribute("objc_arc_inert")) + return true; + + if (auto PN = dyn_cast<PHINode>(V)) { + // Ignore this phi if it has already been discovered. + if (!VisitedPhis.insert(PN).second) + return true; + // Look through phis's operands. + for (Value *Opnd : PN->incoming_values()) + if (!isInertARCValue(Opnd, VisitedPhis)) + return false; + return true; + } + + return false; +} + void ObjCARCOpt::OptimizeIndividualCallImpl( Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors, Instruction *Inst, ARCInstKind Class, const Value *Arg) { LLVM_DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n"); - // Some of the ARC calls can be deleted if their arguments are global - // variables that are inert in ARC. - if (IsNoopOnGlobal(Class)) { - Value *Opnd = Inst->getOperand(0); - if (auto *GV = dyn_cast<GlobalVariable>(Opnd->stripPointerCasts())) - if (GV->hasAttribute("objc_arc_inert")) { - if (!Inst->getType()->isVoidTy()) - Inst->replaceAllUsesWith(Opnd); - Inst->eraseFromParent(); - return; - } - } + // We can delete this call if it takes an inert value. + SmallPtrSet<Value *, 1> VisitedPhis; + + if (IsNoopOnGlobal(Class)) + if (isInertARCValue(Inst->getOperand(0), VisitedPhis)) { + if (!Inst->getType()->isVoidTy()) + Inst->replaceAllUsesWith(Inst->getOperand(0)); + Inst->eraseFromParent(); + Changed = true; + return; + } switch (Class) { default: @@ -1544,6 +1569,15 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB, } } + // Check that BB and MyStates have the same number of predecessors. This + // prevents retain calls that live outside a loop from being moved into the + // loop. + if (!BB->hasNPredecessors(MyStates.pred_end() - MyStates.pred_begin())) + for (auto I = MyStates.top_down_ptr_begin(), + E = MyStates.top_down_ptr_end(); + I != E; ++I) + I->second.SetCFGHazardAfflicted(true); + LLVM_DEBUG(dbgs() << "Before:\n" << BBStates[BB] << "\n" << "Performing Dataflow:\n"); @@ -2020,6 +2054,7 @@ void ObjCARCOpt::OptimizeWeakCalls(Function &F) { // Delete objc_loadWeak calls with no users. if (Class == ARCInstKind::LoadWeak && Inst->use_empty()) { Inst->eraseFromParent(); + Changed = true; continue; } @@ -2310,6 +2345,14 @@ void ObjCARCOpt::OptimizeReturns(Function &F) { bool HasSafePathToCall = HasSafePathToPredecessorCall(Arg, Retain, DependingInstructions, Visited, PA); + + // Don't remove retainRV/autoreleaseRV pairs if the call isn't a tail call. + if (HasSafePathToCall && + GetBasicARCInstKind(Retain) == ARCInstKind::RetainRV && + GetBasicARCInstKind(Autorelease) == ARCInstKind::AutoreleaseRV && + !cast<CallInst>(*DependingInstructions.begin())->isTailCall()) + continue; + DependingInstructions.clear(); Visited.clear(); |