summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp')
-rw-r--r--gnu/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp751
1 files changed, 0 insertions, 751 deletions
diff --git a/gnu/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/gnu/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
deleted file mode 100644
index abe2871c0b8..00000000000
--- a/gnu/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
+++ /dev/null
@@ -1,751 +0,0 @@
-//===- ObjCARCContract.cpp - ObjC ARC Optimization ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-/// \file
-/// This file defines late ObjC ARC optimizations. ARC stands for Automatic
-/// Reference Counting and is a system for managing reference counts for objects
-/// in Objective C.
-///
-/// This specific file mainly deals with ``contracting'' multiple lower level
-/// operations into singular higher level operations through pattern matching.
-///
-/// WARNING: This file knows about certain library functions. It recognizes them
-/// by name, and hardwires knowledge of their semantics.
-///
-/// WARNING: This file knows about how certain Objective-C library functions are
-/// used. Naive LLVM IR transformations which would otherwise be
-/// behavior-preserving may break these assumptions.
-///
-//===----------------------------------------------------------------------===//
-
-// TODO: ObjCARCContract could insert PHI nodes when uses aren't
-// dominated by single calls.
-
-#include "ARCRuntimeEntryPoints.h"
-#include "DependencyAnalysis.h"
-#include "ObjCARC.h"
-#include "ProvenanceAnalysis.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Analysis/EHPersonalities.h"
-#include "llvm/IR/Dominators.h"
-#include "llvm/IR/InlineAsm.h"
-#include "llvm/IR/Operator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace llvm::objcarc;
-
-#define DEBUG_TYPE "objc-arc-contract"
-
-STATISTIC(NumPeeps, "Number of calls peephole-optimized");
-STATISTIC(NumStoreStrongs, "Number objc_storeStrong calls formed");
-
-//===----------------------------------------------------------------------===//
-// Declarations
-//===----------------------------------------------------------------------===//
-
-namespace {
- /// Late ARC optimizations
- ///
- /// These change the IR in a way that makes it difficult to be analyzed by
- /// ObjCARCOpt, so it's run late.
- class ObjCARCContract : public FunctionPass {
- bool Changed;
- AliasAnalysis *AA;
- DominatorTree *DT;
- ProvenanceAnalysis PA;
- ARCRuntimeEntryPoints EP;
-
- /// A flag indicating whether this optimization pass should run.
- bool Run;
-
- /// The inline asm string to insert between calls and RetainRV calls to make
- /// the optimization work on targets which need it.
- 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
- /// "tail".
- SmallPtrSet<CallInst *, 8> StoreStrongCalls;
-
- /// Returns true if we eliminated Inst.
- bool tryToPeepholeInstruction(
- Function &F, Instruction *Inst, inst_iterator &Iter,
- SmallPtrSetImpl<Instruction *> &DepInsts,
- SmallPtrSetImpl<const BasicBlock *> &Visited,
- bool &TailOkForStoreStrong,
- const DenseMap<BasicBlock *, ColorVector> &BlockColors);
-
- bool optimizeRetainCall(Function &F, Instruction *Retain);
-
- bool
- contractAutorelease(Function &F, Instruction *Autorelease,
- ARCInstKind Class,
- SmallPtrSetImpl<Instruction *> &DependingInstructions,
- SmallPtrSetImpl<const BasicBlock *> &Visited);
-
- void tryToContractReleaseIntoStoreStrong(
- Instruction *Release, inst_iterator &Iter,
- const DenseMap<BasicBlock *, ColorVector> &BlockColors);
-
- void getAnalysisUsage(AnalysisUsage &AU) const override;
- bool doInitialization(Module &M) override;
- bool runOnFunction(Function &F) override;
-
- public:
- static char ID;
- ObjCARCContract() : FunctionPass(ID) {
- initializeObjCARCContractPass(*PassRegistry::getPassRegistry());
- }
- };
-}
-
-//===----------------------------------------------------------------------===//
-// Implementation
-//===----------------------------------------------------------------------===//
-
-/// Turn objc_retain into objc_retainAutoreleasedReturnValue if the operand is a
-/// 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();
- if (!Call)
- return false;
- if (Call->getParent() != Retain->getParent())
- return false;
-
- // Check that the call is next to the retain.
- BasicBlock::const_iterator I = ++Call->getIterator();
- while (IsNoopInstruction(&*I))
- ++I;
- if (&*I != Retain)
- return false;
-
- // Turn it to an objc_retainAutoreleasedReturnValue.
- Changed = true;
- ++NumPeeps;
-
- LLVM_DEBUG(
- dbgs() << "Transforming objc_retain => "
- "objc_retainAutoreleasedReturnValue since the operand is a "
- "return value.\nOld: "
- << *Retain << "\n");
-
- // We do not have to worry about tail calls/does not throw since
- // retain/retainRV have the same properties.
- Constant *Decl = EP.get(ARCRuntimeEntryPointKind::RetainRV);
- cast<CallInst>(Retain)->setCalledFunction(Decl);
-
- LLVM_DEBUG(dbgs() << "New: " << *Retain << "\n");
- return true;
-}
-
-/// Merge an autorelease with a retain into a fused call.
-bool ObjCARCContract::contractAutorelease(
- Function &F, Instruction *Autorelease, ARCInstKind Class,
- SmallPtrSetImpl<Instruction *> &DependingInstructions,
- SmallPtrSetImpl<const BasicBlock *> &Visited) {
- const Value *Arg = GetArgRCIdentityRoot(Autorelease);
-
- // Check that there are no instructions between the retain and the autorelease
- // (such as an autorelease_pop) which may change the count.
- CallInst *Retain = nullptr;
- if (Class == ARCInstKind::AutoreleaseRV)
- FindDependencies(RetainAutoreleaseRVDep, Arg,
- Autorelease->getParent(), Autorelease,
- DependingInstructions, Visited, PA);
- else
- FindDependencies(RetainAutoreleaseDep, Arg,
- Autorelease->getParent(), Autorelease,
- DependingInstructions, Visited, PA);
-
- Visited.clear();
- if (DependingInstructions.size() != 1) {
- DependingInstructions.clear();
- return false;
- }
-
- Retain = dyn_cast_or_null<CallInst>(*DependingInstructions.begin());
- DependingInstructions.clear();
-
- if (!Retain || GetBasicARCInstKind(Retain) != ARCInstKind::Retain ||
- GetArgRCIdentityRoot(Retain) != Arg)
- return false;
-
- Changed = true;
- ++NumPeeps;
-
- LLVM_DEBUG(dbgs() << " Fusing retain/autorelease!\n"
- " Autorelease:"
- << *Autorelease
- << "\n"
- " Retain: "
- << *Retain << "\n");
-
- Constant *Decl = EP.get(Class == ARCInstKind::AutoreleaseRV
- ? ARCRuntimeEntryPointKind::RetainAutoreleaseRV
- : ARCRuntimeEntryPointKind::RetainAutorelease);
- Retain->setCalledFunction(Decl);
-
- LLVM_DEBUG(dbgs() << " New RetainAutorelease: " << *Retain << "\n");
-
- EraseInstruction(Autorelease);
- return true;
-}
-
-static StoreInst *findSafeStoreForStoreStrongContraction(LoadInst *Load,
- Instruction *Release,
- ProvenanceAnalysis &PA,
- AliasAnalysis *AA) {
- StoreInst *Store = nullptr;
- bool SawRelease = false;
-
- // Get the location associated with Load.
- MemoryLocation Loc = MemoryLocation::get(Load);
- auto *LocPtr = Loc.Ptr->stripPointerCasts();
-
- // Walk down to find the store and the release, which may be in either order.
- for (auto I = std::next(BasicBlock::iterator(Load)),
- E = Load->getParent()->end();
- I != E; ++I) {
- // If we found the store we were looking for and saw the release,
- // break. There is no more work to be done.
- if (Store && SawRelease)
- break;
-
- // Now we know that we have not seen either the store or the release. If I
- // is the release, mark that we saw the release and continue.
- Instruction *Inst = &*I;
- if (Inst == Release) {
- SawRelease = true;
- continue;
- }
-
- // Otherwise, we check if Inst is a "good" store. Grab the instruction class
- // of Inst.
- ARCInstKind Class = GetBasicARCInstKind(Inst);
-
- // If Inst is an unrelated retain, we don't care about it.
- //
- // TODO: This is one area where the optimization could be made more
- // aggressive.
- if (IsRetain(Class))
- continue;
-
- // If we have seen the store, but not the release...
- if (Store) {
- // We need to make sure that it is safe to move the release from its
- // current position to the store. This implies proving that any
- // instruction in between Store and the Release conservatively can not use
- // the RCIdentityRoot of Release. If we can prove we can ignore Inst, so
- // continue...
- if (!CanUse(Inst, Load, PA, Class)) {
- continue;
- }
-
- // Otherwise, be conservative and return nullptr.
- return nullptr;
- }
-
- // Ok, now we know we have not seen a store yet. See if Inst can write to
- // our load location, if it can not, just ignore the instruction.
- if (!isModSet(AA->getModRefInfo(Inst, Loc)))
- continue;
-
- Store = dyn_cast<StoreInst>(Inst);
-
- // If Inst can, then check if Inst is a simple store. If Inst is not a
- // store or a store that is not simple, then we have some we do not
- // understand writing to this memory implying we can not move the load
- // over the write to any subsequent store that we may find.
- if (!Store || !Store->isSimple())
- return nullptr;
-
- // Then make sure that the pointer we are storing to is Ptr. If so, we
- // found our Store!
- if (Store->getPointerOperand()->stripPointerCasts() == LocPtr)
- continue;
-
- // Otherwise, we have an unknown store to some other ptr that clobbers
- // Loc.Ptr. Bail!
- return nullptr;
- }
-
- // If we did not find the store or did not see the release, fail.
- if (!Store || !SawRelease)
- return nullptr;
-
- // We succeeded!
- return Store;
-}
-
-static Instruction *
-findRetainForStoreStrongContraction(Value *New, StoreInst *Store,
- Instruction *Release,
- ProvenanceAnalysis &PA) {
- // Walk up from the Store to find the retain.
- BasicBlock::iterator I = Store->getIterator();
- BasicBlock::iterator Begin = Store->getParent()->begin();
- while (I != Begin && GetBasicARCInstKind(&*I) != ARCInstKind::Retain) {
- Instruction *Inst = &*I;
-
- // It is only safe to move the retain to the store if we can prove
- // conservatively that nothing besides the release can decrement reference
- // counts in between the retain and the store.
- if (CanDecrementRefCount(Inst, New, PA) && Inst != Release)
- return nullptr;
- --I;
- }
- Instruction *Retain = &*I;
- if (GetBasicARCInstKind(Retain) != ARCInstKind::Retain)
- return nullptr;
- if (GetArgRCIdentityRoot(Retain) != New)
- return nullptr;
- return Retain;
-}
-
-/// Create a call instruction with the correct funclet token. Should be used
-/// instead of calling CallInst::Create directly.
-static CallInst *
-createCallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr,
- Instruction *InsertBefore,
- const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
- SmallVector<OperandBundleDef, 1> OpBundles;
- if (!BlockColors.empty()) {
- const ColorVector &CV = BlockColors.find(InsertBefore->getParent())->second;
- assert(CV.size() == 1 && "non-unique color for block!");
- Instruction *EHPad = CV.front()->getFirstNonPHI();
- if (EHPad->isEHPad())
- OpBundles.emplace_back("funclet", EHPad);
- }
-
- return CallInst::Create(Func, Args, OpBundles, NameStr, InsertBefore);
-}
-
-/// Attempt to merge an objc_release with a store, load, and objc_retain to form
-/// an objc_storeStrong. An objc_storeStrong:
-///
-/// objc_storeStrong(i8** %old_ptr, i8* new_value)
-///
-/// is equivalent to the following IR sequence:
-///
-/// ; Load old value.
-/// %old_value = load i8** %old_ptr (1)
-///
-/// ; Increment the new value and then release the old value. This must occur
-/// ; in order in case old_value releases new_value in its destructor causing
-/// ; us to potentially have a dangling ptr.
-/// tail call i8* @objc_retain(i8* %new_value) (2)
-/// tail call void @objc_release(i8* %old_value) (3)
-///
-/// ; Store the new_value into old_ptr
-/// store i8* %new_value, i8** %old_ptr (4)
-///
-/// The safety of this optimization is based around the following
-/// considerations:
-///
-/// 1. We are forming the store strong at the store. Thus to perform this
-/// optimization it must be safe to move the retain, load, and release to
-/// (4).
-/// 2. We need to make sure that any re-orderings of (1), (2), (3), (4) are
-/// safe.
-void ObjCARCContract::tryToContractReleaseIntoStoreStrong(
- Instruction *Release, inst_iterator &Iter,
- const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
- // See if we are releasing something that we just loaded.
- auto *Load = dyn_cast<LoadInst>(GetArgRCIdentityRoot(Release));
- if (!Load || !Load->isSimple())
- return;
-
- // For now, require everything to be in one basic block.
- BasicBlock *BB = Release->getParent();
- if (Load->getParent() != BB)
- return;
-
- // First scan down the BB from Load, looking for a store of the RCIdentityRoot
- // of Load's
- StoreInst *Store =
- findSafeStoreForStoreStrongContraction(Load, Release, PA, AA);
- // If we fail, bail.
- if (!Store)
- return;
-
- // Then find what new_value's RCIdentity Root is.
- Value *New = GetRCIdentityRoot(Store->getValueOperand());
-
- // Then walk up the BB and look for a retain on New without any intervening
- // instructions which conservatively might decrement ref counts.
- Instruction *Retain =
- findRetainForStoreStrongContraction(New, Store, Release, PA);
-
- // If we fail, bail.
- if (!Retain)
- return;
-
- Changed = true;
- ++NumStoreStrongs;
-
- LLVM_DEBUG(
- llvm::dbgs() << " Contracting retain, release into objc_storeStrong.\n"
- << " Old:\n"
- << " Store: " << *Store << "\n"
- << " Release: " << *Release << "\n"
- << " Retain: " << *Retain << "\n"
- << " Load: " << *Load << "\n");
-
- LLVMContext &C = Release->getContext();
- Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
- Type *I8XX = PointerType::getUnqual(I8X);
-
- Value *Args[] = { Load->getPointerOperand(), New };
- if (Args[0]->getType() != I8XX)
- Args[0] = new BitCastInst(Args[0], I8XX, "", Store);
- if (Args[1]->getType() != I8X)
- Args[1] = new BitCastInst(Args[1], I8X, "", Store);
- Constant *Decl = EP.get(ARCRuntimeEntryPointKind::StoreStrong);
- CallInst *StoreStrong = createCallInst(Decl, Args, "", Store, BlockColors);
- StoreStrong->setDoesNotThrow();
- StoreStrong->setDebugLoc(Store->getDebugLoc());
-
- // We can't set the tail flag yet, because we haven't yet determined
- // whether there are any escaping allocas. Remember this call, so that
- // we can set the tail flag once we know it's safe.
- StoreStrongCalls.insert(StoreStrong);
-
- LLVM_DEBUG(llvm::dbgs() << " New Store Strong: " << *StoreStrong
- << "\n");
-
- if (&*Iter == Retain) ++Iter;
- if (&*Iter == Store) ++Iter;
- Store->eraseFromParent();
- Release->eraseFromParent();
- EraseInstruction(Retain);
- if (Load->use_empty())
- Load->eraseFromParent();
-}
-
-bool ObjCARCContract::tryToPeepholeInstruction(
- Function &F, Instruction *Inst, inst_iterator &Iter,
- SmallPtrSetImpl<Instruction *> &DependingInsts,
- SmallPtrSetImpl<const BasicBlock *> &Visited,
- bool &TailOkForStoreStrongs,
- const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
- // Only these library routines return their argument. In particular,
- // objc_retainBlock does not necessarily return its argument.
- ARCInstKind Class = GetBasicARCInstKind(Inst);
- switch (Class) {
- case ARCInstKind::FusedRetainAutorelease:
- case ARCInstKind::FusedRetainAutoreleaseRV:
- return false;
- case ARCInstKind::Autorelease:
- case ARCInstKind::AutoreleaseRV:
- return contractAutorelease(F, Inst, Class, DependingInsts, Visited);
- case ARCInstKind::Retain:
- // Attempt to convert retains to retainrvs if they are next to function
- // calls.
- if (!optimizeRetainCall(F, Inst))
- return false;
- // If we succeed in our optimization, fall through.
- LLVM_FALLTHROUGH;
- case ARCInstKind::RetainRV:
- case ARCInstKind::ClaimRV: {
- // If we're compiling for a target which needs a special inline-asm
- // 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 RV call.
- // If it's an invoke, we have to cross a block boundary. And we have
- // to carefully dodge no-op instructions.
- do {
- if (BBI == InstParent->begin()) {
- BasicBlock *Pred = InstParent->getSinglePredecessor();
- if (!Pred)
- goto decline_rv_optimization;
- BBI = Pred->getTerminator()->getIterator();
- break;
- }
- --BBI;
- } while (IsNoopInstruction(&*BBI));
-
- if (&*BBI == GetArgRCIdentityRoot(Inst)) {
- LLVM_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),
- RVInstMarker->getString(),
- /*Constraints=*/"", /*hasSideEffects=*/true);
-
- createCallInst(IA, None, "", Inst, BlockColors);
- }
- decline_rv_optimization:
- return false;
- }
- case ARCInstKind::InitWeak: {
- // objc_initWeak(p, null) => *p = null
- CallInst *CI = cast<CallInst>(Inst);
- if (IsNullOrUndef(CI->getArgOperand(1))) {
- Value *Null =
- ConstantPointerNull::get(cast<PointerType>(CI->getType()));
- Changed = true;
- new StoreInst(Null, CI->getArgOperand(0), CI);
-
- LLVM_DEBUG(dbgs() << "OBJCARCContract: Old = " << *CI << "\n"
- << " New = " << *Null << "\n");
-
- CI->replaceAllUsesWith(Null);
- CI->eraseFromParent();
- }
- return true;
- }
- case ARCInstKind::Release:
- // Try to form an objc store strong from our release. If we fail, there is
- // nothing further to do below, so continue.
- tryToContractReleaseIntoStoreStrong(Inst, Iter, BlockColors);
- return true;
- case ARCInstKind::User:
- // Be conservative if the function has any alloca instructions.
- // Technically we only care about escaping alloca instructions,
- // but this is sufficient to handle some interesting cases.
- if (isa<AllocaInst>(Inst))
- TailOkForStoreStrongs = false;
- return true;
- case ARCInstKind::IntrinsicUser:
- // Remove calls to @llvm.objc.clang.arc.use(...).
- Inst->eraseFromParent();
- return true;
- default:
- return true;
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Top Level Driver
-//===----------------------------------------------------------------------===//
-
-bool ObjCARCContract::runOnFunction(Function &F) {
- if (!EnableARCOpts)
- return false;
-
- // If nothing in the Module uses ARC, don't do anything.
- if (!Run)
- return false;
-
- Changed = false;
- AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
- DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
-
- PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults());
-
- DenseMap<BasicBlock *, ColorVector> BlockColors;
- if (F.hasPersonalityFn() &&
- isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
- BlockColors = colorEHFunclets(F);
-
- LLVM_DEBUG(llvm::dbgs() << "**** ObjCARC Contract ****\n");
-
- // Track whether it's ok to mark objc_storeStrong calls with the "tail"
- // keyword. Be conservative if the function has variadic arguments.
- // It seems that functions which "return twice" are also unsafe for the
- // "tail" argument, because they are setjmp, which could need to
- // return to an earlier stack state.
- bool TailOkForStoreStrongs =
- !F.isVarArg() && !F.callsFunctionThatReturnsTwice();
-
- // For ObjC library calls which return their argument, replace uses of the
- // argument with uses of the call return value, if it dominates the use. This
- // reduces register pressure.
- SmallPtrSet<Instruction *, 4> DependingInstructions;
- SmallPtrSet<const BasicBlock *, 4> Visited;
- for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E;) {
- Instruction *Inst = &*I++;
-
- LLVM_DEBUG(dbgs() << "Visiting: " << *Inst << "\n");
-
- // First try to peephole Inst. If there is nothing further we can do in
- // terms of undoing objc-arc-expand, process the next inst.
- if (tryToPeepholeInstruction(F, Inst, I, DependingInstructions, Visited,
- TailOkForStoreStrongs, BlockColors))
- continue;
-
- // Otherwise, try to undo objc-arc-expand.
-
- // Don't use GetArgRCIdentityRoot because we don't want to look through bitcasts
- // and such; to do the replacement, the argument must have type i8*.
-
- // Function for replacing uses of Arg dominated by Inst.
- 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;
-
- // Look through the uses of the pointer.
- for (Value::use_iterator UI = Arg->use_begin(), UE = Arg->use_end();
- UI != UE; ) {
- // Increment UI now, because we may unlink its element.
- Use &U = *UI++;
- unsigned OperandNo = U.getOperandNo();
-
- // 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
- // trivially dominate itself, which would lead us to rewriting its
- // argument in terms of its return value, which would lead to
- // infinite loops in GetArgRCIdentityRoot.
- if (!DT->isReachableFromEntry(U) || !DT->dominates(Inst, U))
- continue;
-
- Changed = true;
- Instruction *Replacement = Inst;
- Type *UseTy = U.get()->getType();
- if (PHINode *PHI = dyn_cast<PHINode>(U.getUser())) {
- // For PHI nodes, insert the bitcast in the predecessor block.
- unsigned ValNo = PHINode::getIncomingValueNumForOperand(OperandNo);
- BasicBlock *IncomingBB = PHI->getIncomingBlock(ValNo);
- if (Replacement->getType() != UseTy) {
- // A catchswitch is both a pad and a terminator, meaning a basic
- // block with a catchswitch has no insertion point. Keep going up
- // the dominator tree until we find a non-catchswitch.
- BasicBlock *InsertBB = IncomingBB;
- while (isa<CatchSwitchInst>(InsertBB->getFirstNonPHI())) {
- InsertBB = DT->getNode(InsertBB)->getIDom()->getBlock();
- }
-
- assert(DT->dominates(Inst, &InsertBB->back()) &&
- "Invalid insertion point for bitcast");
- Replacement =
- new BitCastInst(Replacement, UseTy, "", &InsertBB->back());
- }
-
- // While we're here, rewrite all edges for this PHI, rather
- // than just one use at a time, to minimize the number of
- // bitcasts we emit.
- for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i)
- if (PHI->getIncomingBlock(i) == IncomingBB) {
- // Keep the UI iterator valid.
- if (UI != UE &&
- &PHI->getOperandUse(
- PHINode::getOperandNumForIncomingValue(i)) == &*UI)
- ++UI;
- PHI->setIncomingValue(i, Replacement);
- }
- } else {
- if (Replacement->getType() != UseTy)
- Replacement = new BitCastInst(Replacement, UseTy, "",
- cast<Instruction>(U.getUser()));
- U.set(Replacement);
- }
- }
- };
-
-
- Value *Arg = cast<CallInst>(Inst)->getArgOperand(0);
- Value *OrigArg = Arg;
-
- // TODO: Change this to a do-while.
- for (;;) {
- ReplaceArgUses(Arg);
-
- // If Arg is a no-op casted pointer, strip one level of casts and iterate.
- if (const BitCastInst *BI = dyn_cast<BitCastInst>(Arg))
- Arg = BI->getOperand(0);
- else if (isa<GEPOperator>(Arg) &&
- cast<GEPOperator>(Arg)->hasAllZeroIndices())
- Arg = cast<GEPOperator>(Arg)->getPointerOperand();
- else if (isa<GlobalAlias>(Arg) &&
- !cast<GlobalAlias>(Arg)->isInterposable())
- Arg = cast<GlobalAlias>(Arg)->getAliasee();
- else {
- // If Arg is a PHI node, get PHIs that are equivalent to it and replace
- // their uses.
- if (PHINode *PN = dyn_cast<PHINode>(Arg)) {
- SmallVector<Value *, 1> PHIList;
- getEquivalentPHIs(*PN, PHIList);
- for (Value *PHI : PHIList)
- ReplaceArgUses(PHI);
- }
- break;
- }
- }
-
- // Replace bitcast users of Arg that are dominated by Inst.
- SmallVector<BitCastInst *, 2> BitCastUsers;
-
- // Add all bitcast users of the function argument first.
- for (User *U : OrigArg->users())
- if (auto *BC = dyn_cast<BitCastInst>(U))
- BitCastUsers.push_back(BC);
-
- // Replace the bitcasts with the call return. Iterate until list is empty.
- while (!BitCastUsers.empty()) {
- auto *BC = BitCastUsers.pop_back_val();
- for (User *U : BC->users())
- if (auto *B = dyn_cast<BitCastInst>(U))
- BitCastUsers.push_back(B);
-
- ReplaceArgUses(BC);
- }
- }
-
- // If this function has no escaping allocas or suspicious vararg usage,
- // objc_storeStrong calls can be marked with the "tail" keyword.
- if (TailOkForStoreStrongs)
- for (CallInst *CI : StoreStrongCalls)
- CI->setTailCall();
- StoreStrongCalls.clear();
-
- return Changed;
-}
-
-//===----------------------------------------------------------------------===//
-// Misc Pass Manager
-//===----------------------------------------------------------------------===//
-
-char ObjCARCContract::ID = 0;
-INITIALIZE_PASS_BEGIN(ObjCARCContract, "objc-arc-contract",
- "ObjC ARC contraction", false, false)
-INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
-INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
-INITIALIZE_PASS_END(ObjCARCContract, "objc-arc-contract",
- "ObjC ARC contraction", false, false)
-
-void ObjCARCContract::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<AAResultsWrapperPass>();
- AU.addRequired<DominatorTreeWrapperPass>();
- AU.setPreservesCFG();
-}
-
-Pass *llvm::createObjCARCContractPass() { return new ObjCARCContract(); }
-
-bool ObjCARCContract::doInitialization(Module &M) {
- // If nothing in the Module uses ARC, don't do anything.
- Run = ModuleHasARC(M);
- if (!Run)
- return false;
-
- EP.init(&M);
-
- // 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)))
- RVInstMarker = S;
- }
-
- return false;
-}