124c4898973a074713201fb9351d302b9f7733e92Michael Gottesman//===- ObjCARCOpts.cpp - ObjC ARC Optimization ----------------------------===// 29fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// 39fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// The LLVM Compiler Infrastructure 49fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// 59fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// This file is distributed under the University of Illinois Open Source 69fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// License. See LICENSE.TXT for details. 79fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// 89fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall//===----------------------------------------------------------------------===// 981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// \file 1081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// This file defines ObjC ARC optimizations. ARC stands for Automatic 1181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Reference Counting and is a system for managing reference counts for objects 1281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// in Objective C. 1381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// 1481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// The optimizations performed include elimination of redundant, partially 1581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// redundant, and inconsequential reference count operations, elimination of 1665c46b0cff2a7bcefff9b58895cdf8d710e3b6f7Michael Gottesman/// redundant weak pointer operations, and numerous minor simplifications. 1781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// 1881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// WARNING: This file knows about certain library functions. It recognizes them 1981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// by name, and hardwires knowledge of their semantics. 2081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// 2181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// WARNING: This file knows about how certain Objective-C library functions are 2281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// used. Naive LLVM IR transformations which would otherwise be 2381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// behavior-preserving may break these assumptions. 2481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// 259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall//===----------------------------------------------------------------------===// 269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 276504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman#define DEBUG_TYPE "objc-arc-opts" 286504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman#include "ObjCARC.h" 297a7102d17f979918042bc040e27288d64a6bea5fMichael Gottesman#include "DependencyAnalysis.h" 306086847bfbc538b99305b4d7e0a53ab610f6a9bbMichael Gottesman#include "ObjCARCAliasAnalysis.h" 313a57c37964adfbbf83b4b309a2ceda43ba6d8231Michael Gottesman#include "ProvenanceAnalysis.h" 329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall#include "llvm/ADT/DenseMap.h" 333c67f1cd94760f879e0ec5407f0d1078bc51f9b4Michael Gottesman#include "llvm/ADT/STLExtras.h" 343a57c37964adfbbf83b4b309a2ceda43ba6d8231Michael Gottesman#include "llvm/ADT/SmallPtrSet.h" 357a7102d17f979918042bc040e27288d64a6bea5fMichael Gottesman#include "llvm/ADT/Statistic.h" 367a7102d17f979918042bc040e27288d64a6bea5fMichael Gottesman#include "llvm/IR/LLVMContext.h" 373a57c37964adfbbf83b4b309a2ceda43ba6d8231Michael Gottesman#include "llvm/Support/CFG.h" 389ab758b9bc2fe51af6dabbdeb30f4a2e600bdcd0Michael Gottesman#include "llvm/Support/Debug.h" 3909840daeefc1aa8760c535ded6a37eb4f8cd4eaaTimur Iskhodzhanov#include "llvm/Support/raw_ostream.h" 403c67f1cd94760f879e0ec5407f0d1078bc51f9b4Michael Gottesman 419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallusing namespace llvm; 426504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesmanusing namespace llvm::objcarc; 439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 4481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// \defgroup MiscUtils Miscellaneous utilities that are not ARC specific. 4581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// @{ 469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallnamespace { 4881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// \brief An associative container with fast insertion-order (deterministic) 4981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// iteration over its elements. Plus the special blot operation. 509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall template<class KeyT, class ValueT> 519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall class MapVector { 5281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Map keys to indices in Vector. 539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall typedef DenseMap<KeyT, size_t> MapTy; 549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapTy Map; 559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall typedef std::vector<std::pair<KeyT, ValueT> > VectorTy; 5781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Keys and values. 589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall VectorTy Vector; 599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall public: 619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall typedef typename VectorTy::iterator iterator; 629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall typedef typename VectorTy::const_iterator const_iterator; 639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall iterator begin() { return Vector.begin(); } 649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall iterator end() { return Vector.end(); } 659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const_iterator begin() const { return Vector.begin(); } 669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const_iterator end() const { return Vector.end(); } 679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall#ifdef XDEBUG 699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ~MapVector() { 709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall assert(Vector.size() >= Map.size()); // May differ due to blotting. 719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (typename MapTy::const_iterator I = Map.begin(), E = Map.end(); 729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall I != E; ++I) { 739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall assert(I->second < Vector.size()); 749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall assert(Vector[I->second].first == I->first); 759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (typename VectorTy::const_iterator I = Vector.begin(), 779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall E = Vector.end(); I != E; ++I) 789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall assert(!I->first || 799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall (Map.count(I->first) && 809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Map[I->first] == size_t(I - Vector.begin()))); 819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall#endif 839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8422cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman ValueT &operator[](const KeyT &Arg) { 859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall std::pair<typename MapTy::iterator, bool> Pair = 869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Map.insert(std::make_pair(Arg, size_t(0))); 879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Pair.second) { 8822cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman size_t Num = Vector.size(); 8922cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman Pair.first->second = Num; 909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Vector.push_back(std::make_pair(Arg, ValueT())); 9122cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman return Vector[Num].second; 929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return Vector[Pair.first->second].second; 949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall std::pair<iterator, bool> 979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall insert(const std::pair<KeyT, ValueT> &InsertPair) { 989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall std::pair<typename MapTy::iterator, bool> Pair = 999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Map.insert(std::make_pair(InsertPair.first, size_t(0))); 1009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Pair.second) { 10122cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman size_t Num = Vector.size(); 10222cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman Pair.first->second = Num; 1039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Vector.push_back(InsertPair); 10422cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman return std::make_pair(Vector.begin() + Num, true); 1059fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return std::make_pair(Vector.begin() + Pair.first->second, false); 1079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 10922cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman const_iterator find(const KeyT &Key) const { 1109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall typename MapTy::const_iterator It = Map.find(Key); 1119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (It == Map.end()) return Vector.end(); 1129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return Vector.begin() + It->second; 1139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 11581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// This is similar to erase, but instead of removing the element from the 11681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// vector, it just zeros out the key in the vector. This leaves iterators 11781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// intact, but clients must be prepared for zeroed-out keys when iterating. 11822cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman void blot(const KeyT &Key) { 1199fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall typename MapTy::iterator It = Map.find(Key); 1209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (It == Map.end()) return; 1219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Vector[It->second].first = KeyT(); 1229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Map.erase(It); 1239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void clear() { 1269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Map.clear(); 1279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Vector.clear(); 1289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall }; 1309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 1319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 13281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// @} 13381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// 13481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// \defgroup ARCUtilities Utility declarations/definitions specific to ARC. 13581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// @{ 1369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 13781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// \brief This is similar to StripPointerCastsAndObjCCalls but it stops as soon 13881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// as it finds a value with multiple uses. 1399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallstatic const Value *FindSingleUseIdentifiedObject(const Value *Arg) { 1409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Arg->hasOneUse()) { 1419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (const BitCastInst *BC = dyn_cast<BitCastInst>(Arg)) 1429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return FindSingleUseIdentifiedObject(BC->getOperand(0)); 1439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Arg)) 1449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (GEP->hasAllZeroIndices()) 1459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return FindSingleUseIdentifiedObject(GEP->getPointerOperand()); 1469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (IsForwarding(GetBasicInstructionClass(Arg))) 1479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return FindSingleUseIdentifiedObject( 1489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall cast<CallInst>(Arg)->getArgOperand(0)); 1499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!IsObjCIdentifiedObject(Arg)) 1509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return 0; 1519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return Arg; 1529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1540daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman // If we found an identifiable object but it has multiple uses, but they are 1550daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman // trivial uses, we can still consider this to be a single-use value. 1569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (IsObjCIdentifiedObject(Arg)) { 1579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (Value::const_use_iterator UI = Arg->use_begin(), UE = Arg->use_end(); 1589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall UI != UE; ++UI) { 1599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const User *U = *UI; 1609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!U->use_empty() || StripPointerCastsAndObjCCalls(U) != Arg) 1619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return 0; 1629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return Arg; 1659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return 0; 1689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 1699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 17082b83011a1e330e41147dbad97e44939840ba755Michael Gottesman/// \brief Test whether the given retainable object pointer escapes. 17181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// 17281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// This differs from regular escape analysis in that a use as an 17381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// argument to a call is not considered an escape. 17481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// 17582b83011a1e330e41147dbad97e44939840ba755Michael Gottesmanstatic bool DoesRetainableObjPtrEscape(const User *Ptr) { 17682b83011a1e330e41147dbad97e44939840ba755Michael Gottesman DEBUG(dbgs() << "DoesRetainableObjPtrEscape: Target: " << *Ptr << "\n"); 177981308cffbfd1f77750452015f6e6f0f053e11d4Michael Gottesman 17879522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // Walk the def-use chains. 17979522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman SmallVector<const Value *, 4> Worklist; 18082b83011a1e330e41147dbad97e44939840ba755Michael Gottesman Worklist.push_back(Ptr); 18182b83011a1e330e41147dbad97e44939840ba755Michael Gottesman // If Ptr has any operands add them as well. 18202c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman for (User::const_op_iterator I = Ptr->op_begin(), E = Ptr->op_end(); I != E; 18302c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman ++I) { 18482b83011a1e330e41147dbad97e44939840ba755Michael Gottesman Worklist.push_back(*I); 18582b83011a1e330e41147dbad97e44939840ba755Michael Gottesman } 1866056b85bb5e863f3b174ed21bd70e22a03ed61f7Michael Gottesman 1876056b85bb5e863f3b174ed21bd70e22a03ed61f7Michael Gottesman // Ensure we do not visit any value twice. 18882b83011a1e330e41147dbad97e44939840ba755Michael Gottesman SmallPtrSet<const Value *, 8> VisitedSet; 1896056b85bb5e863f3b174ed21bd70e22a03ed61f7Michael Gottesman 19079522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman do { 19179522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman const Value *V = Worklist.pop_back_val(); 192981308cffbfd1f77750452015f6e6f0f053e11d4Michael Gottesman 19382b83011a1e330e41147dbad97e44939840ba755Michael Gottesman DEBUG(dbgs() << "DoesRetainableObjPtrEscape: Visiting: " << *V << "\n"); 194981308cffbfd1f77750452015f6e6f0f053e11d4Michael Gottesman 19579522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman for (Value::const_use_iterator UI = V->use_begin(), UE = V->use_end(); 19679522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman UI != UE; ++UI) { 19779522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman const User *UUser = *UI; 198981308cffbfd1f77750452015f6e6f0f053e11d4Michael Gottesman 19982b83011a1e330e41147dbad97e44939840ba755Michael Gottesman DEBUG(dbgs() << "DoesRetainableObjPtrEscape: User: " << *UUser << "\n"); 200981308cffbfd1f77750452015f6e6f0f053e11d4Michael Gottesman 20179522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // Special - Use by a call (callee or argument) is not considered 20279522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // to be an escape. 20344234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman switch (GetBasicInstructionClass(UUser)) { 20444234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman case IC_StoreWeak: 20544234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman case IC_InitWeak: 20644234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman case IC_StoreStrong: 20744234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman case IC_Autorelease: 208981308cffbfd1f77750452015f6e6f0f053e11d4Michael Gottesman case IC_AutoreleaseRV: { 20902c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman DEBUG(dbgs() << "DoesRetainableObjPtrEscape: User copies pointer " 21002c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman "arguments. Pointer Escapes!\n"); 21144234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman // These special functions make copies of their pointer arguments. 21244234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman return true; 213981308cffbfd1f77750452015f6e6f0f053e11d4Michael Gottesman } 21444234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman case IC_User: 21544234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman case IC_None: 21644234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman // Use by an instruction which copies the value is an escape if the 21744234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman // result is an escape. 21844234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman if (isa<BitCastInst>(UUser) || isa<GetElementPtrInst>(UUser) || 21944234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman isa<PHINode>(UUser) || isa<SelectInst>(UUser)) { 2206056b85bb5e863f3b174ed21bd70e22a03ed61f7Michael Gottesman 2213603e9aa5e46923c44db1e6254f0393a2b0644e4Michael Gottesman if (VisitedSet.insert(UUser)) { 22202c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman DEBUG(dbgs() << "DoesRetainableObjPtrEscape: User copies value. " 22302c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman "Ptr escapes if result escapes. Adding to list.\n"); 2246056b85bb5e863f3b174ed21bd70e22a03ed61f7Michael Gottesman Worklist.push_back(UUser); 2256056b85bb5e863f3b174ed21bd70e22a03ed61f7Michael Gottesman } else { 22602c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman DEBUG(dbgs() << "DoesRetainableObjPtrEscape: Already visited node." 22702c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman "\n"); 2286056b85bb5e863f3b174ed21bd70e22a03ed61f7Michael Gottesman } 22944234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman continue; 23044234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman } 23144234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman // Use by a load is not an escape. 23244234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman if (isa<LoadInst>(UUser)) 23344234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman continue; 23444234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman // Use by a store is not an escape if the use is the address. 23544234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman if (const StoreInst *SI = dyn_cast<StoreInst>(UUser)) 23644234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman if (V != SI->getValueOperand()) 23744234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman continue; 23844234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman break; 23944234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman default: 24044234775486a0bd8fb6dae4048666ea5567caa11Dan Gohman // Regular calls and other stuff are not considered escapes. 24179522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman continue; 24279522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman } 243a3b08d68bd281773b0300222edb4149abce4b4b8Dan Gohman // Otherwise, conservatively assume an escape. 24402c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman DEBUG(dbgs() << "DoesRetainableObjPtrEscape: Assuming ptr escapes.\n"); 24579522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman return true; 24679522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman } 24779522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman } while (!Worklist.empty()); 24879522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman 24979522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // No escapes found. 25002c953ea8b8130bd60fdacb97649d6344f1e8143Michael Gottesman DEBUG(dbgs() << "DoesRetainableObjPtrEscape: Ptr does not escape.\n"); 25179522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman return false; 25279522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman} 25379522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman 25481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// @} 25581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// 25681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// \defgroup ARCOpt ARC Optimization. 25781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// @{ 2589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// TODO: On code like this: 2609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// 2619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// objc_retain(%x) 2629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// stuff_that_cannot_release() 2639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// objc_autorelease(%x) 2649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// stuff_that_cannot_release() 2659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// objc_retain(%x) 2669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// stuff_that_cannot_release() 2679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// objc_autorelease(%x) 2689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// 2699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// The second retain and autorelease can be deleted. 2709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// TODO: It should be possible to delete 2729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// objc_autoreleasePoolPush and objc_autoreleasePoolPop 2739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// pairs if nothing is actually autoreleased between them. Also, autorelease 2749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// calls followed by objc_autoreleasePoolPop calls (perhaps in ObjC++ code 2759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// after inlining) can be turned into plain release calls. 2769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// TODO: Critical-edge splitting. If the optimial insertion point is 2789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// a critical edge, the current algorithm has to fail, because it doesn't 2799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// know how to split edges. It should be possible to make the optimizer 2809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// think in terms of edges, rather than blocks, and then split critical 2819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// edges on demand. 2829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// TODO: OptimizeSequences could generalized to be Interprocedural. 2849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// TODO: Recognize that a bunch of other objc runtime calls have 2869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// non-escaping arguments and non-releasing arguments, and may be 2879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// non-autoreleasing. 2889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// TODO: Sink autorelease calls as far as possible. Unfortunately we 2909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// usually can't sink them past other calls, which would be the main 2919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall// case where it would be useful. 2929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 293e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman// TODO: The pointer returned from objc_loadWeakRetained is retained. 294e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman 295e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman// TODO: Delete release+retain pairs (rare). 296c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman 2979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallSTATISTIC(NumNoops, "Number of no-op objc calls eliminated"); 2989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallSTATISTIC(NumPartialNoops, "Number of partially no-op objc calls eliminated"); 2999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallSTATISTIC(NumAutoreleases,"Number of autoreleases converted to releases"); 3009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallSTATISTIC(NumRets, "Number of return value forwarding " 3019fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall "retain+autoreleaes eliminated"); 3029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallSTATISTIC(NumRRs, "Number of retain+release paths eliminated"); 3039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallSTATISTIC(NumPeeps, "Number of calls peephole-optimized"); 3049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 3059fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallnamespace { 30681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// \enum Sequence 30781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// 30881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// \brief A sequence of states that a pointer may go through in which an 30981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// objc_retain and objc_release are actually needed. 3109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall enum Sequence { 3119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall S_None, 312a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman S_Retain, ///< objc_retain(x). 313a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman S_CanRelease, ///< foo(x) -- x could possibly see a ref count decrement. 314a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman S_Use, ///< any use of x. 315b82d200dcb748619e22491ecfb9662ae86d7dfd5Michael Gottesman S_Stop, ///< like S_Release, but code motion is stopped. 316a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman S_Release, ///< objc_release(x). 317485da648484e443f38c8ddbe5cb8ace07e2166e7Michael Gottesman S_MovableRelease ///< objc_release(x), !clang.imprecise_release. 3189fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall }; 319a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman 320a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman raw_ostream &operator<<(raw_ostream &OS, const Sequence S) 321a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman LLVM_ATTRIBUTE_UNUSED; 322a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman raw_ostream &operator<<(raw_ostream &OS, const Sequence S) { 323a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman switch (S) { 324a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman case S_None: 325a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman return OS << "S_None"; 326a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman case S_Retain: 327a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman return OS << "S_Retain"; 328a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman case S_CanRelease: 329a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman return OS << "S_CanRelease"; 330a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman case S_Use: 331a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman return OS << "S_Use"; 332a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman case S_Release: 333a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman return OS << "S_Release"; 334a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman case S_MovableRelease: 335a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman return OS << "S_MovableRelease"; 336a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman case S_Stop: 337a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman return OS << "S_Stop"; 338a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman } 339a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman llvm_unreachable("Unknown sequence type."); 340a519c97b4278970b7104005205c6f42910cb9acbMichael Gottesman } 3419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 3429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 3439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallstatic Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) { 3449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // The easy cases. 3459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (A == B) 3469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return A; 3479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (A == S_None || B == S_None) 3489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return S_None; 3499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 3509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (A > B) std::swap(A, B); 3519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (TopDown) { 3529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Choose the side which is further along in the sequence. 353a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman if ((A == S_Retain || A == S_CanRelease) && 354a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman (B == S_CanRelease || B == S_Use)) 3559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return B; 3569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } else { 3579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Choose the side which is further along in the sequence. 3589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if ((A == S_Use || A == S_CanRelease) && 359a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman (B == S_Use || B == S_Release || B == S_Stop || B == S_MovableRelease)) 3609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return A; 3619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If both sides are releases, choose the more conservative one. 3629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (A == S_Stop && (B == S_Release || B == S_MovableRelease)) 3639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return A; 3649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (A == S_Release && B == S_MovableRelease) 3659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return A; 3669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 3679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 3689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return S_None; 3699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 3709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 3719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallnamespace { 37281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// \brief Unidirectional information about either a 3739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /// retain-decrement-use-release sequence or release-use-decrement-retain 3749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /// reverese sequence. 3759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall struct RRInfo { 37681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// After an objc_retain, the reference count of the referenced 377e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// object is known to be positive. Similarly, before an objc_release, the 378e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// reference count of the referenced object is known to be positive. If 379e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// there are retain-release pairs in code regions where the retain count 380e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// is known to be positive, they can be eliminated, regardless of any side 381e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// effects between them. 382e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// 383e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// Also, a retain+release pair nested within another retain+release 384e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// pair all on the known same pointer value can be eliminated, regardless 385e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// of any intervening side effects. 386e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// 387e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman /// KnownSafe is true when either of these conditions is satisfied. 388e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman bool KnownSafe; 3899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 39081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// True if the Calls are objc_retainBlock calls (as opposed to objc_retain 39181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// calls). 3929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool IsRetainBlock; 3939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 39481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// True of the objc_release calls are all marked with the "tail" keyword. 3959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool IsTailCallRelease; 3969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 39781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// If the Calls are objc_release calls and they all have a 39881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// clang.imprecise_release tag, this is the metadata tag. 3999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MDNode *ReleaseMetadata; 4009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 40181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// For a top-down sequence, the set of objc_retains or 4029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /// objc_retainBlocks. For bottom-up, the set of objc_releases. 4039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallPtrSet<Instruction *, 2> Calls; 4049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 40581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The set of optimal insert positions for moving calls in the opposite 40681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// sequence. 4079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallPtrSet<Instruction *, 2> ReverseInsertPts; 4089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 4099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRInfo() : 41079522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman KnownSafe(false), IsRetainBlock(false), 41150ade659829269f0338cd1bfa0a574dcec62562eDan Gohman IsTailCallRelease(false), 4129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ReleaseMetadata(0) {} 4139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 4149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void clear(); 4159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall }; 4169fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 4179fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 4189fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid RRInfo::clear() { 419e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman KnownSafe = false; 4209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall IsRetainBlock = false; 4219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall IsTailCallRelease = false; 4229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ReleaseMetadata = 0; 4239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Calls.clear(); 4249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ReverseInsertPts.clear(); 4259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 4269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 4279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallnamespace { 42881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// \brief This class summarizes several per-pointer runtime properties which 42981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// are propogated through the flow graph. 4309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall class PtrState { 43181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// True if the reference count is known to be incremented. 43250ade659829269f0338cd1bfa0a574dcec62562eDan Gohman bool KnownPositiveRefCount; 43350ade659829269f0338cd1bfa0a574dcec62562eDan Gohman 43481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// True of we've seen an opportunity for partial RR elimination, such as 43581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// pushing calls into a CFG triangle or into one side of a CFG diamond. 43650ade659829269f0338cd1bfa0a574dcec62562eDan Gohman bool Partial; 4379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 43881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The current position in the sequence. 4390daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Sequence Seq : 8; 4409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 4419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall public: 44281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Unidirectional information about the current sequence. 44381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// 4449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /// TODO: Encapsulate this better. 4459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRInfo RRI; 4469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 447230768bd1316a012e88ac62689589fe5e2f10456Dan Gohman PtrState() : KnownPositiveRefCount(false), Partial(false), 4480daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Seq(S_None) {} 449a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman 450da6bf1d8bbf8e787f7c0edffbad40531dd520446Michael Gottesman void SetKnownPositiveRefCount() { 45150ade659829269f0338cd1bfa0a574dcec62562eDan Gohman KnownPositiveRefCount = true; 4529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 4539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 454da6bf1d8bbf8e787f7c0edffbad40531dd520446Michael Gottesman void ClearRefCount() { 45550ade659829269f0338cd1bfa0a574dcec62562eDan Gohman KnownPositiveRefCount = false; 4569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 4579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 458da6bf1d8bbf8e787f7c0edffbad40531dd520446Michael Gottesman bool IsKnownIncremented() const { 45950ade659829269f0338cd1bfa0a574dcec62562eDan Gohman return KnownPositiveRefCount; 4609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 4619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 462da6bf1d8bbf8e787f7c0edffbad40531dd520446Michael Gottesman void SetSeq(Sequence NewSeq) { 4639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Seq = NewSeq; 4649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 4659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 466da6bf1d8bbf8e787f7c0edffbad40531dd520446Michael Gottesman Sequence GetSeq() const { 4679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return Seq; 4689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 4699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 470da6bf1d8bbf8e787f7c0edffbad40531dd520446Michael Gottesman void ClearSequenceProgress() { 47150ade659829269f0338cd1bfa0a574dcec62562eDan Gohman ResetSequenceProgress(S_None); 47250ade659829269f0338cd1bfa0a574dcec62562eDan Gohman } 47350ade659829269f0338cd1bfa0a574dcec62562eDan Gohman 474da6bf1d8bbf8e787f7c0edffbad40531dd520446Michael Gottesman void ResetSequenceProgress(Sequence NewSeq) { 47550ade659829269f0338cd1bfa0a574dcec62562eDan Gohman Seq = NewSeq; 47650ade659829269f0338cd1bfa0a574dcec62562eDan Gohman Partial = false; 4779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRI.clear(); 4789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 4799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 4809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void Merge(const PtrState &Other, bool TopDown); 4819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall }; 4829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 4839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 4849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid 4859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallPtrState::Merge(const PtrState &Other, bool TopDown) { 4869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Seq = MergeSeqs(Seq, Other.Seq, TopDown); 48750ade659829269f0338cd1bfa0a574dcec62562eDan Gohman KnownPositiveRefCount = KnownPositiveRefCount && Other.KnownPositiveRefCount; 4889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 4899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // We can't merge a plain objc_retain with an objc_retainBlock. 4909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (RRI.IsRetainBlock != Other.RRI.IsRetainBlock) 4919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Seq = S_None; 4929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 49390b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman // If we're not in a sequence (anymore), drop all associated state. 4949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Seq == S_None) { 49550ade659829269f0338cd1bfa0a574dcec62562eDan Gohman Partial = false; 4969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRI.clear(); 49750ade659829269f0338cd1bfa0a574dcec62562eDan Gohman } else if (Partial || Other.Partial) { 49890b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman // If we're doing a merge on a path that's previously seen a partial 49990b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman // merge, conservatively drop the sequence, to avoid doing partial 50090b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman // RR elimination. If the branch predicates for the two merge differ, 50190b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman // mixing them is unsafe. 50250ade659829269f0338cd1bfa0a574dcec62562eDan Gohman ClearSequenceProgress(); 5039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } else { 5049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Conservatively merge the ReleaseMetadata information. 5059fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (RRI.ReleaseMetadata != Other.RRI.ReleaseMetadata) 5069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRI.ReleaseMetadata = 0; 5079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 508e6d5e88c1230eae7056a5cd6238e86c00cdff72fDan Gohman RRI.KnownSafe = RRI.KnownSafe && Other.RRI.KnownSafe; 5090daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman RRI.IsTailCallRelease = RRI.IsTailCallRelease && 5100daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Other.RRI.IsTailCallRelease; 5119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRI.Calls.insert(Other.RRI.Calls.begin(), Other.RRI.Calls.end()); 51290b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman 51390b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman // Merge the insert point sets. If there are any differences, 51490b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman // that makes this a partial merge. 5150daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Partial = RRI.ReverseInsertPts.size() != Other.RRI.ReverseInsertPts.size(); 51690b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman for (SmallPtrSet<Instruction *, 2>::const_iterator 51790b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman I = Other.RRI.ReverseInsertPts.begin(), 51890b8bcd33ab4fd7dd95bd1dc9a2d7d03dcd83ad6Dan Gohman E = Other.RRI.ReverseInsertPts.end(); I != E; ++I) 51950ade659829269f0338cd1bfa0a574dcec62562eDan Gohman Partial |= RRI.ReverseInsertPts.insert(*I); 5209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 5219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 5229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 5239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallnamespace { 52481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// \brief Per-BasicBlock state. 5259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall class BBState { 52681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The number of unique control paths from the entry which can reach this 52781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// block. 5289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall unsigned TopDownPathCount; 5299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 53081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The number of unique control paths to exits from this block. 5319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall unsigned BottomUpPathCount; 5329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 53381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// A type for PerPtrTopDown and PerPtrBottomUp. 5349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall typedef MapVector<const Value *, PtrState> MapTy; 5359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 53681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The top-down traversal uses this to record information known about a 53781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// pointer at the bottom of each block. 5389fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapTy PerPtrTopDown; 5399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 54081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The bottom-up traversal uses this to record information known about a 54181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// pointer at the top of each block. 5429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapTy PerPtrBottomUp; 5439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 54481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Effective predecessors of the current block ignoring ignorable edges and 54581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// ignored backedges. 546eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman SmallVector<BasicBlock *, 2> Preds; 54781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Effective successors of the current block ignoring ignorable edges and 54881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// ignored backedges. 549eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman SmallVector<BasicBlock *, 2> Succs; 550eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman 5519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall public: 5529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BBState() : TopDownPathCount(0), BottomUpPathCount(0) {} 5539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 5549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall typedef MapTy::iterator ptr_iterator; 5559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall typedef MapTy::const_iterator ptr_const_iterator; 5569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 5579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ptr_iterator top_down_ptr_begin() { return PerPtrTopDown.begin(); } 5589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ptr_iterator top_down_ptr_end() { return PerPtrTopDown.end(); } 5599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ptr_const_iterator top_down_ptr_begin() const { 5609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return PerPtrTopDown.begin(); 5619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 5629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ptr_const_iterator top_down_ptr_end() const { 5639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return PerPtrTopDown.end(); 5649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 5659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 5669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ptr_iterator bottom_up_ptr_begin() { return PerPtrBottomUp.begin(); } 5679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ptr_iterator bottom_up_ptr_end() { return PerPtrBottomUp.end(); } 5689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ptr_const_iterator bottom_up_ptr_begin() const { 5699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return PerPtrBottomUp.begin(); 5709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 5719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ptr_const_iterator bottom_up_ptr_end() const { 5729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return PerPtrBottomUp.end(); 5739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 5749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 57581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Mark this block as being an entry block, which has one path from the 57681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// entry by definition. 5779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void SetAsEntry() { TopDownPathCount = 1; } 5789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 57981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Mark this block as being an exit block, which has one path to an exit by 58081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// definition. 5819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void SetAsExit() { BottomUpPathCount = 1; } 5829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 5839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PtrState &getPtrTopDownState(const Value *Arg) { 5849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return PerPtrTopDown[Arg]; 5859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 5869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 5879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PtrState &getPtrBottomUpState(const Value *Arg) { 5889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return PerPtrBottomUp[Arg]; 5899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 5909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 5919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void clearBottomUpPointers() { 592a81388fb4ab78cf85019840a27057b185f828ad1Evan Cheng PerPtrBottomUp.clear(); 5939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 5949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 5959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void clearTopDownPointers() { 5969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PerPtrTopDown.clear(); 5979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 5989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 5999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void InitFromPred(const BBState &Other); 6009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void InitFromSucc(const BBState &Other); 6019fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void MergePred(const BBState &Other); 6029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void MergeSucc(const BBState &Other); 6039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 60481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Return the number of possible unique paths from an entry to an exit 60581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// which pass through this block. This is only valid after both the 60681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// top-down and bottom-up traversals are complete. 6079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall unsigned GetAllPathCount() const { 608eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman assert(TopDownPathCount != 0); 609eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman assert(BottomUpPathCount != 0); 6109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return TopDownPathCount * BottomUpPathCount; 6119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 612a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman 613eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman // Specialized CFG utilities. 614447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman typedef SmallVectorImpl<BasicBlock *>::const_iterator edge_iterator; 615eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman edge_iterator pred_begin() { return Preds.begin(); } 616eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman edge_iterator pred_end() { return Preds.end(); } 617eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman edge_iterator succ_begin() { return Succs.begin(); } 618eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman edge_iterator succ_end() { return Succs.end(); } 619eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman 620eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman void addSucc(BasicBlock *Succ) { Succs.push_back(Succ); } 621eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman void addPred(BasicBlock *Pred) { Preds.push_back(Pred); } 622eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman 623eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman bool isExit() const { return Succs.empty(); } 6249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall }; 6259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 6269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 6279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid BBState::InitFromPred(const BBState &Other) { 6289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PerPtrTopDown = Other.PerPtrTopDown; 6299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall TopDownPathCount = Other.TopDownPathCount; 6309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 6319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 6329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid BBState::InitFromSucc(const BBState &Other) { 6339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PerPtrBottomUp = Other.PerPtrBottomUp; 6349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BottomUpPathCount = Other.BottomUpPathCount; 6359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 6369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 63781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// The top-down traversal uses this to merge information about predecessors to 63881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// form the initial state for a new block. 6399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid BBState::MergePred(const BBState &Other) { 6409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Other.TopDownPathCount can be 0, in which case it is either dead or a 6419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // loop backedge. Loop backedges are special. 6429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall TopDownPathCount += Other.TopDownPathCount; 6439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 6447899e47f205f32127ec2b6229ca587e996e0a08eMichael Gottesman // Check for overflow. If we have overflow, fall back to conservative 6457899e47f205f32127ec2b6229ca587e996e0a08eMichael Gottesman // behavior. 6460d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman if (TopDownPathCount < Other.TopDownPathCount) { 6470d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman clearTopDownPointers(); 6480d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman return; 6490d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman } 6500d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman 6519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // For each entry in the other set, if our set has an entry with the same key, 6529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // merge the entries. Otherwise, copy the entry and merge it with an empty 6539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // entry. 6549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (ptr_const_iterator MI = Other.top_down_ptr_begin(), 6559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ME = Other.top_down_ptr_end(); MI != ME; ++MI) { 6569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall std::pair<ptr_iterator, bool> Pair = PerPtrTopDown.insert(*MI); 6579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Pair.first->second.Merge(Pair.second ? PtrState() : MI->second, 6589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /*TopDown=*/true); 6599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 6609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 661fa7eed1f8eee4fd3839e589c3e0e84f79d248c8aDan Gohman // For each entry in our set, if the other set doesn't have an entry with the 6629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // same key, force it to merge with an empty entry. 6639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (ptr_iterator MI = top_down_ptr_begin(), 6649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ME = top_down_ptr_end(); MI != ME; ++MI) 6659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Other.PerPtrTopDown.find(MI->first) == Other.PerPtrTopDown.end()) 6669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MI->second.Merge(PtrState(), /*TopDown=*/true); 6679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 6689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 66981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// The bottom-up traversal uses this to merge information about successors to 67081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// form the initial state for a new block. 6719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid BBState::MergeSucc(const BBState &Other) { 6729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Other.BottomUpPathCount can be 0, in which case it is either dead or a 6739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // loop backedge. Loop backedges are special. 6749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BottomUpPathCount += Other.BottomUpPathCount; 6759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 6767899e47f205f32127ec2b6229ca587e996e0a08eMichael Gottesman // Check for overflow. If we have overflow, fall back to conservative 6777899e47f205f32127ec2b6229ca587e996e0a08eMichael Gottesman // behavior. 6780d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman if (BottomUpPathCount < Other.BottomUpPathCount) { 6790d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman clearBottomUpPointers(); 6800d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman return; 6810d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman } 6820d1bc5f916d6b0f4eb5bf69cf87e244b52be009eDan Gohman 6839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // For each entry in the other set, if our set has an entry with the 6849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // same key, merge the entries. Otherwise, copy the entry and merge 6859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // it with an empty entry. 6869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (ptr_const_iterator MI = Other.bottom_up_ptr_begin(), 6879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ME = Other.bottom_up_ptr_end(); MI != ME; ++MI) { 6889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall std::pair<ptr_iterator, bool> Pair = PerPtrBottomUp.insert(*MI); 6899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Pair.first->second.Merge(Pair.second ? PtrState() : MI->second, 6909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /*TopDown=*/false); 6919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 6929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 693fa7eed1f8eee4fd3839e589c3e0e84f79d248c8aDan Gohman // For each entry in our set, if the other set doesn't have an entry 6949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // with the same key, force it to merge with an empty entry. 6959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (ptr_iterator MI = bottom_up_ptr_begin(), 6969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ME = bottom_up_ptr_end(); MI != ME; ++MI) 6979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Other.PerPtrBottomUp.find(MI->first) == Other.PerPtrBottomUp.end()) 6989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MI->second.Merge(PtrState(), /*TopDown=*/false); 6999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 7009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 7019fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallnamespace { 70281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// \brief The main ARC optimization pass. 7039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall class ObjCARCOpt : public FunctionPass { 7049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool Changed; 7059fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ProvenanceAnalysis PA; 7069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 70781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// A flag indicating whether this optimization pass should run. 708c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman bool Run; 709c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman 71081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Declarations for ObjC runtime functions, for use in creating calls to 71181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// them. These are initialized lazily to avoid cluttering up the Module 71281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// with unused declarations. 71381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman 71481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Declaration for ObjC runtime function 71581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// objc_retainAutoreleasedReturnValue. 71681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman Constant *RetainRVCallee; 71781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Declaration for ObjC runtime function objc_autoreleaseReturnValue. 71881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman Constant *AutoreleaseRVCallee; 71981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Declaration for ObjC runtime function objc_release. 72081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman Constant *ReleaseCallee; 72181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Declaration for ObjC runtime function objc_retain. 72281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman Constant *RetainCallee; 72381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Declaration for ObjC runtime function objc_retainBlock. 72481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman Constant *RetainBlockCallee; 72581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Declaration for ObjC runtime function objc_autorelease. 72681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman Constant *AutoreleaseCallee; 72781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman 72881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// Flags which determine whether each of the interesting runtine functions 72981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// is in fact used in the current function. 7309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall unsigned UsedInThisFunction; 7319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 73281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The Metadata Kind for clang.imprecise_release metadata. 7339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall unsigned ImpreciseReleaseMDKind; 7349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 73581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The Metadata Kind for clang.arc.copy_on_escape metadata. 736a974beaa1f63394a67c38c66ff0f39a759c7998fDan Gohman unsigned CopyOnEscapeMDKind; 737a974beaa1f63394a67c38c66ff0f39a759c7998fDan Gohman 73881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The Metadata Kind for clang.arc.no_objc_arc_exceptions metadata. 739dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman unsigned NoObjCARCExceptionsMDKind; 740dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman 7419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Constant *getRetainRVCallee(Module *M); 7429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Constant *getAutoreleaseRVCallee(Module *M); 7439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Constant *getReleaseCallee(Module *M); 7449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Constant *getRetainCallee(Module *M); 7454428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman Constant *getRetainBlockCallee(Module *M); 7469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Constant *getAutoreleaseCallee(Module *M); 7479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 74879522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman bool IsRetainBlockOptimizable(const Instruction *Inst); 74979522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman 7509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void OptimizeRetainCall(Function &F, Instruction *Retain); 7519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV); 7520e385450fc62a69cf7c557173f2f5df132702379Michael Gottesman void OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV, 7530e385450fc62a69cf7c557173f2f5df132702379Michael Gottesman InstructionClass &Class); 7549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void OptimizeIndividualCalls(Function &F); 7559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 7569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void CheckForCFGHazards(const BasicBlock *BB, 7579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<const BasicBlock *, BBState> &BBStates, 7589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BBState &MyStates) const; 759c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman bool VisitInstructionBottomUp(Instruction *Inst, 760fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman BasicBlock *BB, 761c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman MapVector<Value *, RRInfo> &Retains, 762c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman BBState &MyStates); 7639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool VisitBottomUp(BasicBlock *BB, 7649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<const BasicBlock *, BBState> &BBStates, 7659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapVector<Value *, RRInfo> &Retains); 766c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman bool VisitInstructionTopDown(Instruction *Inst, 767c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman DenseMap<Value *, RRInfo> &Releases, 768c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman BBState &MyStates); 7699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool VisitTopDown(BasicBlock *BB, 7709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<const BasicBlock *, BBState> &BBStates, 7719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<Value *, RRInfo> &Releases); 7729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool Visit(Function &F, 7739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<const BasicBlock *, BBState> &BBStates, 7749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapVector<Value *, RRInfo> &Retains, 7759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<Value *, RRInfo> &Releases); 7769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 7779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void MoveCalls(Value *Arg, RRInfo &RetainsToMove, RRInfo &ReleasesToMove, 7789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapVector<Value *, RRInfo> &Retains, 7799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<Value *, RRInfo> &Releases, 7804428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman SmallVectorImpl<Instruction *> &DeadInsts, 7814428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman Module *M); 7829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 783862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman bool ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState> &BBStates, 784862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman MapVector<Value *, RRInfo> &Retains, 785862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman DenseMap<Value *, RRInfo> &Releases, 786862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Module *M, 787862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman SmallVector<Instruction *, 4> &NewRetains, 788862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman SmallVector<Instruction *, 4> &NewReleases, 789862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman SmallVector<Instruction *, 8> &DeadInsts, 790862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RRInfo &RetainsToMove, 791862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RRInfo &ReleasesToMove, 792862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Value *Arg, 793862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman bool KnownSafe, 794862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman bool &AnyPairsCompletelyEliminated); 795862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 7969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool PerformCodePlacement(DenseMap<const BasicBlock *, BBState> &BBStates, 7979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapVector<Value *, RRInfo> &Retains, 7984428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman DenseMap<Value *, RRInfo> &Releases, 7994428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman Module *M); 8009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8019fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void OptimizeWeakCalls(Function &F); 8029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool OptimizeSequences(Function &F); 8049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8059fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall void OptimizeReturns(Function &F); 8069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall virtual void getAnalysisUsage(AnalysisUsage &AU) const; 8089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall virtual bool doInitialization(Module &M); 8099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall virtual bool runOnFunction(Function &F); 8109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall virtual void releaseMemory(); 8119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall public: 8139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall static char ID; 8149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ObjCARCOpt() : FunctionPass(ID) { 8159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall initializeObjCARCOptPass(*PassRegistry::getPassRegistry()); 8169fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 8179fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall }; 8189fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 8199fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallchar ObjCARCOpt::ID = 0; 8219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallINITIALIZE_PASS_BEGIN(ObjCARCOpt, 8229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall "objc-arc", "ObjC ARC optimization", false, false) 8239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallINITIALIZE_PASS_DEPENDENCY(ObjCARCAliasAnalysis) 8249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallINITIALIZE_PASS_END(ObjCARCOpt, 8259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall "objc-arc", "ObjC ARC optimization", false, false) 8269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallPass *llvm::createObjCARCOptPass() { 8289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return new ObjCARCOpt(); 8299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 8309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid ObjCARCOpt::getAnalysisUsage(AnalysisUsage &AU) const { 8329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AU.addRequired<ObjCARCAliasAnalysis>(); 8339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AU.addRequired<AliasAnalysis>(); 8349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // ARC optimization doesn't currently split critical edges. 8359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AU.setPreservesCFG(); 8369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 8379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 83879522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohmanbool ObjCARCOpt::IsRetainBlockOptimizable(const Instruction *Inst) { 83979522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // Without the magic metadata tag, we have to assume this might be an 84079522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // objc_retainBlock call inserted to convert a block pointer to an id, 84179522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // in which case it really is needed. 84279522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman if (!Inst->getMetadata(CopyOnEscapeMDKind)) 84379522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman return false; 84479522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman 84579522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // If the pointer "escapes" (not including being used in a call), 84679522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // the copy may be needed. 84782b83011a1e330e41147dbad97e44939840ba755Michael Gottesman if (DoesRetainableObjPtrEscape(Inst)) 84879522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman return false; 84979522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman 85079522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // Otherwise, it's not needed. 85179522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman return true; 85279522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman} 85379522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman 8549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallConstant *ObjCARCOpt::getRetainRVCallee(Module *M) { 8559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!RetainRVCallee) { 8569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall LLVMContext &C = M->getContext(); 8575fdd6c8793462549e3593890ec61573da06e3346Jay Foad Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C)); 8580daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Type *Params[] = { I8X }; 8590daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false); 860034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling AttributeSet Attribute = 861defaca00b8087d452df2b783250a48a32658a910Bill Wendling AttributeSet().addAttribute(M->getContext(), AttributeSet::FunctionIndex, 862defaca00b8087d452df2b783250a48a32658a910Bill Wendling Attribute::NoUnwind); 8639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RetainRVCallee = 8649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall M->getOrInsertFunction("objc_retainAutoreleasedReturnValue", FTy, 865034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling Attribute); 8669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 8679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return RetainRVCallee; 8689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 8699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallConstant *ObjCARCOpt::getAutoreleaseRVCallee(Module *M) { 8719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!AutoreleaseRVCallee) { 8729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall LLVMContext &C = M->getContext(); 8735fdd6c8793462549e3593890ec61573da06e3346Jay Foad Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C)); 8740daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Type *Params[] = { I8X }; 8750daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false); 876034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling AttributeSet Attribute = 877defaca00b8087d452df2b783250a48a32658a910Bill Wendling AttributeSet().addAttribute(M->getContext(), AttributeSet::FunctionIndex, 878defaca00b8087d452df2b783250a48a32658a910Bill Wendling Attribute::NoUnwind); 8799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AutoreleaseRVCallee = 8809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall M->getOrInsertFunction("objc_autoreleaseReturnValue", FTy, 881034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling Attribute); 8829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 8839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return AutoreleaseRVCallee; 8849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 8859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 8869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallConstant *ObjCARCOpt::getReleaseCallee(Module *M) { 8879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!ReleaseCallee) { 8889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall LLVMContext &C = M->getContext(); 8890daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) }; 890034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling AttributeSet Attribute = 891defaca00b8087d452df2b783250a48a32658a910Bill Wendling AttributeSet().addAttribute(M->getContext(), AttributeSet::FunctionIndex, 892defaca00b8087d452df2b783250a48a32658a910Bill Wendling Attribute::NoUnwind); 8939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ReleaseCallee = 8949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall M->getOrInsertFunction( 8959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall "objc_release", 8969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall FunctionType::get(Type::getVoidTy(C), Params, /*isVarArg=*/false), 897034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling Attribute); 8989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 8999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return ReleaseCallee; 9009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 9019fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 9029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallConstant *ObjCARCOpt::getRetainCallee(Module *M) { 9039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!RetainCallee) { 9049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall LLVMContext &C = M->getContext(); 9050daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) }; 906034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling AttributeSet Attribute = 907defaca00b8087d452df2b783250a48a32658a910Bill Wendling AttributeSet().addAttribute(M->getContext(), AttributeSet::FunctionIndex, 908defaca00b8087d452df2b783250a48a32658a910Bill Wendling Attribute::NoUnwind); 9099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RetainCallee = 9109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall M->getOrInsertFunction( 9119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall "objc_retain", 9129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall FunctionType::get(Params[0], Params, /*isVarArg=*/false), 913034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling Attribute); 9149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 9159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return RetainCallee; 9169fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 9179fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 9184428069f10ac6e7efb55826437c82428d4bbe03eDan GohmanConstant *ObjCARCOpt::getRetainBlockCallee(Module *M) { 9194428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman if (!RetainBlockCallee) { 9204428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman LLVMContext &C = M->getContext(); 9210daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) }; 9221d2fd75e3b60314210934078915aa573a2727854Dan Gohman // objc_retainBlock is not nounwind because it calls user copy constructors 9231d2fd75e3b60314210934078915aa573a2727854Dan Gohman // which could theoretically throw. 9244428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman RetainBlockCallee = 9254428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman M->getOrInsertFunction( 9264428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman "objc_retainBlock", 9274428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman FunctionType::get(Params[0], Params, /*isVarArg=*/false), 92899faa3b4ec6d03ac7808fe4ff3fbf3d04e375502Bill Wendling AttributeSet()); 9294428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman } 9304428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman return RetainBlockCallee; 9314428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman} 9324428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman 9339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallConstant *ObjCARCOpt::getAutoreleaseCallee(Module *M) { 9349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!AutoreleaseCallee) { 9359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall LLVMContext &C = M->getContext(); 9360daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) }; 937034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling AttributeSet Attribute = 938defaca00b8087d452df2b783250a48a32658a910Bill Wendling AttributeSet().addAttribute(M->getContext(), AttributeSet::FunctionIndex, 939defaca00b8087d452df2b783250a48a32658a910Bill Wendling Attribute::NoUnwind); 9409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AutoreleaseCallee = 9419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall M->getOrInsertFunction( 9429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall "objc_autorelease", 9439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall FunctionType::get(Params[0], Params, /*isVarArg=*/false), 944034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling Attribute); 9459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 9469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return AutoreleaseCallee; 9479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 9489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 94981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Turn objc_retain into objc_retainAutoreleasedReturnValue if the operand is a 95081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// return value. 9519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid 9529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallObjCARCOpt::OptimizeRetainCall(Function &F, Instruction *Retain) { 953447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman ImmutableCallSite CS(GetObjCArg(Retain)); 954447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman const Instruction *Call = CS.getInstruction(); 9559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!Call) return; 9569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Call->getParent() != Retain->getParent()) return; 9579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 9589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Check that the call is next to the retain. 959447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman BasicBlock::const_iterator I = Call; 9609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++I; 9619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall while (isNoopInstruction(I)) ++I; 9629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (&*I != Retain) 9639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return; 9649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 9659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Turn it to an objc_retainAutoreleasedReturnValue.. 9669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 9679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++NumPeeps; 9682f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 969715f6a62a17f1e26a7c3f673b70bf44c99ae7caeMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeRetainCall: Transforming " 970e7a715f61e7855a280734063989a1001320e85deMichael Gottesman "objc_retain => objc_retainAutoreleasedReturnValue" 971e7a715f61e7855a280734063989a1001320e85deMichael Gottesman " since the operand is a return value.\n" 972715f6a62a17f1e26a7c3f673b70bf44c99ae7caeMichael Gottesman " Old: " 973715f6a62a17f1e26a7c3f673b70bf44c99ae7caeMichael Gottesman << *Retain << "\n"); 9742f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 9759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall cast<CallInst>(Retain)->setCalledFunction(getRetainRVCallee(F.getParent())); 976715f6a62a17f1e26a7c3f673b70bf44c99ae7caeMichael Gottesman 977715f6a62a17f1e26a7c3f673b70bf44c99ae7caeMichael Gottesman DEBUG(dbgs() << " New: " 978715f6a62a17f1e26a7c3f673b70bf44c99ae7caeMichael Gottesman << *Retain << "\n"); 9799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 9809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 98181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is 98281c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// not a return value. Or, if it can be paired with an 98381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// objc_autoreleaseReturnValue, delete the pair and return true. 9849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallbool 9859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) { 9866fedb3c4016b8f706c472280a3a9b22430c73ef4Dan Gohman // Check for the argument being from an immediately preceding call or invoke. 987447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman const Value *Arg = GetObjCArg(RetainRV); 988447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman ImmutableCallSite CS(Arg); 989447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman if (const Instruction *Call = CS.getInstruction()) { 9909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Call->getParent() == RetainRV->getParent()) { 991447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman BasicBlock::const_iterator I = Call; 9929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++I; 9939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall while (isNoopInstruction(I)) ++I; 9949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (&*I == RetainRV) 9959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return false; 996447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman } else if (const InvokeInst *II = dyn_cast<InvokeInst>(Call)) { 9976fedb3c4016b8f706c472280a3a9b22430c73ef4Dan Gohman BasicBlock *RetainRVParent = RetainRV->getParent(); 9986fedb3c4016b8f706c472280a3a9b22430c73ef4Dan Gohman if (II->getNormalDest() == RetainRVParent) { 999447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman BasicBlock::const_iterator I = RetainRVParent->begin(); 10006fedb3c4016b8f706c472280a3a9b22430c73ef4Dan Gohman while (isNoopInstruction(I)) ++I; 10016fedb3c4016b8f706c472280a3a9b22430c73ef4Dan Gohman if (&*I == RetainRV) 10026fedb3c4016b8f706c472280a3a9b22430c73ef4Dan Gohman return false; 10036fedb3c4016b8f706c472280a3a9b22430c73ef4Dan Gohman } 10049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 10056fedb3c4016b8f706c472280a3a9b22430c73ef4Dan Gohman } 10069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 10079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Check for being preceded by an objc_autoreleaseReturnValue on the same 10089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // pointer. In this case, we can delete the pair. 10099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BasicBlock::iterator I = RetainRV, Begin = RetainRV->getParent()->begin(); 10109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (I != Begin) { 10119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall do --I; while (I != Begin && isNoopInstruction(I)); 10129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (GetBasicInstructionClass(I) == IC_AutoreleaseRV && 10139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall GetObjCArg(I) == Arg) { 10149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 10159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++NumPeeps; 10162f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 101787a0f02953147bf1bf840ccb92ee046aa9b190f5Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeRetainRVCall: Erasing " << *I << "\n" 101887a0f02953147bf1bf840ccb92ee046aa9b190f5Michael Gottesman << " Erasing " << *RetainRV 101987a0f02953147bf1bf840ccb92ee046aa9b190f5Michael Gottesman << "\n"); 10202f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 10219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall EraseInstruction(I); 10229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall EraseInstruction(RetainRV); 10239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return true; 10249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 10259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 10269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 10279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Turn it to a plain objc_retain. 10289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 10299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++NumPeeps; 10302f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 103136e4bc406ca93f5ebd8e8b67cbf5d236c8423cbeMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeRetainRVCall: Transforming " 103236e4bc406ca93f5ebd8e8b67cbf5d236c8423cbeMichael Gottesman "objc_retainAutoreleasedReturnValue => " 103336e4bc406ca93f5ebd8e8b67cbf5d236c8423cbeMichael Gottesman "objc_retain since the operand is not a return value.\n" 103436e4bc406ca93f5ebd8e8b67cbf5d236c8423cbeMichael Gottesman " Old: " 103536e4bc406ca93f5ebd8e8b67cbf5d236c8423cbeMichael Gottesman << *RetainRV << "\n"); 10362f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 10379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall cast<CallInst>(RetainRV)->setCalledFunction(getRetainCallee(F.getParent())); 103836e4bc406ca93f5ebd8e8b67cbf5d236c8423cbeMichael Gottesman 103936e4bc406ca93f5ebd8e8b67cbf5d236c8423cbeMichael Gottesman DEBUG(dbgs() << " New: " 104036e4bc406ca93f5ebd8e8b67cbf5d236c8423cbeMichael Gottesman << *RetainRV << "\n"); 104136e4bc406ca93f5ebd8e8b67cbf5d236c8423cbeMichael Gottesman 10429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return false; 10439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 10449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 104581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Turn objc_autoreleaseReturnValue into objc_autorelease if the result is not 104681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// used as a return value. 10479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid 10480e385450fc62a69cf7c557173f2f5df132702379Michael GottesmanObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV, 10490e385450fc62a69cf7c557173f2f5df132702379Michael Gottesman InstructionClass &Class) { 10509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Check for a return of the pointer value. 10519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const Value *Ptr = GetObjCArg(AutoreleaseRV); 1052126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman SmallVector<const Value *, 2> Users; 1053126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman Users.push_back(Ptr); 1054126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman do { 1055126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman Ptr = Users.pop_back_val(); 1056126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman for (Value::const_use_iterator UI = Ptr->use_begin(), UE = Ptr->use_end(); 1057126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman UI != UE; ++UI) { 1058126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman const User *I = *UI; 1059126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman if (isa<ReturnInst>(I) || GetBasicInstructionClass(I) == IC_RetainRV) 1060126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman return; 1061126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman if (isa<BitCastInst>(I)) 1062126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman Users.push_back(I); 1063126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman } 1064126a54f1fa233d9da377a3e9f2ae85ff5fe34d9fDan Gohman } while (!Users.empty()); 10659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 10669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 10679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++NumPeeps; 106848239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman 106948239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeAutoreleaseRVCall: Transforming " 107048239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman "objc_autoreleaseReturnValue => " 107148239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman "objc_autorelease since its operand is not used as a return " 107248239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman "value.\n" 107348239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman " Old: " 107448239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman << *AutoreleaseRV << "\n"); 107548239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman 1076e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman CallInst *AutoreleaseRVCI = cast<CallInst>(AutoreleaseRV); 1077e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman AutoreleaseRVCI-> 10789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall setCalledFunction(getAutoreleaseCallee(F.getParent())); 1079e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman AutoreleaseRVCI->setTailCall(false); // Never tail call objc_autorelease. 10800e385450fc62a69cf7c557173f2f5df132702379Michael Gottesman Class = IC_Autorelease; 10812f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 108248239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman DEBUG(dbgs() << " New: " 108348239c753abd4bdc9424f6df2b8ddd43840f93c3Michael Gottesman << *AutoreleaseRV << "\n"); 10842f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 10859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 10869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 108781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Visit each call, one at a time, and make simplifications without doing any 108881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// additional analysis. 10899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid ObjCARCOpt::OptimizeIndividualCalls(Function &F) { 10909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Reset all the flags in preparation for recomputing them. 10919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall UsedInThisFunction = 0; 10929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 10939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Visit all objc_* calls in F. 10949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) { 10959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *Inst = &*I++; 10968f22c8b5e1f32bf253f968a81542a76dbfc3efc7Michael Gottesman 10979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall InstructionClass Class = GetBasicInstructionClass(Inst); 10989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1099268e0ffa78483512ad65002cb2081ab88b0f52a8Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Visiting: Class: " 1100268e0ffa78483512ad65002cb2081ab88b0f52a8Michael Gottesman << Class << "; " << *Inst << "\n"); 110188ceb186f156136592c71021585e847c073612ccMichael Gottesman 11029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall switch (Class) { 11039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall default: break; 11049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 11059fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Delete no-op casts. These function calls have special semantics, but 11069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // the semantics are entirely implemented via lowering in the front-end, 11079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // so by the time they reach the optimizer, they are just no-op calls 11089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // which return their argument. 11099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // 11109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // There are gray areas here, as the ability to cast reference-counted 11119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // pointers to raw void* and back allows code to break ARC assumptions, 11129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // however these are currently considered to be unimportant. 11139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_NoopCast: 11149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 11159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++NumNoops; 11164680abec929e5415da8a918debcee786389aa592Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Erasing no-op cast:" 11174680abec929e5415da8a918debcee786389aa592Michael Gottesman " " << *Inst << "\n"); 11189fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall EraseInstruction(Inst); 11199fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 11209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 11219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If the pointer-to-weak-pointer is null, it's undefined behavior. 11229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_StoreWeak: 11239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_LoadWeak: 11249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_LoadWeakRetained: 11259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_InitWeak: 11269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_DestroyWeak: { 11279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *CI = cast<CallInst>(Inst); 11289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (isNullOrUndef(CI->getArgOperand(0))) { 1129d6bf201fa20a5cd3aa9f61767081d1d03d8aee3cDan Gohman Changed = true; 1130db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *Ty = CI->getArgOperand(0)->getType(); 11319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall new StoreInst(UndefValue::get(cast<PointerType>(Ty)->getElementType()), 11329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Constant::getNullValue(Ty), 11339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CI); 11342f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman llvm::Value *NewValue = UndefValue::get(CI->getType()); 1135e549492c3680814b31058b183d315d69fd9293deMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: A null " 1136e549492c3680814b31058b183d315d69fd9293deMichael Gottesman "pointer-to-weak-pointer is undefined behavior.\n" 1137e549492c3680814b31058b183d315d69fd9293deMichael Gottesman " Old = " << *CI << 1138e549492c3680814b31058b183d315d69fd9293deMichael Gottesman "\n New = " << 11392f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman *NewValue << "\n"); 1140e549492c3680814b31058b183d315d69fd9293deMichael Gottesman CI->replaceAllUsesWith(NewValue); 11419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CI->eraseFromParent(); 11429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 11439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 11449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 11459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 11469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_CopyWeak: 11479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_MoveWeak: { 11489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *CI = cast<CallInst>(Inst); 11499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (isNullOrUndef(CI->getArgOperand(0)) || 11509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall isNullOrUndef(CI->getArgOperand(1))) { 1151d6bf201fa20a5cd3aa9f61767081d1d03d8aee3cDan Gohman Changed = true; 1152db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *Ty = CI->getArgOperand(0)->getType(); 11539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall new StoreInst(UndefValue::get(cast<PointerType>(Ty)->getElementType()), 11549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Constant::getNullValue(Ty), 11559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CI); 1156e549492c3680814b31058b183d315d69fd9293deMichael Gottesman 1157e549492c3680814b31058b183d315d69fd9293deMichael Gottesman llvm::Value *NewValue = UndefValue::get(CI->getType()); 1158e549492c3680814b31058b183d315d69fd9293deMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: A null " 1159e549492c3680814b31058b183d315d69fd9293deMichael Gottesman "pointer-to-weak-pointer is undefined behavior.\n" 1160e549492c3680814b31058b183d315d69fd9293deMichael Gottesman " Old = " << *CI << 1161e549492c3680814b31058b183d315d69fd9293deMichael Gottesman "\n New = " << 1162e549492c3680814b31058b183d315d69fd9293deMichael Gottesman *NewValue << "\n"); 11632f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 1164e549492c3680814b31058b183d315d69fd9293deMichael Gottesman CI->replaceAllUsesWith(NewValue); 11659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CI->eraseFromParent(); 11669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 11679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 11689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 11699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 11709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_Retain: 11719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall OptimizeRetainCall(F, Inst); 11729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 11739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_RetainRV: 11749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (OptimizeRetainRVCall(F, Inst)) 11759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 11769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 11779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_AutoreleaseRV: 11780e385450fc62a69cf7c557173f2f5df132702379Michael Gottesman OptimizeAutoreleaseRVCall(F, Inst, Class); 11799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 11809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 11819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 11829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // objc_autorelease(x) -> objc_release(x) if x is otherwise unused. 11839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (IsAutorelease(Class) && Inst->use_empty()) { 11849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *Call = cast<CallInst>(Inst); 11859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const Value *Arg = Call->getArgOperand(0); 11869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Arg = FindSingleUseIdentifiedObject(Arg); 11879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Arg) { 11889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 11899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++NumAutoreleases; 11909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 11919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Create the declaration lazily. 11929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall LLVMContext &C = Inst->getContext(); 11939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *NewCall = 11949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst::Create(getReleaseCallee(F.getParent()), 11959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Call->getArgOperand(0), "", Call); 11969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall NewCall->setMetadata(ImpreciseReleaseMDKind, 11979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MDNode::get(C, ArrayRef<Value *>())); 11982f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 119920d9fff206ebb21d08f61783462ca56d5efe0af9Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Replacing " 120020d9fff206ebb21d08f61783462ca56d5efe0af9Michael Gottesman "objc_autorelease(x) with objc_release(x) since x is " 120120d9fff206ebb21d08f61783462ca56d5efe0af9Michael Gottesman "otherwise unused.\n" 1202795612702ec46412414b923a33e71fd3a080e826Michael Gottesman " Old: " << *Call << 120320d9fff206ebb21d08f61783462ca56d5efe0af9Michael Gottesman "\n New: " << 120420d9fff206ebb21d08f61783462ca56d5efe0af9Michael Gottesman *NewCall << "\n"); 12052f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 12069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall EraseInstruction(Call); 12079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Inst = NewCall; 12089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Class = IC_Release; 12099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 12109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 12119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 12129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // For functions which can never be passed stack arguments, add 12139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // a tail keyword. 12149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (IsAlwaysTail(Class)) { 12159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 1216817d4e942bf7e7ef51002eb905e5751b44c51223Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Adding tail keyword" 1217817d4e942bf7e7ef51002eb905e5751b44c51223Michael Gottesman " to function since it can never be passed stack args: " << *Inst << 1218817d4e942bf7e7ef51002eb905e5751b44c51223Michael Gottesman "\n"); 12199fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall cast<CallInst>(Inst)->setTailCall(); 12209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 12219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1222e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman // Ensure that functions that can never have a "tail" keyword due to the 1223e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman // semantics of ARC truly do not do so. 1224e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman if (IsNeverTail(Class)) { 1225e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman Changed = true; 12267899e47f205f32127ec2b6229ca587e996e0a08eMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Removing tail " 12277899e47f205f32127ec2b6229ca587e996e0a08eMichael Gottesman "keyword from function: " << *Inst << 1228e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman "\n"); 1229e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman cast<CallInst>(Inst)->setTailCall(false); 1230e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman } 1231e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman 12329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Set nounwind as needed. 12339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (IsNoThrow(Class)) { 12349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 123538bc25a52e7f0019c7339371f2eca080269dd6afMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Found no throw" 123638bc25a52e7f0019c7339371f2eca080269dd6afMichael Gottesman " class. Setting nounwind on: " << *Inst << "\n"); 12379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall cast<CallInst>(Inst)->setDoesNotThrow(); 12389fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 12399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 12409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!IsNoopOnNull(Class)) { 12419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall UsedInThisFunction |= 1 << Class; 12429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 12439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 12449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 12459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const Value *Arg = GetObjCArg(Inst); 12469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 12479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // ARC calls with null are no-ops. Delete them. 12489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (isNullOrUndef(Arg)) { 12499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 12509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++NumNoops; 1251fbe4d6b1fa256825ded9d9ebf1b6aeca3d1ff270Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: ARC calls with " 1252fbe4d6b1fa256825ded9d9ebf1b6aeca3d1ff270Michael Gottesman " null are no-ops. Erasing: " << *Inst << "\n"); 12539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall EraseInstruction(Inst); 12549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 12559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 12569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 12579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Keep track of which of retain, release, autorelease, and retain_block 12589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // are actually present in this function. 12599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall UsedInThisFunction |= 1 << Class; 12609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 12619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If Arg is a PHI, and one or more incoming values to the 12629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // PHI are null, and the call is control-equivalent to the PHI, and there 12639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // are no relevant side effects between the PHI and the call, the call 12649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // could be pushed up to just those paths with non-null incoming values. 12659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // For now, don't bother splitting critical edges for this. 12669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallVector<std::pair<Instruction *, const Value *>, 4> Worklist; 12679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Worklist.push_back(std::make_pair(Inst, Arg)); 12689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall do { 12699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall std::pair<Instruction *, const Value *> Pair = Worklist.pop_back_val(); 12709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Inst = Pair.first; 12719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Arg = Pair.second; 12729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 12739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const PHINode *PN = dyn_cast<PHINode>(Arg); 12749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!PN) continue; 12759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 12769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Determine if the PHI has any null operands, or any incoming 12779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // critical edges. 12789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool HasNull = false; 12799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool HasCriticalEdges = false; 12809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { 12819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *Incoming = 12829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall StripPointerCastsAndObjCCalls(PN->getIncomingValue(i)); 12839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (isNullOrUndef(Incoming)) 12849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall HasNull = true; 12859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall else if (cast<TerminatorInst>(PN->getIncomingBlock(i)->back()) 12869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall .getNumSuccessors() != 1) { 12879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall HasCriticalEdges = true; 12889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 12899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 12909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 12919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If we have null operands and no critical edges, optimize. 12929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!HasCriticalEdges && HasNull) { 12939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallPtrSet<Instruction *, 4> DependingInstructions; 12949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallPtrSet<const BasicBlock *, 4> Visited; 12959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 12969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Check that there is nothing that cares about the reference 12979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // count between the call and the phi. 1298511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman switch (Class) { 1299511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman case IC_Retain: 1300511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman case IC_RetainBlock: 1301511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman // These can always be moved up. 1302511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman break; 1303511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman case IC_Release: 13040daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman // These can't be moved across things that care about the retain 13050daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman // count. 1306511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman FindDependencies(NeedsPositiveRetainCount, Arg, 1307511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman Inst->getParent(), Inst, 1308511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman DependingInstructions, Visited, PA); 1309511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman break; 1310511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman case IC_Autorelease: 1311511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman // These can't be moved across autorelease pool scope boundaries. 1312511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman FindDependencies(AutoreleasePoolBoundary, Arg, 1313511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman Inst->getParent(), Inst, 1314511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman DependingInstructions, Visited, PA); 1315511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman break; 1316511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman case IC_RetainRV: 1317511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman case IC_AutoreleaseRV: 1318511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman // Don't move these; the RV optimization depends on the autoreleaseRV 1319511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman // being tail called, and the retainRV being immediately after a call 1320511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman // (which might still happen if we get lucky with codegen layout, but 1321511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman // it's not worth taking the chance). 1322511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman continue; 1323511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman default: 1324511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman llvm_unreachable("Invalid dependence flavor"); 1325511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman } 1326511568dd1f9863de1633b0db8bb105f783e8ac50Dan Gohman 13279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (DependingInstructions.size() == 1 && 13289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall *DependingInstructions.begin() == PN) { 13299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 13309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++NumPartialNoops; 13319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Clone the call into each predecessor that has a non-null value. 13329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *CInst = cast<CallInst>(Inst); 1333db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *ParamTy = CInst->getArgOperand(0)->getType(); 13349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { 13359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *Incoming = 13369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall StripPointerCastsAndObjCCalls(PN->getIncomingValue(i)); 13379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!isNullOrUndef(Incoming)) { 13389fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *Clone = cast<CallInst>(CInst->clone()); 13399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *Op = PN->getIncomingValue(i); 13409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *InsertPos = &PN->getIncomingBlock(i)->back(); 13419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Op->getType() != ParamTy) 13429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Op = new BitCastInst(Op, ParamTy, "", InsertPos); 13439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Clone->setArgOperand(0, Op); 13449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Clone->insertBefore(InsertPos); 13455581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman 13465581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Cloning " 13475581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman << *CInst << "\n" 13485581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman " And inserting " 13495581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman "clone at " << *InsertPos << "\n"); 13509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Worklist.push_back(std::make_pair(Clone, Incoming)); 13519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 13529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 13539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Erase the original call. 13545581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman DEBUG(dbgs() << "Erasing: " << *CInst << "\n"); 13559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall EraseInstruction(CInst); 13569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 13579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 13589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 13599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } while (!Worklist.empty()); 13609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 13610d3582b1d1bedde39f964420edd237583bc5a010Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Finished List.\n"); 13629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 13639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 136481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Check for critical edges, loop boundaries, irreducible control flow, or 136581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// other CFG structures where moving code across the edge would result in it 136681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// being executed more. 13679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid 13689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB, 13699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<const BasicBlock *, BBState> &BBStates, 13709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BBState &MyStates) const { 13719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If any top-down local-use or possible-dec has a succ which is earlier in 13729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // the sequence, forget it. 137322cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman for (BBState::ptr_iterator I = MyStates.top_down_ptr_begin(), 13749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall E = MyStates.top_down_ptr_end(); I != E; ++I) 13759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall switch (I->second.GetSeq()) { 13769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall default: break; 13779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Use: { 13789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const Value *Arg = I->first; 13799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const TerminatorInst *TI = cast<TerminatorInst>(&BB->back()); 13809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool SomeSuccHasSame = false; 13819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool AllSuccsHaveSame = true; 138222cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman PtrState &S = I->second; 1383dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman succ_const_iterator SI(TI), SE(TI, false); 1384dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman 1385dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman for (; SI != SE; ++SI) { 138670e2968866aa09b4c164db77d310f5d43a588227Dan Gohman Sequence SuccSSeq = S_None; 138770e2968866aa09b4c164db77d310f5d43a588227Dan Gohman bool SuccSRRIKnownSafe = false; 13880daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman // If VisitBottomUp has pointer information for this successor, take 13890daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman // what we know about it. 1390447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman DenseMap<const BasicBlock *, BBState>::iterator BBI = 1391447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman BBStates.find(*SI); 1392447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman assert(BBI != BBStates.end()); 1393447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman const PtrState &SuccS = BBI->second.getPtrBottomUpState(Arg); 1394447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman SuccSSeq = SuccS.GetSeq(); 1395447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman SuccSRRIKnownSafe = SuccS.RRI.KnownSafe; 139670e2968866aa09b4c164db77d310f5d43a588227Dan Gohman switch (SuccSSeq) { 13979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_None: 1398a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman case S_CanRelease: { 139970e2968866aa09b4c164db77d310f5d43a588227Dan Gohman if (!S.RRI.KnownSafe && !SuccSRRIKnownSafe) { 1400a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman S.ClearSequenceProgress(); 140170e2968866aa09b4c164db77d310f5d43a588227Dan Gohman break; 140270e2968866aa09b4c164db77d310f5d43a588227Dan Gohman } 1403a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman continue; 1404a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman } 14059fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Use: 14069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SomeSuccHasSame = true; 14079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 14089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Stop: 14099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Release: 14109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_MovableRelease: 141170e2968866aa09b4c164db77d310f5d43a588227Dan Gohman if (!S.RRI.KnownSafe && !SuccSRRIKnownSafe) 1412a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman AllSuccsHaveSame = false; 14139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 14149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Retain: 14159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall llvm_unreachable("bottom-up pointer in retain state!"); 14169fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1417a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman } 14189fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If the state at the other end of any of the successor edges 14199fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // matches the current state, require all edges to match. This 14209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // guards against loops in the middle of a sequence. 14219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (SomeSuccHasSame && !AllSuccsHaveSame) 1422a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman S.ClearSequenceProgress(); 14232e68beb36afad1fbf578b10a012e655690c47120Dan Gohman break; 14249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 14259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_CanRelease: { 14269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const Value *Arg = I->first; 14279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const TerminatorInst *TI = cast<TerminatorInst>(&BB->back()); 14289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool SomeSuccHasSame = false; 14299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool AllSuccsHaveSame = true; 143022cc4ccc9ea4a45d1f529c1bf48d61a88d3615deDan Gohman PtrState &S = I->second; 1431dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman succ_const_iterator SI(TI), SE(TI, false); 1432dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman 1433dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman for (; SI != SE; ++SI) { 143470e2968866aa09b4c164db77d310f5d43a588227Dan Gohman Sequence SuccSSeq = S_None; 143570e2968866aa09b4c164db77d310f5d43a588227Dan Gohman bool SuccSRRIKnownSafe = false; 14360daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman // If VisitBottomUp has pointer information for this successor, take 14370daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman // what we know about it. 1438447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman DenseMap<const BasicBlock *, BBState>::iterator BBI = 1439447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman BBStates.find(*SI); 1440447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman assert(BBI != BBStates.end()); 1441447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman const PtrState &SuccS = BBI->second.getPtrBottomUpState(Arg); 1442447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman SuccSSeq = SuccS.GetSeq(); 1443447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman SuccSRRIKnownSafe = SuccS.RRI.KnownSafe; 144470e2968866aa09b4c164db77d310f5d43a588227Dan Gohman switch (SuccSSeq) { 1445a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman case S_None: { 144670e2968866aa09b4c164db77d310f5d43a588227Dan Gohman if (!S.RRI.KnownSafe && !SuccSRRIKnownSafe) { 1447a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman S.ClearSequenceProgress(); 144870e2968866aa09b4c164db77d310f5d43a588227Dan Gohman break; 144970e2968866aa09b4c164db77d310f5d43a588227Dan Gohman } 1450a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman continue; 1451a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman } 14529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_CanRelease: 14539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SomeSuccHasSame = true; 14549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 14559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Stop: 14569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Release: 14579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_MovableRelease: 14589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Use: 145970e2968866aa09b4c164db77d310f5d43a588227Dan Gohman if (!S.RRI.KnownSafe && !SuccSRRIKnownSafe) 1460a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman AllSuccsHaveSame = false; 14619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 14629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Retain: 14639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall llvm_unreachable("bottom-up pointer in retain state!"); 14649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1465a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman } 14669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If the state at the other end of any of the successor edges 14679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // matches the current state, require all edges to match. This 14689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // guards against loops in the middle of a sequence. 14699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (SomeSuccHasSame && !AllSuccsHaveSame) 1470a7f7db2ebd4d3ca5c4e50cb2f9047dd85a34c6c8Dan Gohman S.ClearSequenceProgress(); 14712e68beb36afad1fbf578b10a012e655690c47120Dan Gohman break; 14729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 14739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 14749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 14759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 14769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallbool 1477c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan GohmanObjCARCOpt::VisitInstructionBottomUp(Instruction *Inst, 1478fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman BasicBlock *BB, 1479c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman MapVector<Value *, RRInfo> &Retains, 1480c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman BBState &MyStates) { 1481c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman bool NestingDetected = false; 1482c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman InstructionClass Class = GetInstructionClass(Inst); 1483c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman const Value *Arg = 0; 1484c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1485c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman switch (Class) { 1486c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_Release: { 1487c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman Arg = GetObjCArg(Inst); 1488c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1489c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman PtrState &S = MyStates.getPtrBottomUpState(Arg); 1490c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1491c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // If we see two releases in a row on the same pointer. If so, make 1492c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // a note, and we'll cicle back to revisit it after we've 1493c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // hopefully eliminated the second release, which may allow us to 1494c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // eliminate the first release too. 1495c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Theoretically we could implement removal of nested retain+release 1496c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // pairs by making PtrState hold a stack of states, but this is 1497c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // simple and avoids adding overhead for the non-nested case. 1498cf14005185778d823631a2367401e65b5e4802d8Michael Gottesman if (S.GetSeq() == S_Release || S.GetSeq() == S_MovableRelease) { 1499cf14005185778d823631a2367401e65b5e4802d8Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::VisitInstructionBottomUp: Found nested " 1500cf14005185778d823631a2367401e65b5e4802d8Michael Gottesman "releases (i.e. a release pair)\n"); 1501c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman NestingDetected = true; 1502cf14005185778d823631a2367401e65b5e4802d8Michael Gottesman } 1503c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1504c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman MDNode *ReleaseMetadata = Inst->getMetadata(ImpreciseReleaseMDKind); 150550ade659829269f0338cd1bfa0a574dcec62562eDan Gohman S.ResetSequenceProgress(ReleaseMetadata ? S_MovableRelease : S_Release); 1506c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.ReleaseMetadata = ReleaseMetadata; 1507230768bd1316a012e88ac62689589fe5e2f10456Dan Gohman S.RRI.KnownSafe = S.IsKnownIncremented(); 1508c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.IsTailCallRelease = cast<CallInst>(Inst)->isTailCall(); 1509c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.Calls.insert(Inst); 1510c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1511230768bd1316a012e88ac62689589fe5e2f10456Dan Gohman S.SetKnownPositiveRefCount(); 1512c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1513c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1514c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_RetainBlock: 1515c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // An objc_retainBlock call with just a use may need to be kept, 1516c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // because it may be copying a block from the stack to the heap. 1517c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (!IsRetainBlockOptimizable(Inst)) 1518c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1519c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // FALLTHROUGH 1520c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_Retain: 1521c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_RetainRV: { 1522c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman Arg = GetObjCArg(Inst); 1523c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1524c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman PtrState &S = MyStates.getPtrBottomUpState(Arg); 152550ade659829269f0338cd1bfa0a574dcec62562eDan Gohman S.SetKnownPositiveRefCount(); 1526c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1527c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman switch (S.GetSeq()) { 1528c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Stop: 1529c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Release: 1530c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_MovableRelease: 1531c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Use: 1532c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.ReverseInsertPts.clear(); 1533c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // FALL THROUGH 1534c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_CanRelease: 1535c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Don't do retain+release tracking for IC_RetainRV, because it's 1536c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // better to let it remain as the first instruction after a call. 1537c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (Class != IC_RetainRV) { 1538c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.IsRetainBlock = Class == IC_RetainBlock; 1539c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman Retains[Inst] = S.RRI; 1540c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1541c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.ClearSequenceProgress(); 1542c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1543c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_None: 1544c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1545c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Retain: 1546c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman llvm_unreachable("bottom-up pointer in retain state!"); 1547c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1548c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman return NestingDetected; 1549c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1550c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_AutoreleasepoolPop: 1551c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Conservatively, clear MyStates for all known pointers. 1552c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman MyStates.clearBottomUpPointers(); 1553c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman return NestingDetected; 1554c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_AutoreleasepoolPush: 1555c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_None: 1556c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // These are irrelevant. 1557c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman return NestingDetected; 1558c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman default: 1559c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1560c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1561c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1562c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Consider any other possible effects of this instruction on each 1563c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // pointer being tracked. 1564c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman for (BBState::ptr_iterator MI = MyStates.bottom_up_ptr_begin(), 1565c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman ME = MyStates.bottom_up_ptr_end(); MI != ME; ++MI) { 1566c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman const Value *Ptr = MI->first; 1567c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (Ptr == Arg) 1568c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman continue; // Handled above. 1569c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman PtrState &S = MI->second; 1570c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman Sequence Seq = S.GetSeq(); 1571c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1572c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Check for possible releases. 1573c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (CanAlterRefCount(Inst, Ptr, PA, Class)) { 157450ade659829269f0338cd1bfa0a574dcec62562eDan Gohman S.ClearRefCount(); 1575c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman switch (Seq) { 1576c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Use: 1577c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.SetSeq(S_CanRelease); 1578c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman continue; 1579c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_CanRelease: 1580c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Release: 1581c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_MovableRelease: 1582c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Stop: 1583c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_None: 1584c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1585c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Retain: 1586c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman llvm_unreachable("bottom-up pointer in retain state!"); 1587c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1588c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1589c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1590c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Check for possible direct uses. 1591c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman switch (Seq) { 1592c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Release: 1593c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_MovableRelease: 1594c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (CanUse(Inst, Ptr, PA, Class)) { 1595c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman assert(S.RRI.ReverseInsertPts.empty()); 1596fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman // If this is an invoke instruction, we're scanning it as part of 1597fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman // one of its successor blocks, since we can't insert code after it 1598fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman // in its own block, and we don't want to split critical edges. 1599fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman if (isa<InvokeInst>(Inst)) 1600fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman S.RRI.ReverseInsertPts.insert(BB->getFirstInsertionPt()); 1601fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman else 1602b54a5eda6d9a1f50c1861b53e19be84994e586efFrancois Pichet S.RRI.ReverseInsertPts.insert(llvm::next(BasicBlock::iterator(Inst))); 1603c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.SetSeq(S_Use); 1604c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } else if (Seq == S_Release && 1605c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman (Class == IC_User || Class == IC_CallOrUser)) { 1606c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Non-movable releases depend on any possible objc pointer use. 1607c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.SetSeq(S_Stop); 1608c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman assert(S.RRI.ReverseInsertPts.empty()); 1609fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman // As above; handle invoke specially. 1610fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman if (isa<InvokeInst>(Inst)) 1611fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman S.RRI.ReverseInsertPts.insert(BB->getFirstInsertionPt()); 1612fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman else 1613b54a5eda6d9a1f50c1861b53e19be84994e586efFrancois Pichet S.RRI.ReverseInsertPts.insert(llvm::next(BasicBlock::iterator(Inst))); 1614c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1615c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1616c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Stop: 1617c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (CanUse(Inst, Ptr, PA, Class)) 1618c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.SetSeq(S_Use); 1619c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1620c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_CanRelease: 1621c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Use: 1622c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_None: 1623c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1624c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Retain: 1625c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman llvm_unreachable("bottom-up pointer in retain state!"); 1626c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1627c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1628c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1629c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman return NestingDetected; 1630c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman} 1631c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1632c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohmanbool 16339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallObjCARCOpt::VisitBottomUp(BasicBlock *BB, 16349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<const BasicBlock *, BBState> &BBStates, 16359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapVector<Value *, RRInfo> &Retains) { 16369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool NestingDetected = false; 16379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BBState &MyStates = BBStates[BB]; 16389fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 16399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Merge the states from each successor to compute the initial state 16409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // for the current block. 164140e466091e76f4608ad09789546d3012c8c11c3eDan Gohman BBState::edge_iterator SI(MyStates.succ_begin()), 164240e466091e76f4608ad09789546d3012c8c11c3eDan Gohman SE(MyStates.succ_end()); 164340e466091e76f4608ad09789546d3012c8c11c3eDan Gohman if (SI != SE) { 1644eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman const BasicBlock *Succ = *SI; 1645eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman DenseMap<const BasicBlock *, BBState>::iterator I = BBStates.find(Succ); 1646eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman assert(I != BBStates.end()); 1647eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman MyStates.InitFromSucc(I->second); 1648eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman ++SI; 1649eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman for (; SI != SE; ++SI) { 1650eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman Succ = *SI; 1651eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman I = BBStates.find(Succ); 1652eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman assert(I != BBStates.end()); 1653eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman MyStates.MergeSucc(I->second); 1654eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman } 1655dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman } 16569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 16579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Visit all the instructions, bottom-up. 16589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; --I) { 16599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *Inst = llvm::prior(I); 1660fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman 1661fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman // Invoke instructions are visited as part of their successors (below). 1662fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman if (isa<InvokeInst>(Inst)) 1663fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman continue; 1664fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman 1665cf14005185778d823631a2367401e65b5e4802d8Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::VisitButtonUp: Visiting " << *Inst << "\n"); 1666cf14005185778d823631a2367401e65b5e4802d8Michael Gottesman 1667fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman NestingDetected |= VisitInstructionBottomUp(Inst, BB, Retains, MyStates); 1668fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman } 1669fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman 1670447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman // If there's a predecessor with an invoke, visit the invoke as if it were 1671447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman // part of this block, since we can't insert code after an invoke in its own 1672447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman // block, and we don't want to split critical edges. 1673eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman for (BBState::edge_iterator PI(MyStates.pred_begin()), 1674eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman PE(MyStates.pred_end()); PI != PE; ++PI) { 1675fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman BasicBlock *Pred = *PI; 1676447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman if (InvokeInst *II = dyn_cast<InvokeInst>(&Pred->back())) 1677447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman NestingDetected |= VisitInstructionBottomUp(II, BB, Retains, MyStates); 1678c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 16799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1680c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman return NestingDetected; 1681c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman} 16829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1683c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohmanbool 1684c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan GohmanObjCARCOpt::VisitInstructionTopDown(Instruction *Inst, 1685c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman DenseMap<Value *, RRInfo> &Releases, 1686c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman BBState &MyStates) { 1687c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman bool NestingDetected = false; 1688c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman InstructionClass Class = GetInstructionClass(Inst); 1689c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman const Value *Arg = 0; 16909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1691c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman switch (Class) { 1692c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_RetainBlock: 1693c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // An objc_retainBlock call with just a use may need to be kept, 1694c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // because it may be copying a block from the stack to the heap. 1695c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (!IsRetainBlockOptimizable(Inst)) 1696c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1697c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // FALLTHROUGH 1698c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_Retain: 1699c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_RetainRV: { 1700c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman Arg = GetObjCArg(Inst); 1701c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1702c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman PtrState &S = MyStates.getPtrTopDownState(Arg); 1703c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1704c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Don't do retain+release tracking for IC_RetainRV, because it's 1705c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // better to let it remain as the first instruction after a call. 1706c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (Class != IC_RetainRV) { 1707c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // If we see two retains in a row on the same pointer. If so, make 17089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // a note, and we'll cicle back to revisit it after we've 1709c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // hopefully eliminated the second retain, which may allow us to 1710c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // eliminate the first retain too. 17119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Theoretically we could implement removal of nested retain+release 17129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // pairs by making PtrState hold a stack of states, but this is 17139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // simple and avoids adding overhead for the non-nested case. 1714c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (S.GetSeq() == S_Retain) 17159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall NestingDetected = true; 17169fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 171750ade659829269f0338cd1bfa0a574dcec62562eDan Gohman S.ResetSequenceProgress(S_Retain); 1718c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.IsRetainBlock = Class == IC_RetainBlock; 1719230768bd1316a012e88ac62689589fe5e2f10456Dan Gohman S.RRI.KnownSafe = S.IsKnownIncremented(); 17209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall S.RRI.Calls.insert(Inst); 1721c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 17229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1723230768bd1316a012e88ac62689589fe5e2f10456Dan Gohman S.SetKnownPositiveRefCount(); 1724c72d3be38915728142d13f982eeef218e42f21aaDan Gohman 1725c72d3be38915728142d13f982eeef218e42f21aaDan Gohman // A retain can be a potential use; procede to the generic checking 1726c72d3be38915728142d13f982eeef218e42f21aaDan Gohman // code below. 1727c72d3be38915728142d13f982eeef218e42f21aaDan Gohman break; 1728c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1729c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_Release: { 1730c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman Arg = GetObjCArg(Inst); 1731c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1732c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman PtrState &S = MyStates.getPtrTopDownState(Arg); 1733230768bd1316a012e88ac62689589fe5e2f10456Dan Gohman S.ClearRefCount(); 1734c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1735c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman switch (S.GetSeq()) { 1736c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Retain: 1737c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_CanRelease: 1738c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.ReverseInsertPts.clear(); 1739c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // FALL THROUGH 1740c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Use: 1741c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.ReleaseMetadata = Inst->getMetadata(ImpreciseReleaseMDKind); 1742c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.IsTailCallRelease = cast<CallInst>(Inst)->isTailCall(); 1743c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman Releases[Inst] = S.RRI; 1744c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.ClearSequenceProgress(); 17459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 1746c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_None: 1747c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1748c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Stop: 1749c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Release: 1750c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_MovableRelease: 1751c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman llvm_unreachable("top-down pointer in release state!"); 17529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1753c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1754c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 1755c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_AutoreleasepoolPop: 1756c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Conservatively, clear MyStates for all known pointers. 1757c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman MyStates.clearTopDownPointers(); 1758c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman return NestingDetected; 1759c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_AutoreleasepoolPush: 1760c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case IC_None: 1761c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // These are irrelevant. 1762c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman return NestingDetected; 1763c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman default: 1764c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1765c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 17669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1767c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Consider any other possible effects of this instruction on each 1768c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // pointer being tracked. 1769c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman for (BBState::ptr_iterator MI = MyStates.top_down_ptr_begin(), 1770c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman ME = MyStates.top_down_ptr_end(); MI != ME; ++MI) { 1771c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman const Value *Ptr = MI->first; 1772c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (Ptr == Arg) 1773c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman continue; // Handled above. 1774c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman PtrState &S = MI->second; 1775c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman Sequence Seq = S.GetSeq(); 1776c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1777c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Check for possible releases. 1778c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (CanAlterRefCount(Inst, Ptr, PA, Class)) { 177950ade659829269f0338cd1bfa0a574dcec62562eDan Gohman S.ClearRefCount(); 1780c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman switch (Seq) { 1781c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Retain: 1782c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.SetSeq(S_CanRelease); 1783c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman assert(S.RRI.ReverseInsertPts.empty()); 1784c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.RRI.ReverseInsertPts.insert(Inst); 17859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 1786c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // One call can't cause a transition from S_Retain to S_CanRelease 1787c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // and S_CanRelease to S_Use. If we've made the first transition, 1788c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // we're done. 1789c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman continue; 17909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Use: 17919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_CanRelease: 17929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_None: 17939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 1794c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Stop: 17959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_Release: 17969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case S_MovableRelease: 1797c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman llvm_unreachable("top-down pointer in release state!"); 17989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 17999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 1800c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman 1801c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman // Check for possible direct uses. 1802c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman switch (Seq) { 1803c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_CanRelease: 1804c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman if (CanUse(Inst, Ptr, PA, Class)) 1805c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman S.SetSeq(S_Use); 1806c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1807c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Retain: 1808c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Use: 1809c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_None: 1810c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman break; 1811c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Stop: 1812c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_Release: 1813c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman case S_MovableRelease: 1814c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman llvm_unreachable("top-down pointer in release state!"); 1815c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman } 18169fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 18179fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 18189fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return NestingDetected; 18199fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 18209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 18219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallbool 18229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallObjCARCOpt::VisitTopDown(BasicBlock *BB, 18239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<const BasicBlock *, BBState> &BBStates, 18249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<Value *, RRInfo> &Releases) { 18259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool NestingDetected = false; 18269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BBState &MyStates = BBStates[BB]; 18279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 18289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Merge the states from each predecessor to compute the initial state 18299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // for the current block. 183040e466091e76f4608ad09789546d3012c8c11c3eDan Gohman BBState::edge_iterator PI(MyStates.pred_begin()), 183140e466091e76f4608ad09789546d3012c8c11c3eDan Gohman PE(MyStates.pred_end()); 183240e466091e76f4608ad09789546d3012c8c11c3eDan Gohman if (PI != PE) { 1833eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman const BasicBlock *Pred = *PI; 1834eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman DenseMap<const BasicBlock *, BBState>::iterator I = BBStates.find(Pred); 1835eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman assert(I != BBStates.end()); 1836eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman MyStates.InitFromPred(I->second); 1837eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman ++PI; 1838eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman for (; PI != PE; ++PI) { 1839eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman Pred = *PI; 1840eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman I = BBStates.find(Pred); 1841eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman assert(I != BBStates.end()); 1842eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman MyStates.MergePred(I->second); 1843eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman } 1844eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman } 18459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 18469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Visit all the instructions, top-down. 18479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { 18489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *Inst = I; 1849cf14005185778d823631a2367401e65b5e4802d8Michael Gottesman 1850cf14005185778d823631a2367401e65b5e4802d8Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::VisitTopDown: Visiting " << *Inst << "\n"); 1851cf14005185778d823631a2367401e65b5e4802d8Michael Gottesman 1852c7f5c6e0e3a25aa5f6320766dd1bb29371e6948dDan Gohman NestingDetected |= VisitInstructionTopDown(Inst, Releases, MyStates); 18539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 18549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 18559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CheckForCFGHazards(BB, BBStates, MyStates); 18569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return NestingDetected; 18579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 18589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 185959a1c93e955c366084742ceca65e7b1afd8772acDan Gohmanstatic void 186059a1c93e955c366084742ceca65e7b1afd8772acDan GohmanComputePostOrders(Function &F, 186159a1c93e955c366084742ceca65e7b1afd8772acDan Gohman SmallVectorImpl<BasicBlock *> &PostOrder, 1862eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman SmallVectorImpl<BasicBlock *> &ReverseCFGPostOrder, 1863eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman unsigned NoObjCARCExceptionsMDKind, 1864eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman DenseMap<const BasicBlock *, BBState> &BBStates) { 186581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// The visited set, for doing DFS walks. 1866d8e48c48215c8aaa87b19245efac8a490c693d17Dan Gohman SmallPtrSet<BasicBlock *, 16> Visited; 186759a1c93e955c366084742ceca65e7b1afd8772acDan Gohman 186859a1c93e955c366084742ceca65e7b1afd8772acDan Gohman // Do DFS, computing the PostOrder. 186959a1c93e955c366084742ceca65e7b1afd8772acDan Gohman SmallPtrSet<BasicBlock *, 16> OnStack; 187059a1c93e955c366084742ceca65e7b1afd8772acDan Gohman SmallVector<std::pair<BasicBlock *, succ_iterator>, 16> SuccStack; 1871eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman 1872eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman // Functions always have exactly one entry block, and we don't have 1873eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman // any other block that we treat like an entry block. 187459a1c93e955c366084742ceca65e7b1afd8772acDan Gohman BasicBlock *EntryBB = &F.getEntryBlock(); 18750daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman BBState &MyStates = BBStates[EntryBB]; 18760daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman MyStates.SetAsEntry(); 18770daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman TerminatorInst *EntryTI = cast<TerminatorInst>(&EntryBB->back()); 18780daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman SuccStack.push_back(std::make_pair(EntryBB, succ_iterator(EntryTI))); 187959a1c93e955c366084742ceca65e7b1afd8772acDan Gohman Visited.insert(EntryBB); 188059a1c93e955c366084742ceca65e7b1afd8772acDan Gohman OnStack.insert(EntryBB); 188159a1c93e955c366084742ceca65e7b1afd8772acDan Gohman do { 188259a1c93e955c366084742ceca65e7b1afd8772acDan Gohman dfs_next_succ: 1883eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman BasicBlock *CurrBB = SuccStack.back().first; 1884eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman TerminatorInst *TI = cast<TerminatorInst>(&CurrBB->back()); 1885eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman succ_iterator SE(TI, false); 18860daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman 1887eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman while (SuccStack.back().second != SE) { 1888eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman BasicBlock *SuccBB = *SuccStack.back().second++; 1889eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman if (Visited.insert(SuccBB)) { 18900daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman TerminatorInst *TI = cast<TerminatorInst>(&SuccBB->back()); 18910daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman SuccStack.push_back(std::make_pair(SuccBB, succ_iterator(TI))); 1892eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman BBStates[CurrBB].addSucc(SuccBB); 18930daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman BBState &SuccStates = BBStates[SuccBB]; 18940daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman SuccStates.addPred(CurrBB); 1895eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman OnStack.insert(SuccBB); 189659a1c93e955c366084742ceca65e7b1afd8772acDan Gohman goto dfs_next_succ; 189759a1c93e955c366084742ceca65e7b1afd8772acDan Gohman } 1898eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman 1899eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman if (!OnStack.count(SuccBB)) { 1900eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman BBStates[CurrBB].addSucc(SuccBB); 1901eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman BBStates[SuccBB].addPred(CurrBB); 1902eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman } 190359a1c93e955c366084742ceca65e7b1afd8772acDan Gohman } 1904eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman OnStack.erase(CurrBB); 1905eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman PostOrder.push_back(CurrBB); 1906eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman SuccStack.pop_back(); 190759a1c93e955c366084742ceca65e7b1afd8772acDan Gohman } while (!SuccStack.empty()); 190859a1c93e955c366084742ceca65e7b1afd8772acDan Gohman 190959a1c93e955c366084742ceca65e7b1afd8772acDan Gohman Visited.clear(); 191059a1c93e955c366084742ceca65e7b1afd8772acDan Gohman 1911eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman // Do reverse-CFG DFS, computing the reverse-CFG PostOrder. 1912eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman // Functions may have many exits, and there also blocks which we treat 1913eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman // as exits due to ignored edges. 1914eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman SmallVector<std::pair<BasicBlock *, BBState::edge_iterator>, 16> PredStack; 1915d8e48c48215c8aaa87b19245efac8a490c693d17Dan Gohman for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { 1916eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman BasicBlock *ExitBB = I; 1917eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman BBState &MyStates = BBStates[ExitBB]; 1918eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman if (!MyStates.isExit()) 1919eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman continue; 192059a1c93e955c366084742ceca65e7b1afd8772acDan Gohman 1921447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman MyStates.SetAsExit(); 1922eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman 1923eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman PredStack.push_back(std::make_pair(ExitBB, MyStates.pred_begin())); 192459a1c93e955c366084742ceca65e7b1afd8772acDan Gohman Visited.insert(ExitBB); 192559a1c93e955c366084742ceca65e7b1afd8772acDan Gohman while (!PredStack.empty()) { 192659a1c93e955c366084742ceca65e7b1afd8772acDan Gohman reverse_dfs_next_succ: 1927eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman BBState::edge_iterator PE = BBStates[PredStack.back().first].pred_end(); 1928eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman while (PredStack.back().second != PE) { 192959a1c93e955c366084742ceca65e7b1afd8772acDan Gohman BasicBlock *BB = *PredStack.back().second++; 193059a1c93e955c366084742ceca65e7b1afd8772acDan Gohman if (Visited.insert(BB)) { 1931eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman PredStack.push_back(std::make_pair(BB, BBStates[BB].pred_begin())); 193259a1c93e955c366084742ceca65e7b1afd8772acDan Gohman goto reverse_dfs_next_succ; 193359a1c93e955c366084742ceca65e7b1afd8772acDan Gohman } 193459a1c93e955c366084742ceca65e7b1afd8772acDan Gohman } 193559a1c93e955c366084742ceca65e7b1afd8772acDan Gohman ReverseCFGPostOrder.push_back(PredStack.pop_back_val().first); 193659a1c93e955c366084742ceca65e7b1afd8772acDan Gohman } 1937d8e48c48215c8aaa87b19245efac8a490c693d17Dan Gohman } 193859a1c93e955c366084742ceca65e7b1afd8772acDan Gohman} 193959a1c93e955c366084742ceca65e7b1afd8772acDan Gohman 194081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman// Visit the function both top-down and bottom-up. 194159a1c93e955c366084742ceca65e7b1afd8772acDan Gohmanbool 194259a1c93e955c366084742ceca65e7b1afd8772acDan GohmanObjCARCOpt::Visit(Function &F, 194359a1c93e955c366084742ceca65e7b1afd8772acDan Gohman DenseMap<const BasicBlock *, BBState> &BBStates, 194459a1c93e955c366084742ceca65e7b1afd8772acDan Gohman MapVector<Value *, RRInfo> &Retains, 194559a1c93e955c366084742ceca65e7b1afd8772acDan Gohman DenseMap<Value *, RRInfo> &Releases) { 194659a1c93e955c366084742ceca65e7b1afd8772acDan Gohman 194759a1c93e955c366084742ceca65e7b1afd8772acDan Gohman // Use reverse-postorder traversals, because we magically know that loops 194859a1c93e955c366084742ceca65e7b1afd8772acDan Gohman // will be well behaved, i.e. they won't repeatedly call retain on a single 194959a1c93e955c366084742ceca65e7b1afd8772acDan Gohman // pointer without doing a release. We can't use the ReversePostOrderTraversal 195059a1c93e955c366084742ceca65e7b1afd8772acDan Gohman // class here because we want the reverse-CFG postorder to consider each 195159a1c93e955c366084742ceca65e7b1afd8772acDan Gohman // function exit point, and we want to ignore selected cycle edges. 195259a1c93e955c366084742ceca65e7b1afd8772acDan Gohman SmallVector<BasicBlock *, 16> PostOrder; 195359a1c93e955c366084742ceca65e7b1afd8772acDan Gohman SmallVector<BasicBlock *, 16> ReverseCFGPostOrder; 1954eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman ComputePostOrders(F, PostOrder, ReverseCFGPostOrder, 1955eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman NoObjCARCExceptionsMDKind, 1956eeeb7752a8eb13f799d33046246b6826990119f1Dan Gohman BBStates); 195759a1c93e955c366084742ceca65e7b1afd8772acDan Gohman 195859a1c93e955c366084742ceca65e7b1afd8772acDan Gohman // Use reverse-postorder on the reverse CFG for bottom-up. 19599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool BottomUpNestingDetected = false; 1960b48ef3a3ec7f527b0c76e7fbb37bbaac63b7c6aaDan Gohman for (SmallVectorImpl<BasicBlock *>::const_reverse_iterator I = 196159a1c93e955c366084742ceca65e7b1afd8772acDan Gohman ReverseCFGPostOrder.rbegin(), E = ReverseCFGPostOrder.rend(); 196259a1c93e955c366084742ceca65e7b1afd8772acDan Gohman I != E; ++I) 196359a1c93e955c366084742ceca65e7b1afd8772acDan Gohman BottomUpNestingDetected |= VisitBottomUp(*I, BBStates, Retains); 19649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 196559a1c93e955c366084742ceca65e7b1afd8772acDan Gohman // Use reverse-postorder for top-down. 19669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool TopDownNestingDetected = false; 196759a1c93e955c366084742ceca65e7b1afd8772acDan Gohman for (SmallVectorImpl<BasicBlock *>::const_reverse_iterator I = 196859a1c93e955c366084742ceca65e7b1afd8772acDan Gohman PostOrder.rbegin(), E = PostOrder.rend(); 196959a1c93e955c366084742ceca65e7b1afd8772acDan Gohman I != E; ++I) 197059a1c93e955c366084742ceca65e7b1afd8772acDan Gohman TopDownNestingDetected |= VisitTopDown(*I, BBStates, Releases); 19719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 19729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return TopDownNestingDetected && BottomUpNestingDetected; 19739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 19749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 197581c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Move the calls in RetainsToMove and ReleasesToMove. 19769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid ObjCARCOpt::MoveCalls(Value *Arg, 19779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRInfo &RetainsToMove, 19789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRInfo &ReleasesToMove, 19799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapVector<Value *, RRInfo> &Retains, 19809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<Value *, RRInfo> &Releases, 19814428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman SmallVectorImpl<Instruction *> &DeadInsts, 19824428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman Module *M) { 1983db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *ArgTy = Arg->getType(); 19844428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman Type *ParamTy = PointerType::getUnqual(Type::getInt8Ty(ArgTy->getContext())); 19859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 19869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Insert the new retain and release calls. 19879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (SmallPtrSet<Instruction *, 2>::const_iterator 19889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PI = ReleasesToMove.ReverseInsertPts.begin(), 19899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PE = ReleasesToMove.ReverseInsertPts.end(); PI != PE; ++PI) { 19909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *InsertPt = *PI; 19919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *MyArg = ArgTy == ParamTy ? Arg : 19929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall new BitCastInst(Arg, ParamTy, "", InsertPt); 19939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *Call = 19949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst::Create(RetainsToMove.IsRetainBlock ? 19954428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman getRetainBlockCallee(M) : getRetainCallee(M), 19969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MyArg, "", InsertPt); 19979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Call->setDoesNotThrow(); 199879522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman if (RetainsToMove.IsRetainBlock) 1999a974beaa1f63394a67c38c66ff0f39a759c7998fDan Gohman Call->setMetadata(CopyOnEscapeMDKind, 2000a974beaa1f63394a67c38c66ff0f39a759c7998fDan Gohman MDNode::get(M->getContext(), ArrayRef<Value *>())); 200179522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman else 20029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Call->setTailCall(); 20035581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman 20045581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::MoveCalls: Inserting new Release: " << *Call 20055581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman << "\n" 20065581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman " At insertion point: " << *InsertPt 20075581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman << "\n"); 20089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 20099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (SmallPtrSet<Instruction *, 2>::const_iterator 20109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PI = RetainsToMove.ReverseInsertPts.begin(), 20119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PE = RetainsToMove.ReverseInsertPts.end(); PI != PE; ++PI) { 2012fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman Instruction *InsertPt = *PI; 2013fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman Value *MyArg = ArgTy == ParamTy ? Arg : 2014fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman new BitCastInst(Arg, ParamTy, "", InsertPt); 2015fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman CallInst *Call = CallInst::Create(getReleaseCallee(M), MyArg, 2016fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman "", InsertPt); 2017fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman // Attach a clang.imprecise_release metadata tag, if appropriate. 2018fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman if (MDNode *M = ReleasesToMove.ReleaseMetadata) 2019fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman Call->setMetadata(ImpreciseReleaseMDKind, M); 2020fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman Call->setDoesNotThrow(); 2021fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman if (ReleasesToMove.IsTailCallRelease) 2022fbab4a8c8a142502b7cdeb7112366f8560a94cecDan Gohman Call->setTailCall(); 20235581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman 20245581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::MoveCalls: Inserting new Retain: " << *Call 20255581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman << "\n" 20265581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman " At insertion point: " << *InsertPt 20275581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman << "\n"); 20289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 20299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 20309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Delete the original retain and release calls. 20319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (SmallPtrSet<Instruction *, 2>::const_iterator 20329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AI = RetainsToMove.Calls.begin(), 20339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AE = RetainsToMove.Calls.end(); AI != AE; ++AI) { 20349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *OrigRetain = *AI; 20359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Retains.blot(OrigRetain); 20369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DeadInsts.push_back(OrigRetain); 20375581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::MoveCalls: Deleting retain: " << *OrigRetain << 20385581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman "\n"); 20399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 20409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (SmallPtrSet<Instruction *, 2>::const_iterator 20419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AI = ReleasesToMove.Calls.begin(), 20429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AE = ReleasesToMove.Calls.end(); AI != AE; ++AI) { 20439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *OrigRelease = *AI; 20449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Releases.erase(OrigRelease); 20459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DeadInsts.push_back(OrigRelease); 20465581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::MoveCalls: Deleting release: " << *OrigRelease 20475581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman << "\n"); 20489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 20499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 20509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2051862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesmanbool 2052862d51fc671af273e52593246e7607fe9a6ba80cMichael GottesmanObjCARCOpt::ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState> 2053862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman &BBStates, 2054862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman MapVector<Value *, RRInfo> &Retains, 2055862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman DenseMap<Value *, RRInfo> &Releases, 2056862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Module *M, 2057862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman SmallVector<Instruction *, 4> &NewRetains, 2058862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman SmallVector<Instruction *, 4> &NewReleases, 2059862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman SmallVector<Instruction *, 8> &DeadInsts, 2060862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RRInfo &RetainsToMove, 2061862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RRInfo &ReleasesToMove, 2062862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Value *Arg, 2063862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman bool KnownSafe, 2064862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman bool &AnyPairsCompletelyEliminated) { 2065862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // If a pair happens in a region where it is known that the reference count 2066862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // is already incremented, we can similarly ignore possible decrements. 2067862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman bool KnownSafeTD = true, KnownSafeBU = true; 2068862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2069862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Connect the dots between the top-down-collected RetainsToMove and 2070862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // bottom-up-collected ReleasesToMove to form sets of related calls. 2071862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // This is an iterative process so that we connect multiple releases 2072862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // to multiple retains if needed. 2073862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman unsigned OldDelta = 0; 2074862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman unsigned NewDelta = 0; 2075862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman unsigned OldCount = 0; 2076862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman unsigned NewCount = 0; 2077862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman bool FirstRelease = true; 2078862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman bool FirstRetain = true; 2079862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman for (;;) { 2080862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman for (SmallVectorImpl<Instruction *>::const_iterator 2081862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NI = NewRetains.begin(), NE = NewRetains.end(); NI != NE; ++NI) { 2082862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Instruction *NewRetain = *NI; 2083862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman MapVector<Value *, RRInfo>::const_iterator It = Retains.find(NewRetain); 2084862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman assert(It != Retains.end()); 2085862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman const RRInfo &NewRetainRRI = It->second; 2086862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman KnownSafeTD &= NewRetainRRI.KnownSafe; 2087862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman for (SmallPtrSet<Instruction *, 2>::const_iterator 2088862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman LI = NewRetainRRI.Calls.begin(), 2089862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman LE = NewRetainRRI.Calls.end(); LI != LE; ++LI) { 2090862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Instruction *NewRetainRelease = *LI; 2091862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman DenseMap<Value *, RRInfo>::const_iterator Jt = 2092862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Releases.find(NewRetainRelease); 2093862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (Jt == Releases.end()) 2094862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman return false; 2095862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman const RRInfo &NewRetainReleaseRRI = Jt->second; 2096862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman assert(NewRetainReleaseRRI.Calls.count(NewRetain)); 2097862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (ReleasesToMove.Calls.insert(NewRetainRelease)) { 2098862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman OldDelta -= 2099862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman BBStates[NewRetainRelease->getParent()].GetAllPathCount(); 2100862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2101862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Merge the ReleaseMetadata and IsTailCallRelease values. 2102862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (FirstRelease) { 2103862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman ReleasesToMove.ReleaseMetadata = 2104862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewRetainReleaseRRI.ReleaseMetadata; 2105862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman ReleasesToMove.IsTailCallRelease = 2106862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewRetainReleaseRRI.IsTailCallRelease; 2107862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman FirstRelease = false; 2108862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } else { 2109862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (ReleasesToMove.ReleaseMetadata != 2110862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewRetainReleaseRRI.ReleaseMetadata) 2111862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman ReleasesToMove.ReleaseMetadata = 0; 2112862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (ReleasesToMove.IsTailCallRelease != 2113862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewRetainReleaseRRI.IsTailCallRelease) 2114862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman ReleasesToMove.IsTailCallRelease = false; 2115862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2116862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2117862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Collect the optimal insertion points. 2118862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (!KnownSafe) 2119862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman for (SmallPtrSet<Instruction *, 2>::const_iterator 2120862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RI = NewRetainReleaseRRI.ReverseInsertPts.begin(), 2121862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RE = NewRetainReleaseRRI.ReverseInsertPts.end(); 2122862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RI != RE; ++RI) { 2123862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Instruction *RIP = *RI; 2124862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (ReleasesToMove.ReverseInsertPts.insert(RIP)) 2125862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewDelta -= BBStates[RIP->getParent()].GetAllPathCount(); 2126862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2127862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewReleases.push_back(NewRetainRelease); 2128862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2129862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2130862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2131862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewRetains.clear(); 2132862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (NewReleases.empty()) break; 2133862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2134862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Back the other way. 2135862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman for (SmallVectorImpl<Instruction *>::const_iterator 2136862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NI = NewReleases.begin(), NE = NewReleases.end(); NI != NE; ++NI) { 2137862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Instruction *NewRelease = *NI; 2138862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman DenseMap<Value *, RRInfo>::const_iterator It = 2139862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Releases.find(NewRelease); 2140862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman assert(It != Releases.end()); 2141862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman const RRInfo &NewReleaseRRI = It->second; 2142862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman KnownSafeBU &= NewReleaseRRI.KnownSafe; 2143862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman for (SmallPtrSet<Instruction *, 2>::const_iterator 2144862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman LI = NewReleaseRRI.Calls.begin(), 2145862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman LE = NewReleaseRRI.Calls.end(); LI != LE; ++LI) { 2146862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Instruction *NewReleaseRetain = *LI; 2147862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman MapVector<Value *, RRInfo>::const_iterator Jt = 2148862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Retains.find(NewReleaseRetain); 2149862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (Jt == Retains.end()) 2150862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman return false; 2151862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman const RRInfo &NewReleaseRetainRRI = Jt->second; 2152862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman assert(NewReleaseRetainRRI.Calls.count(NewRelease)); 2153862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (RetainsToMove.Calls.insert(NewReleaseRetain)) { 2154862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman unsigned PathCount = 2155862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman BBStates[NewReleaseRetain->getParent()].GetAllPathCount(); 2156862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman OldDelta += PathCount; 2157862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman OldCount += PathCount; 2158862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2159862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Merge the IsRetainBlock values. 2160862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (FirstRetain) { 2161862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RetainsToMove.IsRetainBlock = NewReleaseRetainRRI.IsRetainBlock; 2162862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman FirstRetain = false; 2163862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } else if (ReleasesToMove.IsRetainBlock != 2164862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewReleaseRetainRRI.IsRetainBlock) 2165862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // It's not possible to merge the sequences if one uses 2166862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // objc_retain and the other uses objc_retainBlock. 2167862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman return false; 2168862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2169862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Collect the optimal insertion points. 2170862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (!KnownSafe) 2171862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman for (SmallPtrSet<Instruction *, 2>::const_iterator 2172862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RI = NewReleaseRetainRRI.ReverseInsertPts.begin(), 2173862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RE = NewReleaseRetainRRI.ReverseInsertPts.end(); 2174862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RI != RE; ++RI) { 2175862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Instruction *RIP = *RI; 2176862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (RetainsToMove.ReverseInsertPts.insert(RIP)) { 2177862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman PathCount = BBStates[RIP->getParent()].GetAllPathCount(); 2178862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewDelta += PathCount; 2179862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewCount += PathCount; 2180862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2181862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2182862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewRetains.push_back(NewReleaseRetain); 2183862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2184862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2185862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2186862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewReleases.clear(); 2187862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (NewRetains.empty()) break; 2188862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2189862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2190862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // If the pointer is known incremented or nested, we can safely delete the 2191862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // pair regardless of what's between them. 2192862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (KnownSafeTD || KnownSafeBU) { 2193862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman RetainsToMove.ReverseInsertPts.clear(); 2194862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman ReleasesToMove.ReverseInsertPts.clear(); 2195862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewCount = 0; 2196862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } else { 2197862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Determine whether the new insertion points we computed preserve the 2198862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // balance of retain and release calls through the program. 2199862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // TODO: If the fully aggressive solution isn't valid, try to find a 2200862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // less aggressive solution which is. 2201862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (NewDelta != 0) 2202862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman return false; 2203862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 2204862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2205862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Determine whether the original call points are balanced in the retain and 2206862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // release calls through the program. If not, conservatively don't touch 2207862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // them. 2208862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // TODO: It's theoretically possible to do code motion in this case, as 2209862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // long as the existing imbalances are maintained. 2210862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (OldDelta != 0) 2211862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman return false; 2212862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2213862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Changed = true; 2214862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman assert(OldCount != 0 && "Unreachable code?"); 2215862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NumRRs += OldCount - NewCount; 2216862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Set to true if we completely removed any RR pairs. 2217e65d46246c3e8fc279a9b6b7aaf985060ba88ab0Michael Gottesman AnyPairsCompletelyEliminated = NewCount == 0; 2218862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 2219862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // We can move calls! 2220862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman return true; 2221862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman} 2222862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman 222381c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Identify pairings between the retains and releases, and delete and/or move 222481c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// them. 22259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallbool 22269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState> 22279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall &BBStates, 22289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapVector<Value *, RRInfo> &Retains, 22294428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman DenseMap<Value *, RRInfo> &Releases, 22304428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman Module *M) { 22319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool AnyPairsCompletelyEliminated = false; 22329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRInfo RetainsToMove; 22339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RRInfo ReleasesToMove; 22349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallVector<Instruction *, 4> NewRetains; 22359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallVector<Instruction *, 4> NewReleases; 22369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallVector<Instruction *, 8> DeadInsts; 22379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2238d6bf201fa20a5cd3aa9f61767081d1d03d8aee3cDan Gohman // Visit each retain. 22399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (MapVector<Value *, RRInfo>::const_iterator I = Retains.begin(), 2240597fece886fb4551d1f26ec7749d86e89970d8c2Dan Gohman E = Retains.end(); I != E; ++I) { 2241597fece886fb4551d1f26ec7749d86e89970d8c2Dan Gohman Value *V = I->first; 22429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!V) continue; // blotted 22439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 22449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *Retain = cast<Instruction>(V); 22455581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman 22465581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::PerformCodePlacement: Visiting: " << *Retain 22475581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman << "\n"); 22485581115075e688bdf44920f6b93dd42e94c3ccf6Michael Gottesman 22499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *Arg = GetObjCArg(Retain); 22509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 225179522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman // If the object being released is in static or stack storage, we know it's 22529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // not being managed by ObjC reference counting, so we can delete pairs 22539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // regardless of what possible decrements or uses lie between them. 225479522dc569d3fb51b4a12cdacf24b82e5d5992d2Dan Gohman bool KnownSafe = isa<Constant>(Arg) || isa<AllocaInst>(Arg); 22550daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman 22561b31ea8f935d4b643abf100c4943180c9ed8ba1aDan Gohman // A constant pointer can't be pointing to an object on the heap. It may 22571b31ea8f935d4b643abf100c4943180c9ed8ba1aDan Gohman // be reference-counted, but it won't be deleted. 22581b31ea8f935d4b643abf100c4943180c9ed8ba1aDan Gohman if (const LoadInst *LI = dyn_cast<LoadInst>(Arg)) 22591b31ea8f935d4b643abf100c4943180c9ed8ba1aDan Gohman if (const GlobalVariable *GV = 22601b31ea8f935d4b643abf100c4943180c9ed8ba1aDan Gohman dyn_cast<GlobalVariable>( 22611b31ea8f935d4b643abf100c4943180c9ed8ba1aDan Gohman StripPointerCastsAndObjCCalls(LI->getPointerOperand()))) 22621b31ea8f935d4b643abf100c4943180c9ed8ba1aDan Gohman if (GV->isConstant()) 22631b31ea8f935d4b643abf100c4943180c9ed8ba1aDan Gohman KnownSafe = true; 22641b31ea8f935d4b643abf100c4943180c9ed8ba1aDan Gohman 22659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Connect the dots between the top-down-collected RetainsToMove and 22669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // bottom-up-collected ReleasesToMove to form sets of related calls. 22679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall NewRetains.push_back(Retain); 2268862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman bool PerformMoveCalls = 2269862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman ConnectTDBUTraversals(BBStates, Retains, Releases, M, NewRetains, 2270862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman NewReleases, DeadInsts, RetainsToMove, 2271862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman ReleasesToMove, Arg, KnownSafe, 2272862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman AnyPairsCompletelyEliminated); 22739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2274862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman if (PerformMoveCalls) { 2275862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Ok, everything checks out and we're all set. Let's move/delete some 2276862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // code! 2277862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman MoveCalls(Arg, RetainsToMove, ReleasesToMove, 2278862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman Retains, Releases, DeadInsts, M); 2279862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman } 22809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2281862d51fc671af273e52593246e7607fe9a6ba80cMichael Gottesman // Clean up state for next retain. 22829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall NewReleases.clear(); 22839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall NewRetains.clear(); 22849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RetainsToMove.clear(); 22859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ReleasesToMove.clear(); 22869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 22879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 22889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Now that we're done moving everything, we can delete the newly dead 22899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // instructions, as we no longer need them as insert points. 22909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall while (!DeadInsts.empty()) 22919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall EraseInstruction(DeadInsts.pop_back_val()); 22929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 22939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return AnyPairsCompletelyEliminated; 22949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 22959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 229681c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Weak pointer optimizations. 22979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid ObjCARCOpt::OptimizeWeakCalls(Function &F) { 22989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // First, do memdep-style RLE and S2L optimizations. We can't use memdep 22999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // itself because it uses AliasAnalysis and we need to do provenance 23009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // queries instead. 23019fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) { 23029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *Inst = &*I++; 23038f22c8b5e1f32bf253f968a81542a76dbfc3efc7Michael Gottesman 23045c0ae4727fe49a8173ee9084af4f5fb7d6d33f2cMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeWeakCalls: Visiting: " << *Inst << 23058f22c8b5e1f32bf253f968a81542a76dbfc3efc7Michael Gottesman "\n"); 23068f22c8b5e1f32bf253f968a81542a76dbfc3efc7Michael Gottesman 23079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall InstructionClass Class = GetBasicInstructionClass(Inst); 23089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Class != IC_LoadWeak && Class != IC_LoadWeakRetained) 23099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 23109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 23119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Delete objc_loadWeak calls with no users. 23129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Class == IC_LoadWeak && Inst->use_empty()) { 23139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Inst->eraseFromParent(); 23149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 23159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 23169fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 23179fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // TODO: For now, just look for an earlier available version of this value 23189fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // within the same block. Theoretically, we could do memdep-style non-local 23199fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // analysis too, but that would want caching. A better approach would be to 23209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // use the technique that EarlyCSE uses. 23219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall inst_iterator Current = llvm::prior(I); 23229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BasicBlock *CurrentBB = Current.getBasicBlockIterator(); 23239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (BasicBlock::iterator B = CurrentBB->begin(), 23249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall J = Current.getInstructionIterator(); 23259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall J != B; --J) { 23269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *EarlierInst = &*llvm::prior(J); 23279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall InstructionClass EarlierClass = GetInstructionClass(EarlierInst); 23289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall switch (EarlierClass) { 23299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_LoadWeak: 23309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_LoadWeakRetained: { 23319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If this is loading from the same pointer, replace this load's value 23329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // with that one. 23339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *Call = cast<CallInst>(Inst); 23349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *EarlierCall = cast<CallInst>(EarlierInst); 23359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *Arg = Call->getArgOperand(0); 23369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *EarlierArg = EarlierCall->getArgOperand(0); 23379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall switch (PA.getAA()->alias(Arg, EarlierArg)) { 23389fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case AliasAnalysis::MustAlias: 23399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 23409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If the load has a builtin retain, insert a plain retain for it. 23419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Class == IC_LoadWeakRetained) { 23429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *CI = 23439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst::Create(getRetainCallee(F.getParent()), EarlierCall, 23449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall "", Call); 23459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CI->setTailCall(); 23469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 23479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Zap the fully redundant load. 23489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Call->replaceAllUsesWith(EarlierCall); 23499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Call->eraseFromParent(); 23509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto clobbered; 23519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case AliasAnalysis::MayAlias: 23529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case AliasAnalysis::PartialAlias: 23539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto clobbered; 23549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case AliasAnalysis::NoAlias: 23559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 23569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 23579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 23589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 23599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_StoreWeak: 23609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_InitWeak: { 23619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If this is storing to the same pointer and has the same size etc. 23629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // replace this load's value with the stored value. 23639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *Call = cast<CallInst>(Inst); 23649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *EarlierCall = cast<CallInst>(EarlierInst); 23659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *Arg = Call->getArgOperand(0); 23669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *EarlierArg = EarlierCall->getArgOperand(0); 23679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall switch (PA.getAA()->alias(Arg, EarlierArg)) { 23689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case AliasAnalysis::MustAlias: 23699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 23709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If the load has a builtin retain, insert a plain retain for it. 23719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Class == IC_LoadWeakRetained) { 23729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *CI = 23739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst::Create(getRetainCallee(F.getParent()), EarlierCall, 23749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall "", Call); 23759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CI->setTailCall(); 23769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 23779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Zap the fully redundant load. 23789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Call->replaceAllUsesWith(EarlierCall->getArgOperand(1)); 23799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Call->eraseFromParent(); 23809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto clobbered; 23819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case AliasAnalysis::MayAlias: 23829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case AliasAnalysis::PartialAlias: 23839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto clobbered; 23849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case AliasAnalysis::NoAlias: 23859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 23869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 23879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 23889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 23899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_MoveWeak: 23909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_CopyWeak: 23919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // TOOD: Grab the copied value. 23929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto clobbered; 23939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_AutoreleasepoolPush: 23949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_None: 23959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_User: 23969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Weak pointers are only modified through the weak entry points 23979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // (and arbitrary calls, which could call the weak entry points). 23989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall break; 23999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall default: 24009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Anything else could modify the weak pointer. 24019fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto clobbered; 24029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 24039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 24049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall clobbered:; 24059fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 24069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 24079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Then, for each destroyWeak with an alloca operand, check to see if 24089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // the alloca and all its users can be zapped. 24099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) { 24109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Instruction *Inst = &*I++; 24119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall InstructionClass Class = GetBasicInstructionClass(Inst); 24129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Class != IC_DestroyWeak) 24139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 24149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 24159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *Call = cast<CallInst>(Inst); 24169fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Value *Arg = Call->getArgOperand(0); 24179fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (AllocaInst *Alloca = dyn_cast<AllocaInst>(Arg)) { 24189fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (Value::use_iterator UI = Alloca->use_begin(), 24199fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall UE = Alloca->use_end(); UI != UE; ++UI) { 2420447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman const Instruction *UserInst = cast<Instruction>(*UI); 24219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall switch (GetBasicInstructionClass(UserInst)) { 24229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_InitWeak: 24239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_StoreWeak: 24249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall case IC_DestroyWeak: 24259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall continue; 24269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall default: 24279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto done; 24289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 24299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 24309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 24319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (Value::use_iterator UI = Alloca->use_begin(), 24329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall UE = Alloca->use_end(); UI != UE; ) { 24339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *UserInst = cast<CallInst>(*UI++); 2434ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman switch (GetBasicInstructionClass(UserInst)) { 2435ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman case IC_InitWeak: 2436ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman case IC_StoreWeak: 2437ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman // These functions return their second argument. 2438ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman UserInst->replaceAllUsesWith(UserInst->getArgOperand(1)); 2439ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman break; 2440ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman case IC_DestroyWeak: 2441ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman // No return value. 2442ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman break; 2443ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman default: 24444c8f909cdf221195f1d306033a4f843c5a7ee81aDan Gohman llvm_unreachable("alloca really is used!"); 2445ce5d8b0d03b9c37727d08de4fa1bcc7be7ea8bb1Dan Gohman } 24469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall UserInst->eraseFromParent(); 24479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 24489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Alloca->eraseFromParent(); 24499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall done:; 24509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 24519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 24522f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 24535c0ae4727fe49a8173ee9084af4f5fb7d6d33f2cMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeWeakCalls: Finished List.\n\n"); 24542f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 24559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 24569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 245781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Identify program paths which execute sequences of retains and releases which 245881c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// can be eliminated. 24599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallbool ObjCARCOpt::OptimizeSequences(Function &F) { 24609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /// Releases, Retains - These are used to store the results of the main flow 24619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /// analysis. These use Value* as the key instead of Instruction* so that the 24629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /// map stays valid when we get around to rewriting code and calls get 24639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /// replaced by arguments. 24649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<Value *, RRInfo> Releases; 24659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall MapVector<Value *, RRInfo> Retains; 24669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 246781c6121699a66b3e84f7b794b375095a39584701Michael Gottesman /// This is used during the traversal of the function to track the 24689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall /// states for each identified object at each block. 24699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DenseMap<const BasicBlock *, BBState> BBStates; 24709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 24719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Analyze the CFG of the function, and all instructions. 24729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall bool NestingDetected = Visit(F, BBStates, Retains, Releases); 24739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 24749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Transform. 24754428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman return PerformCodePlacement(BBStates, Retains, Releases, F.getParent()) && 24764428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman NestingDetected; 24779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 24789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 247981c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// Look for this pattern: 2480c5252da873d547a19069eaf9030fec203f128f66Dmitri Gribenko/// \code 24819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// %call = call i8* @something(...) 24829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// %2 = call i8* @objc_retain(i8* %call) 24839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// %3 = call i8* @objc_autorelease(i8* %2) 24849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// ret i8* %3 2485c5252da873d547a19069eaf9030fec203f128f66Dmitri Gribenko/// \endcode 24869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// And delete the retain and autorelease. 24879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// 24889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// Otherwise if it's just this: 2489c5252da873d547a19069eaf9030fec203f128f66Dmitri Gribenko/// \code 24909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// %3 = call i8* @objc_autorelease(i8* %2) 24919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// ret i8* %3 2492c5252da873d547a19069eaf9030fec203f128f66Dmitri Gribenko/// \endcode 24939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall/// convert the autorelease to autoreleaseRV. 24949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid ObjCARCOpt::OptimizeReturns(Function &F) { 24959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!F.getReturnType()->isPointerTy()) 24969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return; 24979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 24989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallPtrSet<Instruction *, 4> DependingInstructions; 24999fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall SmallPtrSet<const BasicBlock *, 4> Visited; 25009fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) { 25019fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BasicBlock *BB = FI; 25029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ReturnInst *Ret = dyn_cast<ReturnInst>(&BB->back()); 25038f22c8b5e1f32bf253f968a81542a76dbfc3efc7Michael Gottesman 25045c0ae4727fe49a8173ee9084af4f5fb7d6d33f2cMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeReturns: Visiting: " << *Ret << "\n"); 25058f22c8b5e1f32bf253f968a81542a76dbfc3efc7Michael Gottesman 25069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!Ret) continue; 25079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25089fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall const Value *Arg = StripPointerCastsAndObjCCalls(Ret->getOperand(0)); 25099fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall FindDependencies(NeedsPositiveRetainCount, Arg, 25109fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BB, Ret, DependingInstructions, Visited, PA); 25119fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (DependingInstructions.size() != 1) 25129fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto next_block; 25139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall { 25159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *Autorelease = 25169fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall dyn_cast_or_null<CallInst>(*DependingInstructions.begin()); 25179fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!Autorelease) 25189fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto next_block; 25190daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman InstructionClass AutoreleaseClass = GetBasicInstructionClass(Autorelease); 25209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!IsAutorelease(AutoreleaseClass)) 25219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto next_block; 25229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (GetObjCArg(Autorelease) != Arg) 25239fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto next_block; 25249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DependingInstructions.clear(); 25269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Visited.clear(); 25279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Check that there is nothing that can affect the reference 25299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // count between the autorelease and the retain. 25309fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall FindDependencies(CanChangeRetainCount, Arg, 25319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall BB, Autorelease, DependingInstructions, Visited, PA); 25329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (DependingInstructions.size() != 1) 25339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto next_block; 25349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall { 25369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *Retain = 25379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall dyn_cast_or_null<CallInst>(*DependingInstructions.begin()); 25389fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Check that we found a retain with the same argument. 25409fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!Retain || 25419fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall !IsRetain(GetBasicInstructionClass(Retain)) || 25429fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall GetObjCArg(Retain) != Arg) 25439fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto next_block; 25449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DependingInstructions.clear(); 25469fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Visited.clear(); 25479fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Convert the autorelease to an autoreleaseRV, since it's 25499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // returning the value. 25509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (AutoreleaseClass == IC_Autorelease) { 25515dc300107b0f31ef876f2bf93e9893f6aa8204a2Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeReturns: Converting autorelease " 25525dc300107b0f31ef876f2bf93e9893f6aa8204a2Michael Gottesman "=> autoreleaseRV since it's returning a value.\n" 25535dc300107b0f31ef876f2bf93e9893f6aa8204a2Michael Gottesman " In: " << *Autorelease 25545dc300107b0f31ef876f2bf93e9893f6aa8204a2Michael Gottesman << "\n"); 25559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Autorelease->setCalledFunction(getAutoreleaseRVCallee(F.getParent())); 25565dc300107b0f31ef876f2bf93e9893f6aa8204a2Michael Gottesman DEBUG(dbgs() << " Out: " << *Autorelease 25575dc300107b0f31ef876f2bf93e9893f6aa8204a2Michael Gottesman << "\n"); 2558e8c161a92451ad38919525ea73ae3c6936c24bdfMichael Gottesman Autorelease->setTailCall(); // Always tail call autoreleaseRV. 25599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AutoreleaseClass = IC_AutoreleaseRV; 25609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 25619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Check that there is nothing that can affect the reference 25639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // count between the retain and the call. 256427e0666725c6558574cb7a55f8c91e7532e09548Dan Gohman // Note that Retain need not be in BB. 256527e0666725c6558574cb7a55f8c91e7532e09548Dan Gohman FindDependencies(CanChangeRetainCount, Arg, Retain->getParent(), Retain, 25669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DependingInstructions, Visited, PA); 25679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (DependingInstructions.size() != 1) 25689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto next_block; 25699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall { 25719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall CallInst *Call = 25729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall dyn_cast_or_null<CallInst>(*DependingInstructions.begin()); 25739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Check that the pointer is the return value of the call. 25759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!Call || Arg != Call) 25769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto next_block; 25779fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25789fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Check that the call is a regular call. 25799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall InstructionClass Class = GetBasicInstructionClass(Call); 25809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (Class != IC_CallOrUser && Class != IC_Call) 25819fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall goto next_block; 25829fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // If so, we can zap the retain and autorelease. 25849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = true; 25859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ++NumRets; 2586f93109a9b6843fcbe759e69f360b6e079d46c55eMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeReturns: Erasing: " << *Retain 2587f93109a9b6843fcbe759e69f360b6e079d46c55eMichael Gottesman << "\n Erasing: " 2588f93109a9b6843fcbe759e69f360b6e079d46c55eMichael Gottesman << *Autorelease << "\n"); 25899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall EraseInstruction(Retain); 25909fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall EraseInstruction(Autorelease); 25919fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 25929fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 25939fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 25949fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 25959fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall next_block: 25969fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall DependingInstructions.clear(); 25979fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Visited.clear(); 25989fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall } 25992f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 26005c0ae4727fe49a8173ee9084af4f5fb7d6d33f2cMichael Gottesman DEBUG(dbgs() << "ObjCARCOpt::OptimizeReturns: Finished List.\n\n"); 26012f1bfc4c7937fdf59e2d88e0e23d0657daba79b2Michael Gottesman 26029fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 26039fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26049fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallbool ObjCARCOpt::doInitialization(Module &M) { 26059fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!EnableARCOpts) 26069fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return false; 26079fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2608d6bf201fa20a5cd3aa9f61767081d1d03d8aee3cDan Gohman // If nothing in the Module uses ARC, don't do anything. 2609c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman Run = ModuleHasARC(M); 2610c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman if (!Run) 2611c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman return false; 2612c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman 26139fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Identify the imprecise release metadata kind. 26149fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ImpreciseReleaseMDKind = 26159fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall M.getContext().getMDKindID("clang.imprecise_release"); 2616a974beaa1f63394a67c38c66ff0f39a759c7998fDan Gohman CopyOnEscapeMDKind = 2617a974beaa1f63394a67c38c66ff0f39a759c7998fDan Gohman M.getContext().getMDKindID("clang.arc.copy_on_escape"); 2618dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman NoObjCARCExceptionsMDKind = 2619dbe266be35cfee0fbda5523ac578fef81e8fdfccDan Gohman M.getContext().getMDKindID("clang.arc.no_objc_arc_exceptions"); 26209fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26219fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Intuitively, objc_retain and others are nocapture, however in practice 26229fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // they are not, because they return their argument value. And objc_release 2623447989cb680041ff484c8c00ee5b7135a9df6b3dDan Gohman // calls finalizers which can have arbitrary side effects. 26249fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26259fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // These are initialized lazily. 26269fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RetainRVCallee = 0; 26279fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AutoreleaseRVCallee = 0; 26289fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall ReleaseCallee = 0; 26299fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall RetainCallee = 0; 26304428069f10ac6e7efb55826437c82428d4bbe03eDan Gohman RetainBlockCallee = 0; 26319fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall AutoreleaseCallee = 0; 26329fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26339fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return false; 26349fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 26359fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26369fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallbool ObjCARCOpt::runOnFunction(Function &F) { 26379fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (!EnableARCOpts) 26389fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return false; 26399fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 2640c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman // If nothing in the Module uses ARC, don't do anything. 2641c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman if (!Run) 2642c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman return false; 2643c4bcd4d964327e52ceadcc9be270718d758f8535Dan Gohman 26449fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall Changed = false; 26459fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26460d3582b1d1bedde39f964420edd237583bc5a010Michael Gottesman DEBUG(dbgs() << "ObjCARCOpt: Visiting Function: " << F.getName() << "\n"); 26470d3582b1d1bedde39f964420edd237583bc5a010Michael Gottesman 26489fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PA.setAA(&getAnalysis<AliasAnalysis>()); 26499fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26509fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // This pass performs several distinct transformations. As a compile-time aid 26519fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // when compiling code that isn't ObjC, skip these if the relevant ObjC 26529fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // library functions aren't declared. 26539fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26549fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Preliminary optimizations. This also computs UsedInThisFunction. 26559fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall OptimizeIndividualCalls(F); 26569fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26579fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Optimizations for weak pointers. 26589fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (UsedInThisFunction & ((1 << IC_LoadWeak) | 26599fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall (1 << IC_LoadWeakRetained) | 26609fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall (1 << IC_StoreWeak) | 26619fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall (1 << IC_InitWeak) | 26629fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall (1 << IC_CopyWeak) | 26639fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall (1 << IC_MoveWeak) | 26649fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall (1 << IC_DestroyWeak))) 26659fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall OptimizeWeakCalls(F); 26669fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26679fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Optimizations for retain+release pairs. 26689fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (UsedInThisFunction & ((1 << IC_Retain) | 26699fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall (1 << IC_RetainRV) | 26709fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall (1 << IC_RetainBlock))) 26719fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall if (UsedInThisFunction & (1 << IC_Release)) 26729fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Run OptimizeSequences until it either stops making changes or 26739fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // no retain+release pair nesting is detected. 26749fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall while (OptimizeSequences(F)) {} 26759fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26769fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall // Optimizations if objc_autorelease is used. 26770daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman if (UsedInThisFunction & ((1 << IC_Autorelease) | 26780daef3d90278d6c110f9af1e9f806fd05450ff48Dan Gohman (1 << IC_AutoreleaseRV))) 26799fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall OptimizeReturns(F); 26809fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26810d3582b1d1bedde39f964420edd237583bc5a010Michael Gottesman DEBUG(dbgs() << "\n"); 26820d3582b1d1bedde39f964420edd237583bc5a010Michael Gottesman 26839fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall return Changed; 26849fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 26859fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 26869fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCallvoid ObjCARCOpt::releaseMemory() { 26879fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall PA.clear(); 26889fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall} 26899fbd318d36e618fb08fb53bb48b7c848e617a8a7John McCall 269081c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// @} 269181c6121699a66b3e84f7b794b375095a39584701Michael Gottesman/// 2692