Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
35268 views
//===- ObjCARCOpts.cpp - ObjC ARC Optimization ----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8/// \file9/// This file defines ObjC ARC optimizations. ARC stands for Automatic10/// Reference Counting and is a system for managing reference counts for objects11/// in Objective C.12///13/// The optimizations performed include elimination of redundant, partially14/// redundant, and inconsequential reference count operations, elimination of15/// redundant weak pointer operations, and numerous minor simplifications.16///17/// WARNING: This file knows about certain library functions. It recognizes them18/// by name, and hardwires knowledge of their semantics.19///20/// WARNING: This file knows about how certain Objective-C library functions are21/// used. Naive LLVM IR transformations which would otherwise be22/// behavior-preserving may break these assumptions.23//24//===----------------------------------------------------------------------===//2526#include "ARCRuntimeEntryPoints.h"27#include "BlotMapVector.h"28#include "DependencyAnalysis.h"29#include "ObjCARC.h"30#include "ProvenanceAnalysis.h"31#include "PtrState.h"32#include "llvm/ADT/DenseMap.h"33#include "llvm/ADT/STLExtras.h"34#include "llvm/ADT/SmallPtrSet.h"35#include "llvm/ADT/SmallVector.h"36#include "llvm/ADT/Statistic.h"37#include "llvm/Analysis/AliasAnalysis.h"38#include "llvm/Analysis/ObjCARCAliasAnalysis.h"39#include "llvm/Analysis/ObjCARCAnalysisUtils.h"40#include "llvm/Analysis/ObjCARCInstKind.h"41#include "llvm/Analysis/ObjCARCUtil.h"42#include "llvm/IR/BasicBlock.h"43#include "llvm/IR/CFG.h"44#include "llvm/IR/Constant.h"45#include "llvm/IR/Constants.h"46#include "llvm/IR/DerivedTypes.h"47#include "llvm/IR/EHPersonalities.h"48#include "llvm/IR/Function.h"49#include "llvm/IR/GlobalVariable.h"50#include "llvm/IR/InstIterator.h"51#include "llvm/IR/InstrTypes.h"52#include "llvm/IR/Instruction.h"53#include "llvm/IR/Instructions.h"54#include "llvm/IR/LLVMContext.h"55#include "llvm/IR/Metadata.h"56#include "llvm/IR/Type.h"57#include "llvm/IR/User.h"58#include "llvm/IR/Value.h"59#include "llvm/Support/Casting.h"60#include "llvm/Support/CommandLine.h"61#include "llvm/Support/Compiler.h"62#include "llvm/Support/Debug.h"63#include "llvm/Support/ErrorHandling.h"64#include "llvm/Support/raw_ostream.h"65#include "llvm/Transforms/ObjCARC.h"66#include <cassert>67#include <iterator>68#include <utility>6970using namespace llvm;71using namespace llvm::objcarc;7273#define DEBUG_TYPE "objc-arc-opts"7475static cl::opt<unsigned> MaxPtrStates("arc-opt-max-ptr-states",76cl::Hidden,77cl::desc("Maximum number of ptr states the optimizer keeps track of"),78cl::init(4095));7980/// \defgroup ARCUtilities Utility declarations/definitions specific to ARC.81/// @{8283/// This is similar to GetRCIdentityRoot but it stops as soon84/// as it finds a value with multiple uses.85static const Value *FindSingleUseIdentifiedObject(const Value *Arg) {86// ConstantData (like ConstantPointerNull and UndefValue) is used across87// modules. It's never a single-use value.88if (isa<ConstantData>(Arg))89return nullptr;9091if (Arg->hasOneUse()) {92if (const BitCastInst *BC = dyn_cast<BitCastInst>(Arg))93return FindSingleUseIdentifiedObject(BC->getOperand(0));94if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Arg))95if (GEP->hasAllZeroIndices())96return FindSingleUseIdentifiedObject(GEP->getPointerOperand());97if (IsForwarding(GetBasicARCInstKind(Arg)))98return FindSingleUseIdentifiedObject(99cast<CallInst>(Arg)->getArgOperand(0));100if (!IsObjCIdentifiedObject(Arg))101return nullptr;102return Arg;103}104105// If we found an identifiable object but it has multiple uses, but they are106// trivial uses, we can still consider this to be a single-use value.107if (IsObjCIdentifiedObject(Arg)) {108for (const User *U : Arg->users())109if (!U->use_empty() || GetRCIdentityRoot(U) != Arg)110return nullptr;111112return Arg;113}114115return nullptr;116}117118/// @}119///120/// \defgroup ARCOpt ARC Optimization.121/// @{122123// TODO: On code like this:124//125// objc_retain(%x)126// stuff_that_cannot_release()127// objc_autorelease(%x)128// stuff_that_cannot_release()129// objc_retain(%x)130// stuff_that_cannot_release()131// objc_autorelease(%x)132//133// The second retain and autorelease can be deleted.134135// TODO: It should be possible to delete136// objc_autoreleasePoolPush and objc_autoreleasePoolPop137// pairs if nothing is actually autoreleased between them. Also, autorelease138// calls followed by objc_autoreleasePoolPop calls (perhaps in ObjC++ code139// after inlining) can be turned into plain release calls.140141// TODO: Critical-edge splitting. If the optimial insertion point is142// a critical edge, the current algorithm has to fail, because it doesn't143// know how to split edges. It should be possible to make the optimizer144// think in terms of edges, rather than blocks, and then split critical145// edges on demand.146147// TODO: OptimizeSequences could generalized to be Interprocedural.148149// TODO: Recognize that a bunch of other objc runtime calls have150// non-escaping arguments and non-releasing arguments, and may be151// non-autoreleasing.152153// TODO: Sink autorelease calls as far as possible. Unfortunately we154// usually can't sink them past other calls, which would be the main155// case where it would be useful.156157// TODO: The pointer returned from objc_loadWeakRetained is retained.158159// TODO: Delete release+retain pairs (rare).160161STATISTIC(NumNoops, "Number of no-op objc calls eliminated");162STATISTIC(NumPartialNoops, "Number of partially no-op objc calls eliminated");163STATISTIC(NumAutoreleases,"Number of autoreleases converted to releases");164STATISTIC(NumRets, "Number of return value forwarding "165"retain+autoreleases eliminated");166STATISTIC(NumRRs, "Number of retain+release paths eliminated");167STATISTIC(NumPeeps, "Number of calls peephole-optimized");168#ifndef NDEBUG169STATISTIC(NumRetainsBeforeOpt,170"Number of retains before optimization");171STATISTIC(NumReleasesBeforeOpt,172"Number of releases before optimization");173STATISTIC(NumRetainsAfterOpt,174"Number of retains after optimization");175STATISTIC(NumReleasesAfterOpt,176"Number of releases after optimization");177#endif178179namespace {180181/// Per-BasicBlock state.182class BBState {183/// The number of unique control paths from the entry which can reach this184/// block.185unsigned TopDownPathCount = 0;186187/// The number of unique control paths to exits from this block.188unsigned BottomUpPathCount = 0;189190/// The top-down traversal uses this to record information known about a191/// pointer at the bottom of each block.192BlotMapVector<const Value *, TopDownPtrState> PerPtrTopDown;193194/// The bottom-up traversal uses this to record information known about a195/// pointer at the top of each block.196BlotMapVector<const Value *, BottomUpPtrState> PerPtrBottomUp;197198/// Effective predecessors of the current block ignoring ignorable edges and199/// ignored backedges.200SmallVector<BasicBlock *, 2> Preds;201202/// Effective successors of the current block ignoring ignorable edges and203/// ignored backedges.204SmallVector<BasicBlock *, 2> Succs;205206public:207static const unsigned OverflowOccurredValue;208209BBState() = default;210211using top_down_ptr_iterator = decltype(PerPtrTopDown)::iterator;212using const_top_down_ptr_iterator = decltype(PerPtrTopDown)::const_iterator;213214top_down_ptr_iterator top_down_ptr_begin() { return PerPtrTopDown.begin(); }215top_down_ptr_iterator top_down_ptr_end() { return PerPtrTopDown.end(); }216const_top_down_ptr_iterator top_down_ptr_begin() const {217return PerPtrTopDown.begin();218}219const_top_down_ptr_iterator top_down_ptr_end() const {220return PerPtrTopDown.end();221}222bool hasTopDownPtrs() const {223return !PerPtrTopDown.empty();224}225226unsigned top_down_ptr_list_size() const {227return std::distance(top_down_ptr_begin(), top_down_ptr_end());228}229230using bottom_up_ptr_iterator = decltype(PerPtrBottomUp)::iterator;231using const_bottom_up_ptr_iterator =232decltype(PerPtrBottomUp)::const_iterator;233234bottom_up_ptr_iterator bottom_up_ptr_begin() {235return PerPtrBottomUp.begin();236}237bottom_up_ptr_iterator bottom_up_ptr_end() { return PerPtrBottomUp.end(); }238const_bottom_up_ptr_iterator bottom_up_ptr_begin() const {239return PerPtrBottomUp.begin();240}241const_bottom_up_ptr_iterator bottom_up_ptr_end() const {242return PerPtrBottomUp.end();243}244bool hasBottomUpPtrs() const {245return !PerPtrBottomUp.empty();246}247248unsigned bottom_up_ptr_list_size() const {249return std::distance(bottom_up_ptr_begin(), bottom_up_ptr_end());250}251252/// Mark this block as being an entry block, which has one path from the253/// entry by definition.254void SetAsEntry() { TopDownPathCount = 1; }255256/// Mark this block as being an exit block, which has one path to an exit by257/// definition.258void SetAsExit() { BottomUpPathCount = 1; }259260/// Attempt to find the PtrState object describing the top down state for261/// pointer Arg. Return a new initialized PtrState describing the top down262/// state for Arg if we do not find one.263TopDownPtrState &getPtrTopDownState(const Value *Arg) {264return PerPtrTopDown[Arg];265}266267/// Attempt to find the PtrState object describing the bottom up state for268/// pointer Arg. Return a new initialized PtrState describing the bottom up269/// state for Arg if we do not find one.270BottomUpPtrState &getPtrBottomUpState(const Value *Arg) {271return PerPtrBottomUp[Arg];272}273274/// Attempt to find the PtrState object describing the bottom up state for275/// pointer Arg.276bottom_up_ptr_iterator findPtrBottomUpState(const Value *Arg) {277return PerPtrBottomUp.find(Arg);278}279280void clearBottomUpPointers() {281PerPtrBottomUp.clear();282}283284void clearTopDownPointers() {285PerPtrTopDown.clear();286}287288void InitFromPred(const BBState &Other);289void InitFromSucc(const BBState &Other);290void MergePred(const BBState &Other);291void MergeSucc(const BBState &Other);292293/// Compute the number of possible unique paths from an entry to an exit294/// which pass through this block. This is only valid after both the295/// top-down and bottom-up traversals are complete.296///297/// Returns true if overflow occurred. Returns false if overflow did not298/// occur.299bool GetAllPathCountWithOverflow(unsigned &PathCount) const {300if (TopDownPathCount == OverflowOccurredValue ||301BottomUpPathCount == OverflowOccurredValue)302return true;303unsigned long long Product =304(unsigned long long)TopDownPathCount*BottomUpPathCount;305// Overflow occurred if any of the upper bits of Product are set or if all306// the lower bits of Product are all set.307return (Product >> 32) ||308((PathCount = Product) == OverflowOccurredValue);309}310311// Specialized CFG utilities.312using edge_iterator = SmallVectorImpl<BasicBlock *>::const_iterator;313314edge_iterator pred_begin() const { return Preds.begin(); }315edge_iterator pred_end() const { return Preds.end(); }316edge_iterator succ_begin() const { return Succs.begin(); }317edge_iterator succ_end() const { return Succs.end(); }318319void addSucc(BasicBlock *Succ) { Succs.push_back(Succ); }320void addPred(BasicBlock *Pred) { Preds.push_back(Pred); }321322bool isExit() const { return Succs.empty(); }323};324325} // end anonymous namespace326327const unsigned BBState::OverflowOccurredValue = 0xffffffff;328329namespace llvm {330331raw_ostream &operator<<(raw_ostream &OS,332BBState &BBState) LLVM_ATTRIBUTE_UNUSED;333334} // end namespace llvm335336void BBState::InitFromPred(const BBState &Other) {337PerPtrTopDown = Other.PerPtrTopDown;338TopDownPathCount = Other.TopDownPathCount;339}340341void BBState::InitFromSucc(const BBState &Other) {342PerPtrBottomUp = Other.PerPtrBottomUp;343BottomUpPathCount = Other.BottomUpPathCount;344}345346/// The top-down traversal uses this to merge information about predecessors to347/// form the initial state for a new block.348void BBState::MergePred(const BBState &Other) {349if (TopDownPathCount == OverflowOccurredValue)350return;351352// Other.TopDownPathCount can be 0, in which case it is either dead or a353// loop backedge. Loop backedges are special.354TopDownPathCount += Other.TopDownPathCount;355356// In order to be consistent, we clear the top down pointers when by adding357// TopDownPathCount becomes OverflowOccurredValue even though "true" overflow358// has not occurred.359if (TopDownPathCount == OverflowOccurredValue) {360clearTopDownPointers();361return;362}363364// Check for overflow. If we have overflow, fall back to conservative365// behavior.366if (TopDownPathCount < Other.TopDownPathCount) {367TopDownPathCount = OverflowOccurredValue;368clearTopDownPointers();369return;370}371372// For each entry in the other set, if our set has an entry with the same key,373// merge the entries. Otherwise, copy the entry and merge it with an empty374// entry.375for (auto MI = Other.top_down_ptr_begin(), ME = Other.top_down_ptr_end();376MI != ME; ++MI) {377auto Pair = PerPtrTopDown.insert(*MI);378Pair.first->second.Merge(Pair.second ? TopDownPtrState() : MI->second,379/*TopDown=*/true);380}381382// For each entry in our set, if the other set doesn't have an entry with the383// same key, force it to merge with an empty entry.384for (auto MI = top_down_ptr_begin(), ME = top_down_ptr_end(); MI != ME; ++MI)385if (Other.PerPtrTopDown.find(MI->first) == Other.PerPtrTopDown.end())386MI->second.Merge(TopDownPtrState(), /*TopDown=*/true);387}388389/// The bottom-up traversal uses this to merge information about successors to390/// form the initial state for a new block.391void BBState::MergeSucc(const BBState &Other) {392if (BottomUpPathCount == OverflowOccurredValue)393return;394395// Other.BottomUpPathCount can be 0, in which case it is either dead or a396// loop backedge. Loop backedges are special.397BottomUpPathCount += Other.BottomUpPathCount;398399// In order to be consistent, we clear the top down pointers when by adding400// BottomUpPathCount becomes OverflowOccurredValue even though "true" overflow401// has not occurred.402if (BottomUpPathCount == OverflowOccurredValue) {403clearBottomUpPointers();404return;405}406407// Check for overflow. If we have overflow, fall back to conservative408// behavior.409if (BottomUpPathCount < Other.BottomUpPathCount) {410BottomUpPathCount = OverflowOccurredValue;411clearBottomUpPointers();412return;413}414415// For each entry in the other set, if our set has an entry with the416// same key, merge the entries. Otherwise, copy the entry and merge417// it with an empty entry.418for (auto MI = Other.bottom_up_ptr_begin(), ME = Other.bottom_up_ptr_end();419MI != ME; ++MI) {420auto Pair = PerPtrBottomUp.insert(*MI);421Pair.first->second.Merge(Pair.second ? BottomUpPtrState() : MI->second,422/*TopDown=*/false);423}424425// For each entry in our set, if the other set doesn't have an entry426// with the same key, force it to merge with an empty entry.427for (auto MI = bottom_up_ptr_begin(), ME = bottom_up_ptr_end(); MI != ME;428++MI)429if (Other.PerPtrBottomUp.find(MI->first) == Other.PerPtrBottomUp.end())430MI->second.Merge(BottomUpPtrState(), /*TopDown=*/false);431}432433raw_ostream &llvm::operator<<(raw_ostream &OS, BBState &BBInfo) {434// Dump the pointers we are tracking.435OS << " TopDown State:\n";436if (!BBInfo.hasTopDownPtrs()) {437LLVM_DEBUG(dbgs() << " NONE!\n");438} else {439for (auto I = BBInfo.top_down_ptr_begin(), E = BBInfo.top_down_ptr_end();440I != E; ++I) {441const PtrState &P = I->second;442OS << " Ptr: " << *I->first443<< "\n KnownSafe: " << (P.IsKnownSafe()?"true":"false")444<< "\n ImpreciseRelease: "445<< (P.IsTrackingImpreciseReleases()?"true":"false") << "\n"446<< " HasCFGHazards: "447<< (P.IsCFGHazardAfflicted()?"true":"false") << "\n"448<< " KnownPositive: "449<< (P.HasKnownPositiveRefCount()?"true":"false") << "\n"450<< " Seq: "451<< P.GetSeq() << "\n";452}453}454455OS << " BottomUp State:\n";456if (!BBInfo.hasBottomUpPtrs()) {457LLVM_DEBUG(dbgs() << " NONE!\n");458} else {459for (auto I = BBInfo.bottom_up_ptr_begin(), E = BBInfo.bottom_up_ptr_end();460I != E; ++I) {461const PtrState &P = I->second;462OS << " Ptr: " << *I->first463<< "\n KnownSafe: " << (P.IsKnownSafe()?"true":"false")464<< "\n ImpreciseRelease: "465<< (P.IsTrackingImpreciseReleases()?"true":"false") << "\n"466<< " HasCFGHazards: "467<< (P.IsCFGHazardAfflicted()?"true":"false") << "\n"468<< " KnownPositive: "469<< (P.HasKnownPositiveRefCount()?"true":"false") << "\n"470<< " Seq: "471<< P.GetSeq() << "\n";472}473}474475return OS;476}477478namespace {479480/// The main ARC optimization pass.481class ObjCARCOpt {482bool Changed = false;483bool CFGChanged = false;484ProvenanceAnalysis PA;485486/// A cache of references to runtime entry point constants.487ARCRuntimeEntryPoints EP;488489/// A cache of MDKinds that can be passed into other functions to propagate490/// MDKind identifiers.491ARCMDKindCache MDKindCache;492493BundledRetainClaimRVs *BundledInsts = nullptr;494495/// A flag indicating whether the optimization that removes or moves496/// retain/release pairs should be performed.497bool DisableRetainReleasePairing = false;498499/// Flags which determine whether each of the interesting runtime functions500/// is in fact used in the current function.501unsigned UsedInThisFunction;502503DenseMap<BasicBlock *, ColorVector> BlockEHColors;504505bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV);506void OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV,507ARCInstKind &Class);508void OptimizeIndividualCalls(Function &F);509510/// Optimize an individual call, optionally passing the511/// GetArgRCIdentityRoot if it has already been computed.512void OptimizeIndividualCallImpl(Function &F, Instruction *Inst,513ARCInstKind Class, const Value *Arg);514515/// Try to optimize an AutoreleaseRV with a RetainRV or UnsafeClaimRV. If the516/// optimization occurs, returns true to indicate that the caller should517/// assume the instructions are dead.518bool OptimizeInlinedAutoreleaseRVCall(Function &F, Instruction *Inst,519const Value *&Arg, ARCInstKind Class,520Instruction *AutoreleaseRV,521const Value *&AutoreleaseRVArg);522523void CheckForCFGHazards(const BasicBlock *BB,524DenseMap<const BasicBlock *, BBState> &BBStates,525BBState &MyStates) const;526bool VisitInstructionBottomUp(Instruction *Inst, BasicBlock *BB,527BlotMapVector<Value *, RRInfo> &Retains,528BBState &MyStates);529bool VisitBottomUp(BasicBlock *BB,530DenseMap<const BasicBlock *, BBState> &BBStates,531BlotMapVector<Value *, RRInfo> &Retains);532bool VisitInstructionTopDown(533Instruction *Inst, DenseMap<Value *, RRInfo> &Releases, BBState &MyStates,534const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>535&ReleaseInsertPtToRCIdentityRoots);536bool VisitTopDown(537BasicBlock *BB, DenseMap<const BasicBlock *, BBState> &BBStates,538DenseMap<Value *, RRInfo> &Releases,539const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>540&ReleaseInsertPtToRCIdentityRoots);541bool Visit(Function &F, DenseMap<const BasicBlock *, BBState> &BBStates,542BlotMapVector<Value *, RRInfo> &Retains,543DenseMap<Value *, RRInfo> &Releases);544545void MoveCalls(Value *Arg, RRInfo &RetainsToMove, RRInfo &ReleasesToMove,546BlotMapVector<Value *, RRInfo> &Retains,547DenseMap<Value *, RRInfo> &Releases,548SmallVectorImpl<Instruction *> &DeadInsts, Module *M);549550bool PairUpRetainsAndReleases(DenseMap<const BasicBlock *, BBState> &BBStates,551BlotMapVector<Value *, RRInfo> &Retains,552DenseMap<Value *, RRInfo> &Releases, Module *M,553Instruction *Retain,554SmallVectorImpl<Instruction *> &DeadInsts,555RRInfo &RetainsToMove, RRInfo &ReleasesToMove,556Value *Arg, bool KnownSafe,557bool &AnyPairsCompletelyEliminated);558559bool PerformCodePlacement(DenseMap<const BasicBlock *, BBState> &BBStates,560BlotMapVector<Value *, RRInfo> &Retains,561DenseMap<Value *, RRInfo> &Releases, Module *M);562563void OptimizeWeakCalls(Function &F);564565bool OptimizeSequences(Function &F);566567void OptimizeReturns(Function &F);568569template <typename PredicateT>570static void cloneOpBundlesIf(CallBase *CI,571SmallVectorImpl<OperandBundleDef> &OpBundles,572PredicateT Predicate) {573for (unsigned I = 0, E = CI->getNumOperandBundles(); I != E; ++I) {574OperandBundleUse B = CI->getOperandBundleAt(I);575if (Predicate(B))576OpBundles.emplace_back(B);577}578}579580void addOpBundleForFunclet(BasicBlock *BB,581SmallVectorImpl<OperandBundleDef> &OpBundles) {582if (!BlockEHColors.empty()) {583const ColorVector &CV = BlockEHColors.find(BB)->second;584assert(CV.size() > 0 && "Uncolored block");585for (BasicBlock *EHPadBB : CV)586if (auto *EHPad = dyn_cast<FuncletPadInst>(EHPadBB->getFirstNonPHI())) {587OpBundles.emplace_back("funclet", EHPad);588return;589}590}591}592593#ifndef NDEBUG594void GatherStatistics(Function &F, bool AfterOptimization = false);595#endif596597public:598void init(Function &F);599bool run(Function &F, AAResults &AA);600bool hasCFGChanged() const { return CFGChanged; }601};602} // end anonymous namespace603604/// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is605/// not a return value.606bool607ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {608// Check for the argument being from an immediately preceding call or invoke.609const Value *Arg = GetArgRCIdentityRoot(RetainRV);610if (const Instruction *Call = dyn_cast<CallBase>(Arg)) {611if (Call->getParent() == RetainRV->getParent()) {612BasicBlock::const_iterator I(Call);613++I;614while (IsNoopInstruction(&*I))615++I;616if (&*I == RetainRV)617return false;618} else if (const InvokeInst *II = dyn_cast<InvokeInst>(Call)) {619BasicBlock *RetainRVParent = RetainRV->getParent();620if (II->getNormalDest() == RetainRVParent) {621BasicBlock::const_iterator I = RetainRVParent->begin();622while (IsNoopInstruction(&*I))623++I;624if (&*I == RetainRV)625return false;626}627}628}629630assert(!BundledInsts->contains(RetainRV) &&631"a bundled retainRV's argument should be a call");632633// Turn it to a plain objc_retain.634Changed = true;635++NumPeeps;636637LLVM_DEBUG(dbgs() << "Transforming objc_retainAutoreleasedReturnValue => "638"objc_retain since the operand is not a return value.\n"639"Old = "640<< *RetainRV << "\n");641642Function *NewDecl = EP.get(ARCRuntimeEntryPointKind::Retain);643cast<CallInst>(RetainRV)->setCalledFunction(NewDecl);644645LLVM_DEBUG(dbgs() << "New = " << *RetainRV << "\n");646647return false;648}649650bool ObjCARCOpt::OptimizeInlinedAutoreleaseRVCall(651Function &F, Instruction *Inst, const Value *&Arg, ARCInstKind Class,652Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg) {653if (BundledInsts->contains(Inst))654return false;655656// Must be in the same basic block.657assert(Inst->getParent() == AutoreleaseRV->getParent());658659// Must operate on the same root.660Arg = GetArgRCIdentityRoot(Inst);661AutoreleaseRVArg = GetArgRCIdentityRoot(AutoreleaseRV);662if (Arg != AutoreleaseRVArg) {663// If there isn't an exact match, check if we have equivalent PHIs.664const PHINode *PN = dyn_cast<PHINode>(Arg);665if (!PN)666return false;667668SmallVector<const Value *, 4> ArgUsers;669getEquivalentPHIs(*PN, ArgUsers);670if (!llvm::is_contained(ArgUsers, AutoreleaseRVArg))671return false;672}673674// Okay, this is a match. Merge them.675++NumPeeps;676LLVM_DEBUG(dbgs() << "Found inlined objc_autoreleaseReturnValue '"677<< *AutoreleaseRV << "' paired with '" << *Inst << "'\n");678679// Delete the RV pair, starting with the AutoreleaseRV.680AutoreleaseRV->replaceAllUsesWith(681cast<CallInst>(AutoreleaseRV)->getArgOperand(0));682Changed = true;683EraseInstruction(AutoreleaseRV);684if (Class == ARCInstKind::RetainRV) {685// AutoreleaseRV and RetainRV cancel out. Delete the RetainRV.686Inst->replaceAllUsesWith(cast<CallInst>(Inst)->getArgOperand(0));687EraseInstruction(Inst);688return true;689}690691// UnsafeClaimRV is a frontend peephole for RetainRV + Release. Since the692// AutoreleaseRV and RetainRV cancel out, replace UnsafeClaimRV with Release.693assert(Class == ARCInstKind::UnsafeClaimRV);694Value *CallArg = cast<CallInst>(Inst)->getArgOperand(0);695CallInst *Release =696CallInst::Create(EP.get(ARCRuntimeEntryPointKind::Release), CallArg, "",697Inst->getIterator());698assert(IsAlwaysTail(ARCInstKind::UnsafeClaimRV) &&699"Expected UnsafeClaimRV to be safe to tail call");700Release->setTailCall();701Inst->replaceAllUsesWith(CallArg);702EraseInstruction(Inst);703704// Run the normal optimizations on Release.705OptimizeIndividualCallImpl(F, Release, ARCInstKind::Release, Arg);706return true;707}708709/// Turn objc_autoreleaseReturnValue into objc_autorelease if the result is not710/// used as a return value.711void ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F,712Instruction *AutoreleaseRV,713ARCInstKind &Class) {714// Check for a return of the pointer value.715const Value *Ptr = GetArgRCIdentityRoot(AutoreleaseRV);716717// If the argument is ConstantPointerNull or UndefValue, its other users718// aren't actually interesting to look at.719if (isa<ConstantData>(Ptr))720return;721722SmallVector<const Value *, 2> Users;723Users.push_back(Ptr);724725// Add PHIs that are equivalent to Ptr to Users.726if (const PHINode *PN = dyn_cast<PHINode>(Ptr))727getEquivalentPHIs(*PN, Users);728729do {730Ptr = Users.pop_back_val();731for (const User *U : Ptr->users()) {732if (isa<ReturnInst>(U) || GetBasicARCInstKind(U) == ARCInstKind::RetainRV)733return;734if (isa<BitCastInst>(U))735Users.push_back(U);736}737} while (!Users.empty());738739Changed = true;740++NumPeeps;741742LLVM_DEBUG(743dbgs() << "Transforming objc_autoreleaseReturnValue => "744"objc_autorelease since its operand is not used as a return "745"value.\n"746"Old = "747<< *AutoreleaseRV << "\n");748749CallInst *AutoreleaseRVCI = cast<CallInst>(AutoreleaseRV);750Function *NewDecl = EP.get(ARCRuntimeEntryPointKind::Autorelease);751AutoreleaseRVCI->setCalledFunction(NewDecl);752AutoreleaseRVCI->setTailCall(false); // Never tail call objc_autorelease.753Class = ARCInstKind::Autorelease;754755LLVM_DEBUG(dbgs() << "New: " << *AutoreleaseRV << "\n");756}757758/// Visit each call, one at a time, and make simplifications without doing any759/// additional analysis.760void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {761LLVM_DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeIndividualCalls ==\n");762// Reset all the flags in preparation for recomputing them.763UsedInThisFunction = 0;764765// Store any delayed AutoreleaseRV intrinsics, so they can be easily paired766// with RetainRV and UnsafeClaimRV.767Instruction *DelayedAutoreleaseRV = nullptr;768const Value *DelayedAutoreleaseRVArg = nullptr;769auto setDelayedAutoreleaseRV = [&](Instruction *AutoreleaseRV) {770assert(!DelayedAutoreleaseRV || !AutoreleaseRV);771DelayedAutoreleaseRV = AutoreleaseRV;772DelayedAutoreleaseRVArg = nullptr;773};774auto optimizeDelayedAutoreleaseRV = [&]() {775if (!DelayedAutoreleaseRV)776return;777OptimizeIndividualCallImpl(F, DelayedAutoreleaseRV,778ARCInstKind::AutoreleaseRV,779DelayedAutoreleaseRVArg);780setDelayedAutoreleaseRV(nullptr);781};782auto shouldDelayAutoreleaseRV = [&](Instruction *NonARCInst) {783// Nothing to delay, but we may as well skip the logic below.784if (!DelayedAutoreleaseRV)785return true;786787// If we hit the end of the basic block we're not going to find an RV-pair.788// Stop delaying.789if (NonARCInst->isTerminator())790return false;791792// Given the frontend rules for emitting AutoreleaseRV, RetainRV, and793// UnsafeClaimRV, it's probably safe to skip over even opaque function calls794// here since OptimizeInlinedAutoreleaseRVCall will confirm that they795// have the same RCIdentityRoot. However, what really matters is796// skipping instructions or intrinsics that the inliner could leave behind;797// be conservative for now and don't skip over opaque calls, which could798// potentially include other ARC calls.799auto *CB = dyn_cast<CallBase>(NonARCInst);800if (!CB)801return true;802return CB->getIntrinsicID() != Intrinsic::not_intrinsic;803};804805// Visit all objc_* calls in F.806for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {807Instruction *Inst = &*I++;808809if (auto *CI = dyn_cast<CallInst>(Inst))810if (objcarc::hasAttachedCallOpBundle(CI)) {811BundledInsts->insertRVCall(I->getIterator(), CI);812Changed = true;813}814815ARCInstKind Class = GetBasicARCInstKind(Inst);816817// Skip this loop if this instruction isn't itself an ARC intrinsic.818const Value *Arg = nullptr;819switch (Class) {820default:821optimizeDelayedAutoreleaseRV();822break;823case ARCInstKind::CallOrUser:824case ARCInstKind::User:825case ARCInstKind::None:826// This is a non-ARC instruction. If we're delaying an AutoreleaseRV,827// check if it's safe to skip over it; if not, optimize the AutoreleaseRV828// now.829if (!shouldDelayAutoreleaseRV(Inst))830optimizeDelayedAutoreleaseRV();831continue;832case ARCInstKind::AutoreleaseRV:833optimizeDelayedAutoreleaseRV();834setDelayedAutoreleaseRV(Inst);835continue;836case ARCInstKind::RetainRV:837case ARCInstKind::UnsafeClaimRV:838if (DelayedAutoreleaseRV) {839// We have a potential RV pair. Check if they cancel out.840if (OptimizeInlinedAutoreleaseRVCall(F, Inst, Arg, Class,841DelayedAutoreleaseRV,842DelayedAutoreleaseRVArg)) {843setDelayedAutoreleaseRV(nullptr);844continue;845}846optimizeDelayedAutoreleaseRV();847}848break;849}850851OptimizeIndividualCallImpl(F, Inst, Class, Arg);852}853854// Catch the final delayed AutoreleaseRV.855optimizeDelayedAutoreleaseRV();856}857858/// This function returns true if the value is inert. An ObjC ARC runtime call859/// taking an inert operand can be safely deleted.860static bool isInertARCValue(Value *V, SmallPtrSet<Value *, 1> &VisitedPhis) {861V = V->stripPointerCasts();862863if (IsNullOrUndef(V))864return true;865866// See if this is a global attribute annotated with an 'objc_arc_inert'.867if (auto *GV = dyn_cast<GlobalVariable>(V))868if (GV->hasAttribute("objc_arc_inert"))869return true;870871if (auto PN = dyn_cast<PHINode>(V)) {872// Ignore this phi if it has already been discovered.873if (!VisitedPhis.insert(PN).second)874return true;875// Look through phis's operands.876for (Value *Opnd : PN->incoming_values())877if (!isInertARCValue(Opnd, VisitedPhis))878return false;879return true;880}881882return false;883}884885void ObjCARCOpt::OptimizeIndividualCallImpl(Function &F, Instruction *Inst,886ARCInstKind Class,887const Value *Arg) {888LLVM_DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n");889890// We can delete this call if it takes an inert value.891SmallPtrSet<Value *, 1> VisitedPhis;892893if (BundledInsts->contains(Inst)) {894UsedInThisFunction |= 1 << unsigned(Class);895return;896}897898if (IsNoopOnGlobal(Class))899if (isInertARCValue(Inst->getOperand(0), VisitedPhis)) {900if (!Inst->getType()->isVoidTy())901Inst->replaceAllUsesWith(Inst->getOperand(0));902Inst->eraseFromParent();903Changed = true;904return;905}906907switch (Class) {908default:909break;910911// Delete no-op casts. These function calls have special semantics, but912// the semantics are entirely implemented via lowering in the front-end,913// so by the time they reach the optimizer, they are just no-op calls914// which return their argument.915//916// There are gray areas here, as the ability to cast reference-counted917// pointers to raw void* and back allows code to break ARC assumptions,918// however these are currently considered to be unimportant.919case ARCInstKind::NoopCast:920Changed = true;921++NumNoops;922LLVM_DEBUG(dbgs() << "Erasing no-op cast: " << *Inst << "\n");923EraseInstruction(Inst);924return;925926// If the pointer-to-weak-pointer is null, it's undefined behavior.927case ARCInstKind::StoreWeak:928case ARCInstKind::LoadWeak:929case ARCInstKind::LoadWeakRetained:930case ARCInstKind::InitWeak:931case ARCInstKind::DestroyWeak: {932CallInst *CI = cast<CallInst>(Inst);933if (IsNullOrUndef(CI->getArgOperand(0))) {934Changed = true;935new StoreInst(ConstantInt::getTrue(CI->getContext()),936PoisonValue::get(PointerType::getUnqual(CI->getContext())),937CI->getIterator());938Value *NewValue = PoisonValue::get(CI->getType());939LLVM_DEBUG(940dbgs() << "A null pointer-to-weak-pointer is undefined behavior."941"\nOld = "942<< *CI << "\nNew = " << *NewValue << "\n");943CI->replaceAllUsesWith(NewValue);944CI->eraseFromParent();945return;946}947break;948}949case ARCInstKind::CopyWeak:950case ARCInstKind::MoveWeak: {951CallInst *CI = cast<CallInst>(Inst);952if (IsNullOrUndef(CI->getArgOperand(0)) ||953IsNullOrUndef(CI->getArgOperand(1))) {954Changed = true;955new StoreInst(ConstantInt::getTrue(CI->getContext()),956PoisonValue::get(PointerType::getUnqual(CI->getContext())),957CI->getIterator());958959Value *NewValue = PoisonValue::get(CI->getType());960LLVM_DEBUG(961dbgs() << "A null pointer-to-weak-pointer is undefined behavior."962"\nOld = "963<< *CI << "\nNew = " << *NewValue << "\n");964965CI->replaceAllUsesWith(NewValue);966CI->eraseFromParent();967return;968}969break;970}971case ARCInstKind::RetainRV:972if (OptimizeRetainRVCall(F, Inst))973return;974break;975case ARCInstKind::AutoreleaseRV:976OptimizeAutoreleaseRVCall(F, Inst, Class);977break;978}979980// objc_autorelease(x) -> objc_release(x) if x is otherwise unused.981if (IsAutorelease(Class) && Inst->use_empty()) {982CallInst *Call = cast<CallInst>(Inst);983const Value *Arg = Call->getArgOperand(0);984Arg = FindSingleUseIdentifiedObject(Arg);985if (Arg) {986Changed = true;987++NumAutoreleases;988989// Create the declaration lazily.990LLVMContext &C = Inst->getContext();991992Function *Decl = EP.get(ARCRuntimeEntryPointKind::Release);993CallInst *NewCall = CallInst::Create(Decl, Call->getArgOperand(0), "",994Call->getIterator());995NewCall->setMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease),996MDNode::get(C, std::nullopt));997998LLVM_DEBUG(dbgs() << "Replacing autorelease{,RV}(x) with objc_release(x) "999"since x is otherwise unused.\nOld: "1000<< *Call << "\nNew: " << *NewCall << "\n");10011002EraseInstruction(Call);1003Inst = NewCall;1004Class = ARCInstKind::Release;1005}1006}10071008// For functions which can never be passed stack arguments, add1009// a tail keyword.1010if (IsAlwaysTail(Class) && !cast<CallInst>(Inst)->isNoTailCall()) {1011Changed = true;1012LLVM_DEBUG(1013dbgs() << "Adding tail keyword to function since it can never be "1014"passed stack args: "1015<< *Inst << "\n");1016cast<CallInst>(Inst)->setTailCall();1017}10181019// Ensure that functions that can never have a "tail" keyword due to the1020// semantics of ARC truly do not do so.1021if (IsNeverTail(Class)) {1022Changed = true;1023LLVM_DEBUG(dbgs() << "Removing tail keyword from function: " << *Inst1024<< "\n");1025cast<CallInst>(Inst)->setTailCall(false);1026}10271028// Set nounwind as needed.1029if (IsNoThrow(Class)) {1030Changed = true;1031LLVM_DEBUG(dbgs() << "Found no throw class. Setting nounwind on: " << *Inst1032<< "\n");1033cast<CallInst>(Inst)->setDoesNotThrow();1034}10351036// Note: This catches instructions unrelated to ARC.1037if (!IsNoopOnNull(Class)) {1038UsedInThisFunction |= 1 << unsigned(Class);1039return;1040}10411042// If we haven't already looked up the root, look it up now.1043if (!Arg)1044Arg = GetArgRCIdentityRoot(Inst);10451046// ARC calls with null are no-ops. Delete them.1047if (IsNullOrUndef(Arg)) {1048Changed = true;1049++NumNoops;1050LLVM_DEBUG(dbgs() << "ARC calls with null are no-ops. Erasing: " << *Inst1051<< "\n");1052EraseInstruction(Inst);1053return;1054}10551056// Keep track of which of retain, release, autorelease, and retain_block1057// are actually present in this function.1058UsedInThisFunction |= 1 << unsigned(Class);10591060// If Arg is a PHI, and one or more incoming values to the1061// PHI are null, and the call is control-equivalent to the PHI, and there1062// are no relevant side effects between the PHI and the call, and the call1063// is not a release that doesn't have the clang.imprecise_release tag, the1064// call could be pushed up to just those paths with non-null incoming1065// values. For now, don't bother splitting critical edges for this.1066if (Class == ARCInstKind::Release &&1067!Inst->getMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease)))1068return;10691070SmallVector<std::pair<Instruction *, const Value *>, 4> Worklist;1071Worklist.push_back(std::make_pair(Inst, Arg));1072do {1073std::pair<Instruction *, const Value *> Pair = Worklist.pop_back_val();1074Inst = Pair.first;1075Arg = Pair.second;10761077const PHINode *PN = dyn_cast<PHINode>(Arg);1078if (!PN)1079continue;10801081// Determine if the PHI has any null operands, or any incoming1082// critical edges.1083bool HasNull = false;1084bool HasCriticalEdges = false;1085for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {1086Value *Incoming = GetRCIdentityRoot(PN->getIncomingValue(i));1087if (IsNullOrUndef(Incoming))1088HasNull = true;1089else if (PN->getIncomingBlock(i)->getTerminator()->getNumSuccessors() !=10901) {1091HasCriticalEdges = true;1092break;1093}1094}1095// If we have null operands and no critical edges, optimize.1096if (HasCriticalEdges)1097continue;1098if (!HasNull)1099continue;11001101Instruction *DepInst = nullptr;11021103// Check that there is nothing that cares about the reference1104// count between the call and the phi.1105switch (Class) {1106case ARCInstKind::Retain:1107case ARCInstKind::RetainBlock:1108// These can always be moved up.1109break;1110case ARCInstKind::Release:1111// These can't be moved across things that care about the retain1112// count.1113DepInst = findSingleDependency(NeedsPositiveRetainCount, Arg,1114Inst->getParent(), Inst, PA);1115break;1116case ARCInstKind::Autorelease:1117// These can't be moved across autorelease pool scope boundaries.1118DepInst = findSingleDependency(AutoreleasePoolBoundary, Arg,1119Inst->getParent(), Inst, PA);1120break;1121case ARCInstKind::UnsafeClaimRV:1122case ARCInstKind::RetainRV:1123case ARCInstKind::AutoreleaseRV:1124// Don't move these; the RV optimization depends on the autoreleaseRV1125// being tail called, and the retainRV being immediately after a call1126// (which might still happen if we get lucky with codegen layout, but1127// it's not worth taking the chance).1128continue;1129default:1130llvm_unreachable("Invalid dependence flavor");1131}11321133if (DepInst != PN)1134continue;11351136Changed = true;1137++NumPartialNoops;1138// Clone the call into each predecessor that has a non-null value.1139CallInst *CInst = cast<CallInst>(Inst);1140Type *ParamTy = CInst->getArgOperand(0)->getType();1141for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {1142Value *Incoming = GetRCIdentityRoot(PN->getIncomingValue(i));1143if (IsNullOrUndef(Incoming))1144continue;1145Value *Op = PN->getIncomingValue(i);1146BasicBlock::iterator InsertPos =1147PN->getIncomingBlock(i)->back().getIterator();1148SmallVector<OperandBundleDef, 1> OpBundles;1149cloneOpBundlesIf(CInst, OpBundles, [](const OperandBundleUse &B) {1150return B.getTagID() != LLVMContext::OB_funclet;1151});1152addOpBundleForFunclet(InsertPos->getParent(), OpBundles);1153CallInst *Clone = CallInst::Create(CInst, OpBundles);1154if (Op->getType() != ParamTy)1155Op = new BitCastInst(Op, ParamTy, "", InsertPos);1156Clone->setArgOperand(0, Op);1157Clone->insertBefore(*InsertPos->getParent(), InsertPos);11581159LLVM_DEBUG(dbgs() << "Cloning " << *CInst << "\n"1160"And inserting clone at "1161<< *InsertPos << "\n");1162Worklist.push_back(std::make_pair(Clone, Incoming));1163}1164// Erase the original call.1165LLVM_DEBUG(dbgs() << "Erasing: " << *CInst << "\n");1166EraseInstruction(CInst);1167} while (!Worklist.empty());1168}11691170/// If we have a top down pointer in the S_Use state, make sure that there are1171/// no CFG hazards by checking the states of various bottom up pointers.1172static void CheckForUseCFGHazard(const Sequence SuccSSeq,1173const bool SuccSRRIKnownSafe,1174TopDownPtrState &S,1175bool &SomeSuccHasSame,1176bool &AllSuccsHaveSame,1177bool &NotAllSeqEqualButKnownSafe,1178bool &ShouldContinue) {1179switch (SuccSSeq) {1180case S_CanRelease: {1181if (!S.IsKnownSafe() && !SuccSRRIKnownSafe) {1182S.ClearSequenceProgress();1183break;1184}1185S.SetCFGHazardAfflicted(true);1186ShouldContinue = true;1187break;1188}1189case S_Use:1190SomeSuccHasSame = true;1191break;1192case S_Stop:1193case S_MovableRelease:1194if (!S.IsKnownSafe() && !SuccSRRIKnownSafe)1195AllSuccsHaveSame = false;1196else1197NotAllSeqEqualButKnownSafe = true;1198break;1199case S_Retain:1200llvm_unreachable("bottom-up pointer in retain state!");1201case S_None:1202llvm_unreachable("This should have been handled earlier.");1203}1204}12051206/// If we have a Top Down pointer in the S_CanRelease state, make sure that1207/// there are no CFG hazards by checking the states of various bottom up1208/// pointers.1209static void CheckForCanReleaseCFGHazard(const Sequence SuccSSeq,1210const bool SuccSRRIKnownSafe,1211TopDownPtrState &S,1212bool &SomeSuccHasSame,1213bool &AllSuccsHaveSame,1214bool &NotAllSeqEqualButKnownSafe) {1215switch (SuccSSeq) {1216case S_CanRelease:1217SomeSuccHasSame = true;1218break;1219case S_Stop:1220case S_MovableRelease:1221case S_Use:1222if (!S.IsKnownSafe() && !SuccSRRIKnownSafe)1223AllSuccsHaveSame = false;1224else1225NotAllSeqEqualButKnownSafe = true;1226break;1227case S_Retain:1228llvm_unreachable("bottom-up pointer in retain state!");1229case S_None:1230llvm_unreachable("This should have been handled earlier.");1231}1232}12331234/// Check for critical edges, loop boundaries, irreducible control flow, or1235/// other CFG structures where moving code across the edge would result in it1236/// being executed more.1237void1238ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,1239DenseMap<const BasicBlock *, BBState> &BBStates,1240BBState &MyStates) const {1241// If any top-down local-use or possible-dec has a succ which is earlier in1242// the sequence, forget it.1243for (auto I = MyStates.top_down_ptr_begin(), E = MyStates.top_down_ptr_end();1244I != E; ++I) {1245TopDownPtrState &S = I->second;1246const Sequence Seq = I->second.GetSeq();12471248// We only care about S_Retain, S_CanRelease, and S_Use.1249if (Seq == S_None)1250continue;12511252// Make sure that if extra top down states are added in the future that this1253// code is updated to handle it.1254assert((Seq == S_Retain || Seq == S_CanRelease || Seq == S_Use) &&1255"Unknown top down sequence state.");12561257const Value *Arg = I->first;1258bool SomeSuccHasSame = false;1259bool AllSuccsHaveSame = true;1260bool NotAllSeqEqualButKnownSafe = false;12611262for (const BasicBlock *Succ : successors(BB)) {1263// If VisitBottomUp has pointer information for this successor, take1264// what we know about it.1265const DenseMap<const BasicBlock *, BBState>::iterator BBI =1266BBStates.find(Succ);1267assert(BBI != BBStates.end());1268const BottomUpPtrState &SuccS = BBI->second.getPtrBottomUpState(Arg);1269const Sequence SuccSSeq = SuccS.GetSeq();12701271// If bottom up, the pointer is in an S_None state, clear the sequence1272// progress since the sequence in the bottom up state finished1273// suggesting a mismatch in between retains/releases. This is true for1274// all three cases that we are handling here: S_Retain, S_Use, and1275// S_CanRelease.1276if (SuccSSeq == S_None) {1277S.ClearSequenceProgress();1278continue;1279}12801281// If we have S_Use or S_CanRelease, perform our check for cfg hazard1282// checks.1283const bool SuccSRRIKnownSafe = SuccS.IsKnownSafe();12841285// *NOTE* We do not use Seq from above here since we are allowing for1286// S.GetSeq() to change while we are visiting basic blocks.1287switch(S.GetSeq()) {1288case S_Use: {1289bool ShouldContinue = false;1290CheckForUseCFGHazard(SuccSSeq, SuccSRRIKnownSafe, S, SomeSuccHasSame,1291AllSuccsHaveSame, NotAllSeqEqualButKnownSafe,1292ShouldContinue);1293if (ShouldContinue)1294continue;1295break;1296}1297case S_CanRelease:1298CheckForCanReleaseCFGHazard(SuccSSeq, SuccSRRIKnownSafe, S,1299SomeSuccHasSame, AllSuccsHaveSame,1300NotAllSeqEqualButKnownSafe);1301break;1302case S_Retain:1303case S_None:1304case S_Stop:1305case S_MovableRelease:1306break;1307}1308}13091310// If the state at the other end of any of the successor edges1311// matches the current state, require all edges to match. This1312// guards against loops in the middle of a sequence.1313if (SomeSuccHasSame && !AllSuccsHaveSame) {1314S.ClearSequenceProgress();1315} else if (NotAllSeqEqualButKnownSafe) {1316// If we would have cleared the state foregoing the fact that we are known1317// safe, stop code motion. This is because whether or not it is safe to1318// remove RR pairs via KnownSafe is an orthogonal concept to whether we1319// are allowed to perform code motion.1320S.SetCFGHazardAfflicted(true);1321}1322}1323}13241325bool ObjCARCOpt::VisitInstructionBottomUp(1326Instruction *Inst, BasicBlock *BB, BlotMapVector<Value *, RRInfo> &Retains,1327BBState &MyStates) {1328bool NestingDetected = false;1329ARCInstKind Class = GetARCInstKind(Inst);1330const Value *Arg = nullptr;13311332LLVM_DEBUG(dbgs() << " Class: " << Class << "\n");13331334switch (Class) {1335case ARCInstKind::Release: {1336Arg = GetArgRCIdentityRoot(Inst);13371338BottomUpPtrState &S = MyStates.getPtrBottomUpState(Arg);1339NestingDetected |= S.InitBottomUp(MDKindCache, Inst);1340break;1341}1342case ARCInstKind::RetainBlock:1343// In OptimizeIndividualCalls, we have strength reduced all optimizable1344// objc_retainBlocks to objc_retains. Thus at this point any1345// objc_retainBlocks that we see are not optimizable.1346break;1347case ARCInstKind::Retain:1348case ARCInstKind::RetainRV: {1349Arg = GetArgRCIdentityRoot(Inst);1350BottomUpPtrState &S = MyStates.getPtrBottomUpState(Arg);1351if (S.MatchWithRetain()) {1352// Don't do retain+release tracking for ARCInstKind::RetainRV, because1353// it's better to let it remain as the first instruction after a call.1354if (Class != ARCInstKind::RetainRV) {1355LLVM_DEBUG(dbgs() << " Matching with: " << *Inst << "\n");1356Retains[Inst] = S.GetRRInfo();1357}1358S.ClearSequenceProgress();1359}1360// A retain moving bottom up can be a use.1361break;1362}1363case ARCInstKind::AutoreleasepoolPop:1364// Conservatively, clear MyStates for all known pointers.1365MyStates.clearBottomUpPointers();1366return NestingDetected;1367case ARCInstKind::AutoreleasepoolPush:1368case ARCInstKind::None:1369// These are irrelevant.1370return NestingDetected;1371default:1372break;1373}13741375// Consider any other possible effects of this instruction on each1376// pointer being tracked.1377for (auto MI = MyStates.bottom_up_ptr_begin(),1378ME = MyStates.bottom_up_ptr_end();1379MI != ME; ++MI) {1380const Value *Ptr = MI->first;1381if (Ptr == Arg)1382continue; // Handled above.1383BottomUpPtrState &S = MI->second;13841385if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class))1386continue;13871388S.HandlePotentialUse(BB, Inst, Ptr, PA, Class);1389}13901391return NestingDetected;1392}13931394bool ObjCARCOpt::VisitBottomUp(BasicBlock *BB,1395DenseMap<const BasicBlock *, BBState> &BBStates,1396BlotMapVector<Value *, RRInfo> &Retains) {1397LLVM_DEBUG(dbgs() << "\n== ObjCARCOpt::VisitBottomUp ==\n");13981399bool NestingDetected = false;1400BBState &MyStates = BBStates[BB];14011402// Merge the states from each successor to compute the initial state1403// for the current block.1404BBState::edge_iterator SI(MyStates.succ_begin()),1405SE(MyStates.succ_end());1406if (SI != SE) {1407const BasicBlock *Succ = *SI;1408DenseMap<const BasicBlock *, BBState>::iterator I = BBStates.find(Succ);1409assert(I != BBStates.end());1410MyStates.InitFromSucc(I->second);1411++SI;1412for (; SI != SE; ++SI) {1413Succ = *SI;1414I = BBStates.find(Succ);1415assert(I != BBStates.end());1416MyStates.MergeSucc(I->second);1417}1418}14191420LLVM_DEBUG(dbgs() << "Before:\n"1421<< BBStates[BB] << "\n"1422<< "Performing Dataflow:\n");14231424// Visit all the instructions, bottom-up.1425for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; --I) {1426Instruction *Inst = &*std::prev(I);14271428// Invoke instructions are visited as part of their successors (below).1429if (isa<InvokeInst>(Inst))1430continue;14311432LLVM_DEBUG(dbgs() << " Visiting " << *Inst << "\n");14331434NestingDetected |= VisitInstructionBottomUp(Inst, BB, Retains, MyStates);14351436// Bail out if the number of pointers being tracked becomes too large so1437// that this pass can complete in a reasonable amount of time.1438if (MyStates.bottom_up_ptr_list_size() > MaxPtrStates) {1439DisableRetainReleasePairing = true;1440return false;1441}1442}14431444// If there's a predecessor with an invoke, visit the invoke as if it were1445// part of this block, since we can't insert code after an invoke in its own1446// block, and we don't want to split critical edges.1447for (BBState::edge_iterator PI(MyStates.pred_begin()),1448PE(MyStates.pred_end()); PI != PE; ++PI) {1449BasicBlock *Pred = *PI;1450if (InvokeInst *II = dyn_cast<InvokeInst>(&Pred->back()))1451NestingDetected |= VisitInstructionBottomUp(II, BB, Retains, MyStates);1452}14531454LLVM_DEBUG(dbgs() << "\nFinal State:\n" << BBStates[BB] << "\n");14551456return NestingDetected;1457}14581459// Fill ReleaseInsertPtToRCIdentityRoots, which is a map from insertion points1460// to the set of RC identity roots that would be released by the release calls1461// moved to the insertion points.1462static void collectReleaseInsertPts(1463const BlotMapVector<Value *, RRInfo> &Retains,1464DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>1465&ReleaseInsertPtToRCIdentityRoots) {1466for (const auto &P : Retains) {1467// Retains is a map from an objc_retain call to a RRInfo of the RC identity1468// root of the call. Get the RC identity root of the objc_retain call.1469Instruction *Retain = cast<Instruction>(P.first);1470Value *Root = GetRCIdentityRoot(Retain->getOperand(0));1471// Collect all the insertion points of the objc_release calls that release1472// the RC identity root of the objc_retain call.1473for (const Instruction *InsertPt : P.second.ReverseInsertPts)1474ReleaseInsertPtToRCIdentityRoots[InsertPt].insert(Root);1475}1476}14771478// Get the RC identity roots from an insertion point of an objc_release call.1479// Return nullptr if the passed instruction isn't an insertion point.1480static const SmallPtrSet<const Value *, 2> *1481getRCIdentityRootsFromReleaseInsertPt(1482const Instruction *InsertPt,1483const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>1484&ReleaseInsertPtToRCIdentityRoots) {1485auto I = ReleaseInsertPtToRCIdentityRoots.find(InsertPt);1486if (I == ReleaseInsertPtToRCIdentityRoots.end())1487return nullptr;1488return &I->second;1489}14901491bool ObjCARCOpt::VisitInstructionTopDown(1492Instruction *Inst, DenseMap<Value *, RRInfo> &Releases, BBState &MyStates,1493const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>1494&ReleaseInsertPtToRCIdentityRoots) {1495bool NestingDetected = false;1496ARCInstKind Class = GetARCInstKind(Inst);1497const Value *Arg = nullptr;14981499// Make sure a call to objc_retain isn't moved past insertion points of calls1500// to objc_release.1501if (const SmallPtrSet<const Value *, 2> *Roots =1502getRCIdentityRootsFromReleaseInsertPt(1503Inst, ReleaseInsertPtToRCIdentityRoots))1504for (const auto *Root : *Roots) {1505TopDownPtrState &S = MyStates.getPtrTopDownState(Root);1506// Disable code motion if the current position is S_Retain to prevent1507// moving the objc_retain call past objc_release calls. If it's1508// S_CanRelease or larger, it's not necessary to disable code motion as1509// the insertion points that prevent the objc_retain call from moving down1510// should have been set already.1511if (S.GetSeq() == S_Retain)1512S.SetCFGHazardAfflicted(true);1513}15141515LLVM_DEBUG(dbgs() << " Class: " << Class << "\n");15161517switch (Class) {1518case ARCInstKind::RetainBlock:1519// In OptimizeIndividualCalls, we have strength reduced all optimizable1520// objc_retainBlocks to objc_retains. Thus at this point any1521// objc_retainBlocks that we see are not optimizable. We need to break since1522// a retain can be a potential use.1523break;1524case ARCInstKind::Retain:1525case ARCInstKind::RetainRV: {1526Arg = GetArgRCIdentityRoot(Inst);1527TopDownPtrState &S = MyStates.getPtrTopDownState(Arg);1528NestingDetected |= S.InitTopDown(Class, Inst);1529// A retain can be a potential use; proceed to the generic checking1530// code below.1531break;1532}1533case ARCInstKind::Release: {1534Arg = GetArgRCIdentityRoot(Inst);1535TopDownPtrState &S = MyStates.getPtrTopDownState(Arg);1536// Try to form a tentative pair in between this release instruction and the1537// top down pointers that we are tracking.1538if (S.MatchWithRelease(MDKindCache, Inst)) {1539// If we succeed, copy S's RRInfo into the Release -> {Retain Set1540// Map}. Then we clear S.1541LLVM_DEBUG(dbgs() << " Matching with: " << *Inst << "\n");1542Releases[Inst] = S.GetRRInfo();1543S.ClearSequenceProgress();1544}1545break;1546}1547case ARCInstKind::AutoreleasepoolPop:1548// Conservatively, clear MyStates for all known pointers.1549MyStates.clearTopDownPointers();1550return false;1551case ARCInstKind::AutoreleasepoolPush:1552case ARCInstKind::None:1553// These can not be uses of1554return false;1555default:1556break;1557}15581559// Consider any other possible effects of this instruction on each1560// pointer being tracked.1561for (auto MI = MyStates.top_down_ptr_begin(),1562ME = MyStates.top_down_ptr_end();1563MI != ME; ++MI) {1564const Value *Ptr = MI->first;1565if (Ptr == Arg)1566continue; // Handled above.1567TopDownPtrState &S = MI->second;1568if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class, *BundledInsts))1569continue;15701571S.HandlePotentialUse(Inst, Ptr, PA, Class);1572}15731574return NestingDetected;1575}15761577bool ObjCARCOpt::VisitTopDown(1578BasicBlock *BB, DenseMap<const BasicBlock *, BBState> &BBStates,1579DenseMap<Value *, RRInfo> &Releases,1580const DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>1581&ReleaseInsertPtToRCIdentityRoots) {1582LLVM_DEBUG(dbgs() << "\n== ObjCARCOpt::VisitTopDown ==\n");1583bool NestingDetected = false;1584BBState &MyStates = BBStates[BB];15851586// Merge the states from each predecessor to compute the initial state1587// for the current block.1588BBState::edge_iterator PI(MyStates.pred_begin()),1589PE(MyStates.pred_end());1590if (PI != PE) {1591const BasicBlock *Pred = *PI;1592DenseMap<const BasicBlock *, BBState>::iterator I = BBStates.find(Pred);1593assert(I != BBStates.end());1594MyStates.InitFromPred(I->second);1595++PI;1596for (; PI != PE; ++PI) {1597Pred = *PI;1598I = BBStates.find(Pred);1599assert(I != BBStates.end());1600MyStates.MergePred(I->second);1601}1602}16031604// Check that BB and MyStates have the same number of predecessors. This1605// prevents retain calls that live outside a loop from being moved into the1606// loop.1607if (!BB->hasNPredecessors(MyStates.pred_end() - MyStates.pred_begin()))1608for (auto I = MyStates.top_down_ptr_begin(),1609E = MyStates.top_down_ptr_end();1610I != E; ++I)1611I->second.SetCFGHazardAfflicted(true);16121613LLVM_DEBUG(dbgs() << "Before:\n"1614<< BBStates[BB] << "\n"1615<< "Performing Dataflow:\n");16161617// Visit all the instructions, top-down.1618for (Instruction &Inst : *BB) {1619LLVM_DEBUG(dbgs() << " Visiting " << Inst << "\n");16201621NestingDetected |= VisitInstructionTopDown(1622&Inst, Releases, MyStates, ReleaseInsertPtToRCIdentityRoots);16231624// Bail out if the number of pointers being tracked becomes too large so1625// that this pass can complete in a reasonable amount of time.1626if (MyStates.top_down_ptr_list_size() > MaxPtrStates) {1627DisableRetainReleasePairing = true;1628return false;1629}1630}16311632LLVM_DEBUG(dbgs() << "\nState Before Checking for CFG Hazards:\n"1633<< BBStates[BB] << "\n\n");1634CheckForCFGHazards(BB, BBStates, MyStates);1635LLVM_DEBUG(dbgs() << "Final State:\n" << BBStates[BB] << "\n");1636return NestingDetected;1637}16381639static void1640ComputePostOrders(Function &F,1641SmallVectorImpl<BasicBlock *> &PostOrder,1642SmallVectorImpl<BasicBlock *> &ReverseCFGPostOrder,1643unsigned NoObjCARCExceptionsMDKind,1644DenseMap<const BasicBlock *, BBState> &BBStates) {1645/// The visited set, for doing DFS walks.1646SmallPtrSet<BasicBlock *, 16> Visited;16471648// Do DFS, computing the PostOrder.1649SmallPtrSet<BasicBlock *, 16> OnStack;1650SmallVector<std::pair<BasicBlock *, succ_iterator>, 16> SuccStack;16511652// Functions always have exactly one entry block, and we don't have1653// any other block that we treat like an entry block.1654BasicBlock *EntryBB = &F.getEntryBlock();1655BBState &MyStates = BBStates[EntryBB];1656MyStates.SetAsEntry();1657Instruction *EntryTI = EntryBB->getTerminator();1658SuccStack.push_back(std::make_pair(EntryBB, succ_iterator(EntryTI)));1659Visited.insert(EntryBB);1660OnStack.insert(EntryBB);1661do {1662dfs_next_succ:1663BasicBlock *CurrBB = SuccStack.back().first;1664succ_iterator SE(CurrBB->getTerminator(), false);16651666while (SuccStack.back().second != SE) {1667BasicBlock *SuccBB = *SuccStack.back().second++;1668if (Visited.insert(SuccBB).second) {1669SuccStack.push_back(1670std::make_pair(SuccBB, succ_iterator(SuccBB->getTerminator())));1671BBStates[CurrBB].addSucc(SuccBB);1672BBState &SuccStates = BBStates[SuccBB];1673SuccStates.addPred(CurrBB);1674OnStack.insert(SuccBB);1675goto dfs_next_succ;1676}16771678if (!OnStack.count(SuccBB)) {1679BBStates[CurrBB].addSucc(SuccBB);1680BBStates[SuccBB].addPred(CurrBB);1681}1682}1683OnStack.erase(CurrBB);1684PostOrder.push_back(CurrBB);1685SuccStack.pop_back();1686} while (!SuccStack.empty());16871688Visited.clear();16891690// Do reverse-CFG DFS, computing the reverse-CFG PostOrder.1691// Functions may have many exits, and there also blocks which we treat1692// as exits due to ignored edges.1693SmallVector<std::pair<BasicBlock *, BBState::edge_iterator>, 16> PredStack;1694for (BasicBlock &ExitBB : F) {1695BBState &MyStates = BBStates[&ExitBB];1696if (!MyStates.isExit())1697continue;16981699MyStates.SetAsExit();17001701PredStack.push_back(std::make_pair(&ExitBB, MyStates.pred_begin()));1702Visited.insert(&ExitBB);1703while (!PredStack.empty()) {1704reverse_dfs_next_succ:1705BBState::edge_iterator PE = BBStates[PredStack.back().first].pred_end();1706while (PredStack.back().second != PE) {1707BasicBlock *BB = *PredStack.back().second++;1708if (Visited.insert(BB).second) {1709PredStack.push_back(std::make_pair(BB, BBStates[BB].pred_begin()));1710goto reverse_dfs_next_succ;1711}1712}1713ReverseCFGPostOrder.push_back(PredStack.pop_back_val().first);1714}1715}1716}17171718// Visit the function both top-down and bottom-up.1719bool ObjCARCOpt::Visit(Function &F,1720DenseMap<const BasicBlock *, BBState> &BBStates,1721BlotMapVector<Value *, RRInfo> &Retains,1722DenseMap<Value *, RRInfo> &Releases) {1723// Use reverse-postorder traversals, because we magically know that loops1724// will be well behaved, i.e. they won't repeatedly call retain on a single1725// pointer without doing a release. We can't use the ReversePostOrderTraversal1726// class here because we want the reverse-CFG postorder to consider each1727// function exit point, and we want to ignore selected cycle edges.1728SmallVector<BasicBlock *, 16> PostOrder;1729SmallVector<BasicBlock *, 16> ReverseCFGPostOrder;1730ComputePostOrders(F, PostOrder, ReverseCFGPostOrder,1731MDKindCache.get(ARCMDKindID::NoObjCARCExceptions),1732BBStates);17331734// Use reverse-postorder on the reverse CFG for bottom-up.1735bool BottomUpNestingDetected = false;1736for (BasicBlock *BB : llvm::reverse(ReverseCFGPostOrder)) {1737BottomUpNestingDetected |= VisitBottomUp(BB, BBStates, Retains);1738if (DisableRetainReleasePairing)1739return false;1740}17411742DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>>1743ReleaseInsertPtToRCIdentityRoots;1744collectReleaseInsertPts(Retains, ReleaseInsertPtToRCIdentityRoots);17451746// Use reverse-postorder for top-down.1747bool TopDownNestingDetected = false;1748for (BasicBlock *BB : llvm::reverse(PostOrder)) {1749TopDownNestingDetected |=1750VisitTopDown(BB, BBStates, Releases, ReleaseInsertPtToRCIdentityRoots);1751if (DisableRetainReleasePairing)1752return false;1753}17541755return TopDownNestingDetected && BottomUpNestingDetected;1756}17571758/// Move the calls in RetainsToMove and ReleasesToMove.1759void ObjCARCOpt::MoveCalls(Value *Arg, RRInfo &RetainsToMove,1760RRInfo &ReleasesToMove,1761BlotMapVector<Value *, RRInfo> &Retains,1762DenseMap<Value *, RRInfo> &Releases,1763SmallVectorImpl<Instruction *> &DeadInsts,1764Module *M) {1765Type *ArgTy = Arg->getType();1766Type *ParamTy = PointerType::getUnqual(Type::getInt8Ty(ArgTy->getContext()));17671768LLVM_DEBUG(dbgs() << "== ObjCARCOpt::MoveCalls ==\n");17691770// Insert the new retain and release calls.1771for (Instruction *InsertPt : ReleasesToMove.ReverseInsertPts) {1772Value *MyArg = ArgTy == ParamTy ? Arg1773: new BitCastInst(Arg, ParamTy, "",1774InsertPt->getIterator());1775Function *Decl = EP.get(ARCRuntimeEntryPointKind::Retain);1776SmallVector<OperandBundleDef, 1> BundleList;1777addOpBundleForFunclet(InsertPt->getParent(), BundleList);1778CallInst *Call =1779CallInst::Create(Decl, MyArg, BundleList, "", InsertPt->getIterator());1780Call->setDoesNotThrow();1781Call->setTailCall();17821783LLVM_DEBUG(dbgs() << "Inserting new Retain: " << *Call1784<< "\n"1785"At insertion point: "1786<< *InsertPt << "\n");1787}1788for (Instruction *InsertPt : RetainsToMove.ReverseInsertPts) {1789Value *MyArg = ArgTy == ParamTy ? Arg1790: new BitCastInst(Arg, ParamTy, "",1791InsertPt->getIterator());1792Function *Decl = EP.get(ARCRuntimeEntryPointKind::Release);1793SmallVector<OperandBundleDef, 1> BundleList;1794addOpBundleForFunclet(InsertPt->getParent(), BundleList);1795CallInst *Call =1796CallInst::Create(Decl, MyArg, BundleList, "", InsertPt->getIterator());1797// Attach a clang.imprecise_release metadata tag, if appropriate.1798if (MDNode *M = ReleasesToMove.ReleaseMetadata)1799Call->setMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease), M);1800Call->setDoesNotThrow();1801if (ReleasesToMove.IsTailCallRelease)1802Call->setTailCall();18031804LLVM_DEBUG(dbgs() << "Inserting new Release: " << *Call1805<< "\n"1806"At insertion point: "1807<< *InsertPt << "\n");1808}18091810// Delete the original retain and release calls.1811for (Instruction *OrigRetain : RetainsToMove.Calls) {1812Retains.blot(OrigRetain);1813DeadInsts.push_back(OrigRetain);1814LLVM_DEBUG(dbgs() << "Deleting retain: " << *OrigRetain << "\n");1815}1816for (Instruction *OrigRelease : ReleasesToMove.Calls) {1817Releases.erase(OrigRelease);1818DeadInsts.push_back(OrigRelease);1819LLVM_DEBUG(dbgs() << "Deleting release: " << *OrigRelease << "\n");1820}1821}18221823bool ObjCARCOpt::PairUpRetainsAndReleases(1824DenseMap<const BasicBlock *, BBState> &BBStates,1825BlotMapVector<Value *, RRInfo> &Retains,1826DenseMap<Value *, RRInfo> &Releases, Module *M,1827Instruction *Retain,1828SmallVectorImpl<Instruction *> &DeadInsts, RRInfo &RetainsToMove,1829RRInfo &ReleasesToMove, Value *Arg, bool KnownSafe,1830bool &AnyPairsCompletelyEliminated) {1831// If a pair happens in a region where it is known that the reference count1832// is already incremented, we can similarly ignore possible decrements unless1833// we are dealing with a retainable object with multiple provenance sources.1834bool KnownSafeTD = true, KnownSafeBU = true;1835bool CFGHazardAfflicted = false;18361837// Connect the dots between the top-down-collected RetainsToMove and1838// bottom-up-collected ReleasesToMove to form sets of related calls.1839// This is an iterative process so that we connect multiple releases1840// to multiple retains if needed.1841unsigned OldDelta = 0;1842unsigned NewDelta = 0;1843unsigned OldCount = 0;1844unsigned NewCount = 0;1845bool FirstRelease = true;1846for (SmallVector<Instruction *, 4> NewRetains{Retain};;) {1847SmallVector<Instruction *, 4> NewReleases;1848for (Instruction *NewRetain : NewRetains) {1849auto It = Retains.find(NewRetain);1850assert(It != Retains.end());1851const RRInfo &NewRetainRRI = It->second;1852KnownSafeTD &= NewRetainRRI.KnownSafe;1853CFGHazardAfflicted |= NewRetainRRI.CFGHazardAfflicted;1854for (Instruction *NewRetainRelease : NewRetainRRI.Calls) {1855auto Jt = Releases.find(NewRetainRelease);1856if (Jt == Releases.end())1857return false;1858const RRInfo &NewRetainReleaseRRI = Jt->second;18591860// If the release does not have a reference to the retain as well,1861// something happened which is unaccounted for. Do not do anything.1862//1863// This can happen if we catch an additive overflow during path count1864// merging.1865if (!NewRetainReleaseRRI.Calls.count(NewRetain))1866return false;18671868if (ReleasesToMove.Calls.insert(NewRetainRelease).second) {1869// If we overflow when we compute the path count, don't remove/move1870// anything.1871const BBState &NRRBBState = BBStates[NewRetainRelease->getParent()];1872unsigned PathCount = BBState::OverflowOccurredValue;1873if (NRRBBState.GetAllPathCountWithOverflow(PathCount))1874return false;1875assert(PathCount != BBState::OverflowOccurredValue &&1876"PathCount at this point can not be "1877"OverflowOccurredValue.");1878OldDelta -= PathCount;18791880// Merge the ReleaseMetadata and IsTailCallRelease values.1881if (FirstRelease) {1882ReleasesToMove.ReleaseMetadata =1883NewRetainReleaseRRI.ReleaseMetadata;1884ReleasesToMove.IsTailCallRelease =1885NewRetainReleaseRRI.IsTailCallRelease;1886FirstRelease = false;1887} else {1888if (ReleasesToMove.ReleaseMetadata !=1889NewRetainReleaseRRI.ReleaseMetadata)1890ReleasesToMove.ReleaseMetadata = nullptr;1891if (ReleasesToMove.IsTailCallRelease !=1892NewRetainReleaseRRI.IsTailCallRelease)1893ReleasesToMove.IsTailCallRelease = false;1894}18951896// Collect the optimal insertion points.1897if (!KnownSafe)1898for (Instruction *RIP : NewRetainReleaseRRI.ReverseInsertPts) {1899if (ReleasesToMove.ReverseInsertPts.insert(RIP).second) {1900// If we overflow when we compute the path count, don't1901// remove/move anything.1902const BBState &RIPBBState = BBStates[RIP->getParent()];1903PathCount = BBState::OverflowOccurredValue;1904if (RIPBBState.GetAllPathCountWithOverflow(PathCount))1905return false;1906assert(PathCount != BBState::OverflowOccurredValue &&1907"PathCount at this point can not be "1908"OverflowOccurredValue.");1909NewDelta -= PathCount;1910}1911}1912NewReleases.push_back(NewRetainRelease);1913}1914}1915}1916NewRetains.clear();1917if (NewReleases.empty()) break;19181919// Back the other way.1920for (Instruction *NewRelease : NewReleases) {1921auto It = Releases.find(NewRelease);1922assert(It != Releases.end());1923const RRInfo &NewReleaseRRI = It->second;1924KnownSafeBU &= NewReleaseRRI.KnownSafe;1925CFGHazardAfflicted |= NewReleaseRRI.CFGHazardAfflicted;1926for (Instruction *NewReleaseRetain : NewReleaseRRI.Calls) {1927auto Jt = Retains.find(NewReleaseRetain);1928if (Jt == Retains.end())1929return false;1930const RRInfo &NewReleaseRetainRRI = Jt->second;19311932// If the retain does not have a reference to the release as well,1933// something happened which is unaccounted for. Do not do anything.1934//1935// This can happen if we catch an additive overflow during path count1936// merging.1937if (!NewReleaseRetainRRI.Calls.count(NewRelease))1938return false;19391940if (RetainsToMove.Calls.insert(NewReleaseRetain).second) {1941// If we overflow when we compute the path count, don't remove/move1942// anything.1943const BBState &NRRBBState = BBStates[NewReleaseRetain->getParent()];1944unsigned PathCount = BBState::OverflowOccurredValue;1945if (NRRBBState.GetAllPathCountWithOverflow(PathCount))1946return false;1947assert(PathCount != BBState::OverflowOccurredValue &&1948"PathCount at this point can not be "1949"OverflowOccurredValue.");1950OldDelta += PathCount;1951OldCount += PathCount;19521953// Collect the optimal insertion points.1954if (!KnownSafe)1955for (Instruction *RIP : NewReleaseRetainRRI.ReverseInsertPts) {1956if (RetainsToMove.ReverseInsertPts.insert(RIP).second) {1957// If we overflow when we compute the path count, don't1958// remove/move anything.1959const BBState &RIPBBState = BBStates[RIP->getParent()];19601961PathCount = BBState::OverflowOccurredValue;1962if (RIPBBState.GetAllPathCountWithOverflow(PathCount))1963return false;1964assert(PathCount != BBState::OverflowOccurredValue &&1965"PathCount at this point can not be "1966"OverflowOccurredValue.");1967NewDelta += PathCount;1968NewCount += PathCount;1969}1970}1971NewRetains.push_back(NewReleaseRetain);1972}1973}1974}1975if (NewRetains.empty()) break;1976}19771978// We can only remove pointers if we are known safe in both directions.1979bool UnconditionallySafe = KnownSafeTD && KnownSafeBU;1980if (UnconditionallySafe) {1981RetainsToMove.ReverseInsertPts.clear();1982ReleasesToMove.ReverseInsertPts.clear();1983NewCount = 0;1984} else {1985// Determine whether the new insertion points we computed preserve the1986// balance of retain and release calls through the program.1987// TODO: If the fully aggressive solution isn't valid, try to find a1988// less aggressive solution which is.1989if (NewDelta != 0)1990return false;19911992// At this point, we are not going to remove any RR pairs, but we still are1993// able to move RR pairs. If one of our pointers is afflicted with1994// CFGHazards, we cannot perform such code motion so exit early.1995const bool WillPerformCodeMotion =1996!RetainsToMove.ReverseInsertPts.empty() ||1997!ReleasesToMove.ReverseInsertPts.empty();1998if (CFGHazardAfflicted && WillPerformCodeMotion)1999return false;2000}20012002// Determine whether the original call points are balanced in the retain and2003// release calls through the program. If not, conservatively don't touch2004// them.2005// TODO: It's theoretically possible to do code motion in this case, as2006// long as the existing imbalances are maintained.2007if (OldDelta != 0)2008return false;20092010Changed = true;2011assert(OldCount != 0 && "Unreachable code?");2012NumRRs += OldCount - NewCount;2013// Set to true if we completely removed any RR pairs.2014AnyPairsCompletelyEliminated = NewCount == 0;20152016// We can move calls!2017return true;2018}20192020/// Identify pairings between the retains and releases, and delete and/or move2021/// them.2022bool ObjCARCOpt::PerformCodePlacement(2023DenseMap<const BasicBlock *, BBState> &BBStates,2024BlotMapVector<Value *, RRInfo> &Retains,2025DenseMap<Value *, RRInfo> &Releases, Module *M) {2026LLVM_DEBUG(dbgs() << "\n== ObjCARCOpt::PerformCodePlacement ==\n");20272028bool AnyPairsCompletelyEliminated = false;2029SmallVector<Instruction *, 8> DeadInsts;20302031// Visit each retain.2032for (BlotMapVector<Value *, RRInfo>::const_iterator I = Retains.begin(),2033E = Retains.end();2034I != E; ++I) {2035Value *V = I->first;2036if (!V) continue; // blotted20372038Instruction *Retain = cast<Instruction>(V);20392040LLVM_DEBUG(dbgs() << "Visiting: " << *Retain << "\n");20412042Value *Arg = GetArgRCIdentityRoot(Retain);20432044// If the object being released is in static or stack storage, we know it's2045// not being managed by ObjC reference counting, so we can delete pairs2046// regardless of what possible decrements or uses lie between them.2047bool KnownSafe = isa<Constant>(Arg) || isa<AllocaInst>(Arg);20482049// A constant pointer can't be pointing to an object on the heap. It may2050// be reference-counted, but it won't be deleted.2051if (const LoadInst *LI = dyn_cast<LoadInst>(Arg))2052if (const GlobalVariable *GV =2053dyn_cast<GlobalVariable>(2054GetRCIdentityRoot(LI->getPointerOperand())))2055if (GV->isConstant())2056KnownSafe = true;20572058// Connect the dots between the top-down-collected RetainsToMove and2059// bottom-up-collected ReleasesToMove to form sets of related calls.2060RRInfo RetainsToMove, ReleasesToMove;20612062bool PerformMoveCalls = PairUpRetainsAndReleases(2063BBStates, Retains, Releases, M, Retain, DeadInsts,2064RetainsToMove, ReleasesToMove, Arg, KnownSafe,2065AnyPairsCompletelyEliminated);20662067if (PerformMoveCalls) {2068// Ok, everything checks out and we're all set. Let's move/delete some2069// code!2070MoveCalls(Arg, RetainsToMove, ReleasesToMove,2071Retains, Releases, DeadInsts, M);2072}2073}20742075// Now that we're done moving everything, we can delete the newly dead2076// instructions, as we no longer need them as insert points.2077while (!DeadInsts.empty())2078EraseInstruction(DeadInsts.pop_back_val());20792080return AnyPairsCompletelyEliminated;2081}20822083/// Weak pointer optimizations.2084void ObjCARCOpt::OptimizeWeakCalls(Function &F) {2085LLVM_DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeWeakCalls ==\n");20862087// First, do memdep-style RLE and S2L optimizations. We can't use memdep2088// itself because it uses AliasAnalysis and we need to do provenance2089// queries instead.2090for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {2091Instruction *Inst = &*I++;20922093LLVM_DEBUG(dbgs() << "Visiting: " << *Inst << "\n");20942095ARCInstKind Class = GetBasicARCInstKind(Inst);2096if (Class != ARCInstKind::LoadWeak &&2097Class != ARCInstKind::LoadWeakRetained)2098continue;20992100// Delete objc_loadWeak calls with no users.2101if (Class == ARCInstKind::LoadWeak && Inst->use_empty()) {2102Inst->eraseFromParent();2103Changed = true;2104continue;2105}21062107// TODO: For now, just look for an earlier available version of this value2108// within the same block. Theoretically, we could do memdep-style non-local2109// analysis too, but that would want caching. A better approach would be to2110// use the technique that EarlyCSE uses.2111inst_iterator Current = std::prev(I);2112BasicBlock *CurrentBB = &*Current.getBasicBlockIterator();2113for (BasicBlock::iterator B = CurrentBB->begin(),2114J = Current.getInstructionIterator();2115J != B; --J) {2116Instruction *EarlierInst = &*std::prev(J);2117ARCInstKind EarlierClass = GetARCInstKind(EarlierInst);2118switch (EarlierClass) {2119case ARCInstKind::LoadWeak:2120case ARCInstKind::LoadWeakRetained: {2121// If this is loading from the same pointer, replace this load's value2122// with that one.2123CallInst *Call = cast<CallInst>(Inst);2124CallInst *EarlierCall = cast<CallInst>(EarlierInst);2125Value *Arg = Call->getArgOperand(0);2126Value *EarlierArg = EarlierCall->getArgOperand(0);2127switch (PA.getAA()->alias(Arg, EarlierArg)) {2128case AliasResult::MustAlias:2129Changed = true;2130// If the load has a builtin retain, insert a plain retain for it.2131if (Class == ARCInstKind::LoadWeakRetained) {2132Function *Decl = EP.get(ARCRuntimeEntryPointKind::Retain);2133CallInst *CI =2134CallInst::Create(Decl, EarlierCall, "", Call->getIterator());2135CI->setTailCall();2136}2137// Zap the fully redundant load.2138Call->replaceAllUsesWith(EarlierCall);2139Call->eraseFromParent();2140goto clobbered;2141case AliasResult::MayAlias:2142case AliasResult::PartialAlias:2143goto clobbered;2144case AliasResult::NoAlias:2145break;2146}2147break;2148}2149case ARCInstKind::StoreWeak:2150case ARCInstKind::InitWeak: {2151// If this is storing to the same pointer and has the same size etc.2152// replace this load's value with the stored value.2153CallInst *Call = cast<CallInst>(Inst);2154CallInst *EarlierCall = cast<CallInst>(EarlierInst);2155Value *Arg = Call->getArgOperand(0);2156Value *EarlierArg = EarlierCall->getArgOperand(0);2157switch (PA.getAA()->alias(Arg, EarlierArg)) {2158case AliasResult::MustAlias:2159Changed = true;2160// If the load has a builtin retain, insert a plain retain for it.2161if (Class == ARCInstKind::LoadWeakRetained) {2162Function *Decl = EP.get(ARCRuntimeEntryPointKind::Retain);2163CallInst *CI =2164CallInst::Create(Decl, EarlierCall, "", Call->getIterator());2165CI->setTailCall();2166}2167// Zap the fully redundant load.2168Call->replaceAllUsesWith(EarlierCall->getArgOperand(1));2169Call->eraseFromParent();2170goto clobbered;2171case AliasResult::MayAlias:2172case AliasResult::PartialAlias:2173goto clobbered;2174case AliasResult::NoAlias:2175break;2176}2177break;2178}2179case ARCInstKind::MoveWeak:2180case ARCInstKind::CopyWeak:2181// TOOD: Grab the copied value.2182goto clobbered;2183case ARCInstKind::AutoreleasepoolPush:2184case ARCInstKind::None:2185case ARCInstKind::IntrinsicUser:2186case ARCInstKind::User:2187// Weak pointers are only modified through the weak entry points2188// (and arbitrary calls, which could call the weak entry points).2189break;2190default:2191// Anything else could modify the weak pointer.2192goto clobbered;2193}2194}2195clobbered:;2196}21972198// Then, for each destroyWeak with an alloca operand, check to see if2199// the alloca and all its users can be zapped.2200for (Instruction &Inst : llvm::make_early_inc_range(instructions(F))) {2201ARCInstKind Class = GetBasicARCInstKind(&Inst);2202if (Class != ARCInstKind::DestroyWeak)2203continue;22042205CallInst *Call = cast<CallInst>(&Inst);2206Value *Arg = Call->getArgOperand(0);2207if (AllocaInst *Alloca = dyn_cast<AllocaInst>(Arg)) {2208for (User *U : Alloca->users()) {2209const Instruction *UserInst = cast<Instruction>(U);2210switch (GetBasicARCInstKind(UserInst)) {2211case ARCInstKind::InitWeak:2212case ARCInstKind::StoreWeak:2213case ARCInstKind::DestroyWeak:2214continue;2215default:2216goto done;2217}2218}2219Changed = true;2220for (User *U : llvm::make_early_inc_range(Alloca->users())) {2221CallInst *UserInst = cast<CallInst>(U);2222switch (GetBasicARCInstKind(UserInst)) {2223case ARCInstKind::InitWeak:2224case ARCInstKind::StoreWeak:2225// These functions return their second argument.2226UserInst->replaceAllUsesWith(UserInst->getArgOperand(1));2227break;2228case ARCInstKind::DestroyWeak:2229// No return value.2230break;2231default:2232llvm_unreachable("alloca really is used!");2233}2234UserInst->eraseFromParent();2235}2236Alloca->eraseFromParent();2237done:;2238}2239}2240}22412242/// Identify program paths which execute sequences of retains and releases which2243/// can be eliminated.2244bool ObjCARCOpt::OptimizeSequences(Function &F) {2245// Releases, Retains - These are used to store the results of the main flow2246// analysis. These use Value* as the key instead of Instruction* so that the2247// map stays valid when we get around to rewriting code and calls get2248// replaced by arguments.2249DenseMap<Value *, RRInfo> Releases;2250BlotMapVector<Value *, RRInfo> Retains;22512252// This is used during the traversal of the function to track the2253// states for each identified object at each block.2254DenseMap<const BasicBlock *, BBState> BBStates;22552256// Analyze the CFG of the function, and all instructions.2257bool NestingDetected = Visit(F, BBStates, Retains, Releases);22582259if (DisableRetainReleasePairing)2260return false;22612262// Transform.2263bool AnyPairsCompletelyEliminated = PerformCodePlacement(BBStates, Retains,2264Releases,2265F.getParent());22662267return AnyPairsCompletelyEliminated && NestingDetected;2268}22692270/// Check if there is a dependent call earlier that does not have anything in2271/// between the Retain and the call that can affect the reference count of their2272/// shared pointer argument. Note that Retain need not be in BB.2273static CallInst *HasSafePathToPredecessorCall(const Value *Arg,2274Instruction *Retain,2275ProvenanceAnalysis &PA) {2276auto *Call = dyn_cast_or_null<CallInst>(findSingleDependency(2277CanChangeRetainCount, Arg, Retain->getParent(), Retain, PA));22782279// Check that the pointer is the return value of the call.2280if (!Call || Arg != Call)2281return nullptr;22822283// Check that the call is a regular call.2284ARCInstKind Class = GetBasicARCInstKind(Call);2285return Class == ARCInstKind::CallOrUser || Class == ARCInstKind::Call2286? Call2287: nullptr;2288}22892290/// Find a dependent retain that precedes the given autorelease for which there2291/// is nothing in between the two instructions that can affect the ref count of2292/// Arg.2293static CallInst *2294FindPredecessorRetainWithSafePath(const Value *Arg, BasicBlock *BB,2295Instruction *Autorelease,2296ProvenanceAnalysis &PA) {2297auto *Retain = dyn_cast_or_null<CallInst>(2298findSingleDependency(CanChangeRetainCount, Arg, BB, Autorelease, PA));22992300// Check that we found a retain with the same argument.2301if (!Retain || !IsRetain(GetBasicARCInstKind(Retain)) ||2302GetArgRCIdentityRoot(Retain) != Arg) {2303return nullptr;2304}23052306return Retain;2307}23082309/// Look for an ``autorelease'' instruction dependent on Arg such that there are2310/// no instructions dependent on Arg that need a positive ref count in between2311/// the autorelease and the ret.2312static CallInst *2313FindPredecessorAutoreleaseWithSafePath(const Value *Arg, BasicBlock *BB,2314ReturnInst *Ret,2315ProvenanceAnalysis &PA) {2316SmallPtrSet<Instruction *, 4> DepInsts;2317auto *Autorelease = dyn_cast_or_null<CallInst>(2318findSingleDependency(NeedsPositiveRetainCount, Arg, BB, Ret, PA));23192320if (!Autorelease)2321return nullptr;2322ARCInstKind AutoreleaseClass = GetBasicARCInstKind(Autorelease);2323if (!IsAutorelease(AutoreleaseClass))2324return nullptr;2325if (GetArgRCIdentityRoot(Autorelease) != Arg)2326return nullptr;23272328return Autorelease;2329}23302331/// Look for this pattern:2332/// \code2333/// %call = call i8* @something(...)2334/// %2 = call i8* @objc_retain(i8* %call)2335/// %3 = call i8* @objc_autorelease(i8* %2)2336/// ret i8* %32337/// \endcode2338/// And delete the retain and autorelease.2339void ObjCARCOpt::OptimizeReturns(Function &F) {2340if (!F.getReturnType()->isPointerTy())2341return;23422343LLVM_DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeReturns ==\n");23442345for (BasicBlock &BB: F) {2346ReturnInst *Ret = dyn_cast<ReturnInst>(&BB.back());2347if (!Ret)2348continue;23492350LLVM_DEBUG(dbgs() << "Visiting: " << *Ret << "\n");23512352const Value *Arg = GetRCIdentityRoot(Ret->getOperand(0));23532354// Look for an ``autorelease'' instruction that is a predecessor of Ret and2355// dependent on Arg such that there are no instructions dependent on Arg2356// that need a positive ref count in between the autorelease and Ret.2357CallInst *Autorelease =2358FindPredecessorAutoreleaseWithSafePath(Arg, &BB, Ret, PA);23592360if (!Autorelease)2361continue;23622363CallInst *Retain = FindPredecessorRetainWithSafePath(2364Arg, Autorelease->getParent(), Autorelease, PA);23652366if (!Retain)2367continue;23682369// Check that there is nothing that can affect the reference count2370// between the retain and the call. Note that Retain need not be in BB.2371CallInst *Call = HasSafePathToPredecessorCall(Arg, Retain, PA);23722373// Don't remove retainRV/autoreleaseRV pairs if the call isn't a tail call.2374if (!Call ||2375(!Call->isTailCall() &&2376GetBasicARCInstKind(Retain) == ARCInstKind::RetainRV &&2377GetBasicARCInstKind(Autorelease) == ARCInstKind::AutoreleaseRV))2378continue;23792380// If so, we can zap the retain and autorelease.2381Changed = true;2382++NumRets;2383LLVM_DEBUG(dbgs() << "Erasing: " << *Retain << "\nErasing: " << *Autorelease2384<< "\n");2385BundledInsts->eraseInst(Retain);2386EraseInstruction(Autorelease);2387}2388}23892390#ifndef NDEBUG2391void2392ObjCARCOpt::GatherStatistics(Function &F, bool AfterOptimization) {2393Statistic &NumRetains =2394AfterOptimization ? NumRetainsAfterOpt : NumRetainsBeforeOpt;2395Statistic &NumReleases =2396AfterOptimization ? NumReleasesAfterOpt : NumReleasesBeforeOpt;23972398for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {2399Instruction *Inst = &*I++;2400switch (GetBasicARCInstKind(Inst)) {2401default:2402break;2403case ARCInstKind::Retain:2404++NumRetains;2405break;2406case ARCInstKind::Release:2407++NumReleases;2408break;2409}2410}2411}2412#endif24132414void ObjCARCOpt::init(Function &F) {2415if (!EnableARCOpts)2416return;24172418// Intuitively, objc_retain and others are nocapture, however in practice2419// they are not, because they return their argument value. And objc_release2420// calls finalizers which can have arbitrary side effects.2421MDKindCache.init(F.getParent());24222423// Initialize our runtime entry point cache.2424EP.init(F.getParent());24252426// Compute which blocks are in which funclet.2427if (F.hasPersonalityFn() &&2428isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn())))2429BlockEHColors = colorEHFunclets(F);2430}24312432bool ObjCARCOpt::run(Function &F, AAResults &AA) {2433if (!EnableARCOpts)2434return false;24352436Changed = CFGChanged = false;2437BundledRetainClaimRVs BRV(/*ContractPass=*/false);2438BundledInsts = &BRV;24392440LLVM_DEBUG(dbgs() << "<<< ObjCARCOpt: Visiting Function: " << F.getName()2441<< " >>>"2442"\n");24432444std::pair<bool, bool> R = BundledInsts->insertAfterInvokes(F, nullptr);2445Changed |= R.first;2446CFGChanged |= R.second;24472448PA.setAA(&AA);24492450#ifndef NDEBUG2451if (AreStatisticsEnabled()) {2452GatherStatistics(F, false);2453}2454#endif24552456// This pass performs several distinct transformations. As a compile-time aid2457// when compiling code that isn't ObjC, skip these if the relevant ObjC2458// library functions aren't declared.24592460// Preliminary optimizations. This also computes UsedInThisFunction.2461OptimizeIndividualCalls(F);24622463// Optimizations for weak pointers.2464if (UsedInThisFunction & ((1 << unsigned(ARCInstKind::LoadWeak)) |2465(1 << unsigned(ARCInstKind::LoadWeakRetained)) |2466(1 << unsigned(ARCInstKind::StoreWeak)) |2467(1 << unsigned(ARCInstKind::InitWeak)) |2468(1 << unsigned(ARCInstKind::CopyWeak)) |2469(1 << unsigned(ARCInstKind::MoveWeak)) |2470(1 << unsigned(ARCInstKind::DestroyWeak))))2471OptimizeWeakCalls(F);24722473// Optimizations for retain+release pairs.2474if (UsedInThisFunction & ((1 << unsigned(ARCInstKind::Retain)) |2475(1 << unsigned(ARCInstKind::RetainRV)) |2476(1 << unsigned(ARCInstKind::RetainBlock))))2477if (UsedInThisFunction & (1 << unsigned(ARCInstKind::Release)))2478// Run OptimizeSequences until it either stops making changes or2479// no retain+release pair nesting is detected.2480while (OptimizeSequences(F)) {}24812482// Optimizations if objc_autorelease is used.2483if (UsedInThisFunction & ((1 << unsigned(ARCInstKind::Autorelease)) |2484(1 << unsigned(ARCInstKind::AutoreleaseRV))))2485OptimizeReturns(F);24862487// Gather statistics after optimization.2488#ifndef NDEBUG2489if (AreStatisticsEnabled()) {2490GatherStatistics(F, true);2491}2492#endif24932494LLVM_DEBUG(dbgs() << "\n");24952496return Changed;2497}24982499/// @}2500///25012502PreservedAnalyses ObjCARCOptPass::run(Function &F,2503FunctionAnalysisManager &AM) {2504ObjCARCOpt OCAO;2505OCAO.init(F);25062507bool Changed = OCAO.run(F, AM.getResult<AAManager>(F));2508bool CFGChanged = OCAO.hasCFGChanged();2509if (Changed) {2510PreservedAnalyses PA;2511if (!CFGChanged)2512PA.preserveSet<CFGAnalyses>();2513return PA;2514}2515return PreservedAnalyses::all();2516}251725182519