10b57cec5SDimitry Andric //===- DependencyAnalysis.cpp - ObjC ARC Optimization ---------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// 100b57cec5SDimitry Andric /// This file defines special dependency analysis routines used in Objective C 110b57cec5SDimitry Andric /// ARC Optimizations. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric /// WARNING: This file knows about certain library functions. It recognizes them 140b57cec5SDimitry Andric /// by name, and hardwires knowledge of their semantics. 150b57cec5SDimitry Andric /// 160b57cec5SDimitry Andric /// WARNING: This file knows about how certain Objective-C library functions are 170b57cec5SDimitry Andric /// used. Naive LLVM IR transformations which would otherwise be 180b57cec5SDimitry Andric /// behavior-preserving may break these assumptions. 190b57cec5SDimitry Andric /// 200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric #include "DependencyAnalysis.h" 230b57cec5SDimitry Andric #include "ObjCARC.h" 240b57cec5SDimitry Andric #include "ProvenanceAnalysis.h" 25e8d8bef9SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 260b57cec5SDimitry Andric #include "llvm/IR/CFG.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric using namespace llvm; 290b57cec5SDimitry Andric using namespace llvm::objcarc; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric #define DEBUG_TYPE "objc-arc-dependency" 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric /// Test whether the given instruction can result in a reference count 340b57cec5SDimitry Andric /// modification (positive or negative) for the pointer's object. 350b57cec5SDimitry Andric bool llvm::objcarc::CanAlterRefCount(const Instruction *Inst, const Value *Ptr, 360b57cec5SDimitry Andric ProvenanceAnalysis &PA, 370b57cec5SDimitry Andric ARCInstKind Class) { 380b57cec5SDimitry Andric switch (Class) { 390b57cec5SDimitry Andric case ARCInstKind::Autorelease: 400b57cec5SDimitry Andric case ARCInstKind::AutoreleaseRV: 410b57cec5SDimitry Andric case ARCInstKind::IntrinsicUser: 420b57cec5SDimitry Andric case ARCInstKind::User: 430b57cec5SDimitry Andric // These operations never directly modify a reference count. 440b57cec5SDimitry Andric return false; 450b57cec5SDimitry Andric default: break; 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric const auto *Call = cast<CallBase>(Inst); 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // See if AliasAnalysis can help us with the call. 51bdd1243dSDimitry Andric MemoryEffects ME = PA.getAA()->getMemoryEffects(Call); 52bdd1243dSDimitry Andric if (ME.onlyReadsMemory()) 530b57cec5SDimitry Andric return false; 54bdd1243dSDimitry Andric if (ME.onlyAccessesArgPointees()) { 550b57cec5SDimitry Andric for (const Value *Op : Call->args()) { 56e8d8bef9SDimitry Andric if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op)) 570b57cec5SDimitry Andric return true; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric return false; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // Assume the worst. 630b57cec5SDimitry Andric return true; 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric bool llvm::objcarc::CanDecrementRefCount(const Instruction *Inst, 670b57cec5SDimitry Andric const Value *Ptr, 680b57cec5SDimitry Andric ProvenanceAnalysis &PA, 690b57cec5SDimitry Andric ARCInstKind Class) { 700b57cec5SDimitry Andric // First perform a quick check if Class can not touch ref counts. 710b57cec5SDimitry Andric if (!CanDecrementRefCount(Class)) 720b57cec5SDimitry Andric return false; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Otherwise, just use CanAlterRefCount for now. 750b57cec5SDimitry Andric return CanAlterRefCount(Inst, Ptr, PA, Class); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric /// Test whether the given instruction can "use" the given pointer's object in a 790b57cec5SDimitry Andric /// way that requires the reference count to be positive. 800b57cec5SDimitry Andric bool llvm::objcarc::CanUse(const Instruction *Inst, const Value *Ptr, 810b57cec5SDimitry Andric ProvenanceAnalysis &PA, ARCInstKind Class) { 820b57cec5SDimitry Andric // ARCInstKind::Call operations (as opposed to 830b57cec5SDimitry Andric // ARCInstKind::CallOrUser) never "use" objc pointers. 840b57cec5SDimitry Andric if (Class == ARCInstKind::Call) 850b57cec5SDimitry Andric return false; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // Consider various instructions which may have pointer arguments which are 880b57cec5SDimitry Andric // not "uses". 890b57cec5SDimitry Andric if (const ICmpInst *ICI = dyn_cast<ICmpInst>(Inst)) { 900b57cec5SDimitry Andric // Comparing a pointer with null, or any other constant, isn't really a use, 910b57cec5SDimitry Andric // because we don't care what the pointer points to, or about the values 920b57cec5SDimitry Andric // of any other dynamic reference-counted pointers. 930b57cec5SDimitry Andric if (!IsPotentialRetainableObjPtr(ICI->getOperand(1), *PA.getAA())) 940b57cec5SDimitry Andric return false; 955ffd83dbSDimitry Andric } else if (const auto *CS = dyn_cast<CallBase>(Inst)) { 960b57cec5SDimitry Andric // For calls, just check the arguments (and not the callee operand). 974824e7fdSDimitry Andric for (const Value *Op : CS->args()) 98e8d8bef9SDimitry Andric if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op)) 990b57cec5SDimitry Andric return true; 1000b57cec5SDimitry Andric return false; 1010b57cec5SDimitry Andric } else if (const StoreInst *SI = dyn_cast<StoreInst>(Inst)) { 1020b57cec5SDimitry Andric // Special-case stores, because we don't care about the stored value, just 1030b57cec5SDimitry Andric // the store address. 104e8d8bef9SDimitry Andric const Value *Op = GetUnderlyingObjCPtr(SI->getPointerOperand()); 1050b57cec5SDimitry Andric // If we can't tell what the underlying object was, assume there is a 1060b57cec5SDimitry Andric // dependence. 107e8d8bef9SDimitry Andric return IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Op, Ptr); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric // Check each operand for a match. 111fe6060f1SDimitry Andric for (const Use &U : Inst->operands()) { 112fe6060f1SDimitry Andric const Value *Op = U; 113e8d8bef9SDimitry Andric if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op)) 1140b57cec5SDimitry Andric return true; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric return false; 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric /// Test if there can be dependencies on Inst through Arg. This function only 1200b57cec5SDimitry Andric /// tests dependencies relevant for removing pairs of calls. 1210b57cec5SDimitry Andric bool 1220b57cec5SDimitry Andric llvm::objcarc::Depends(DependenceKind Flavor, Instruction *Inst, 1230b57cec5SDimitry Andric const Value *Arg, ProvenanceAnalysis &PA) { 1240b57cec5SDimitry Andric // If we've reached the definition of Arg, stop. 1250b57cec5SDimitry Andric if (Inst == Arg) 1260b57cec5SDimitry Andric return true; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric switch (Flavor) { 1290b57cec5SDimitry Andric case NeedsPositiveRetainCount: { 1300b57cec5SDimitry Andric ARCInstKind Class = GetARCInstKind(Inst); 1310b57cec5SDimitry Andric switch (Class) { 1320b57cec5SDimitry Andric case ARCInstKind::AutoreleasepoolPop: 1330b57cec5SDimitry Andric case ARCInstKind::AutoreleasepoolPush: 1340b57cec5SDimitry Andric case ARCInstKind::None: 1350b57cec5SDimitry Andric return false; 1360b57cec5SDimitry Andric default: 1370b57cec5SDimitry Andric return CanUse(Inst, Arg, PA, Class); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric case AutoreleasePoolBoundary: { 1420b57cec5SDimitry Andric ARCInstKind Class = GetARCInstKind(Inst); 1430b57cec5SDimitry Andric switch (Class) { 1440b57cec5SDimitry Andric case ARCInstKind::AutoreleasepoolPop: 1450b57cec5SDimitry Andric case ARCInstKind::AutoreleasepoolPush: 1460b57cec5SDimitry Andric // These mark the end and begin of an autorelease pool scope. 1470b57cec5SDimitry Andric return true; 1480b57cec5SDimitry Andric default: 1490b57cec5SDimitry Andric // Nothing else does this. 1500b57cec5SDimitry Andric return false; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric case CanChangeRetainCount: { 1550b57cec5SDimitry Andric ARCInstKind Class = GetARCInstKind(Inst); 1560b57cec5SDimitry Andric switch (Class) { 1570b57cec5SDimitry Andric case ARCInstKind::AutoreleasepoolPop: 1580b57cec5SDimitry Andric // Conservatively assume this can decrement any count. 1590b57cec5SDimitry Andric return true; 1600b57cec5SDimitry Andric case ARCInstKind::AutoreleasepoolPush: 1610b57cec5SDimitry Andric case ARCInstKind::None: 1620b57cec5SDimitry Andric return false; 1630b57cec5SDimitry Andric default: 1640b57cec5SDimitry Andric return CanAlterRefCount(Inst, Arg, PA, Class); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric case RetainAutoreleaseDep: 1690b57cec5SDimitry Andric switch (GetBasicARCInstKind(Inst)) { 1700b57cec5SDimitry Andric case ARCInstKind::AutoreleasepoolPop: 1710b57cec5SDimitry Andric case ARCInstKind::AutoreleasepoolPush: 1720b57cec5SDimitry Andric // Don't merge an objc_autorelease with an objc_retain inside a different 1730b57cec5SDimitry Andric // autoreleasepool scope. 1740b57cec5SDimitry Andric return true; 1750b57cec5SDimitry Andric case ARCInstKind::Retain: 1760b57cec5SDimitry Andric case ARCInstKind::RetainRV: 1770b57cec5SDimitry Andric // Check for a retain of the same pointer for merging. 1780b57cec5SDimitry Andric return GetArgRCIdentityRoot(Inst) == Arg; 1790b57cec5SDimitry Andric default: 1800b57cec5SDimitry Andric // Nothing else matters for objc_retainAutorelease formation. 1810b57cec5SDimitry Andric return false; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric case RetainAutoreleaseRVDep: { 1850b57cec5SDimitry Andric ARCInstKind Class = GetBasicARCInstKind(Inst); 1860b57cec5SDimitry Andric switch (Class) { 1870b57cec5SDimitry Andric case ARCInstKind::Retain: 1880b57cec5SDimitry Andric case ARCInstKind::RetainRV: 1890b57cec5SDimitry Andric // Check for a retain of the same pointer for merging. 1900b57cec5SDimitry Andric return GetArgRCIdentityRoot(Inst) == Arg; 1910b57cec5SDimitry Andric default: 1920b57cec5SDimitry Andric // Anything that can autorelease interrupts 1930b57cec5SDimitry Andric // retainAutoreleaseReturnValue formation. 1940b57cec5SDimitry Andric return CanInterruptRV(Class); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric llvm_unreachable("Invalid dependence flavor"); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric /// Walk up the CFG from StartPos (which is in StartBB) and find local and 2030b57cec5SDimitry Andric /// non-local dependencies on Arg. 2040b57cec5SDimitry Andric /// 2050b57cec5SDimitry Andric /// TODO: Cache results? 206e8d8bef9SDimitry Andric static bool findDependencies(DependenceKind Flavor, const Value *Arg, 2070b57cec5SDimitry Andric BasicBlock *StartBB, Instruction *StartInst, 2080b57cec5SDimitry Andric SmallPtrSetImpl<Instruction *> &DependingInsts, 2090b57cec5SDimitry Andric ProvenanceAnalysis &PA) { 2100b57cec5SDimitry Andric BasicBlock::iterator StartPos = StartInst->getIterator(); 2110b57cec5SDimitry Andric 212e8d8bef9SDimitry Andric SmallPtrSet<const BasicBlock *, 4> Visited; 2130b57cec5SDimitry Andric SmallVector<std::pair<BasicBlock *, BasicBlock::iterator>, 4> Worklist; 2140b57cec5SDimitry Andric Worklist.push_back(std::make_pair(StartBB, StartPos)); 2150b57cec5SDimitry Andric do { 2160b57cec5SDimitry Andric std::pair<BasicBlock *, BasicBlock::iterator> Pair = 2170b57cec5SDimitry Andric Worklist.pop_back_val(); 2180b57cec5SDimitry Andric BasicBlock *LocalStartBB = Pair.first; 2190b57cec5SDimitry Andric BasicBlock::iterator LocalStartPos = Pair.second; 2200b57cec5SDimitry Andric BasicBlock::iterator StartBBBegin = LocalStartBB->begin(); 2210b57cec5SDimitry Andric for (;;) { 2220b57cec5SDimitry Andric if (LocalStartPos == StartBBBegin) { 223*0fca6ea1SDimitry Andric if (pred_empty(LocalStartBB)) 224e8d8bef9SDimitry Andric // Return if we've reached the function entry. 225e8d8bef9SDimitry Andric return false; 2260b57cec5SDimitry Andric // Add the predecessors to the worklist. 227*0fca6ea1SDimitry Andric for (BasicBlock *PredBB : predecessors(LocalStartBB)) 2280b57cec5SDimitry Andric if (Visited.insert(PredBB).second) 2290b57cec5SDimitry Andric Worklist.push_back(std::make_pair(PredBB, PredBB->end())); 2300b57cec5SDimitry Andric break; 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric Instruction *Inst = &*--LocalStartPos; 2340b57cec5SDimitry Andric if (Depends(Flavor, Inst, Arg, PA)) { 2350b57cec5SDimitry Andric DependingInsts.insert(Inst); 2360b57cec5SDimitry Andric break; 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric } while (!Worklist.empty()); 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric // Determine whether the original StartBB post-dominates all of the blocks we 2427a6dacacSDimitry Andric // visited. If not, insert a sentinel indicating that most optimizations are 2430b57cec5SDimitry Andric // not safe. 2440b57cec5SDimitry Andric for (const BasicBlock *BB : Visited) { 2450b57cec5SDimitry Andric if (BB == StartBB) 2460b57cec5SDimitry Andric continue; 2470b57cec5SDimitry Andric for (const BasicBlock *Succ : successors(BB)) 248e8d8bef9SDimitry Andric if (Succ != StartBB && !Visited.count(Succ)) 249e8d8bef9SDimitry Andric return false; 2500b57cec5SDimitry Andric } 251e8d8bef9SDimitry Andric 252e8d8bef9SDimitry Andric return true; 2530b57cec5SDimitry Andric } 254e8d8bef9SDimitry Andric 255e8d8bef9SDimitry Andric llvm::Instruction *llvm::objcarc::findSingleDependency(DependenceKind Flavor, 256e8d8bef9SDimitry Andric const Value *Arg, 257e8d8bef9SDimitry Andric BasicBlock *StartBB, 258e8d8bef9SDimitry Andric Instruction *StartInst, 259e8d8bef9SDimitry Andric ProvenanceAnalysis &PA) { 260e8d8bef9SDimitry Andric SmallPtrSet<Instruction *, 4> DependingInsts; 261e8d8bef9SDimitry Andric 262e8d8bef9SDimitry Andric if (!findDependencies(Flavor, Arg, StartBB, StartInst, DependingInsts, PA) || 263e8d8bef9SDimitry Andric DependingInsts.size() != 1) 264e8d8bef9SDimitry Andric return nullptr; 265e8d8bef9SDimitry Andric return *DependingInsts.begin(); 2660b57cec5SDimitry Andric } 267