1//===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9/// \file 10/// This file defines a simple ARC-aware AliasAnalysis using special knowledge 11/// of Objective C to enhance other optimization passes which rely on the Alias 12/// Analysis infrastructure. 13/// 14/// WARNING: This file knows about certain library functions. It recognizes them 15/// by name, and hardwires knowledge of their semantics. 16/// 17/// WARNING: This file knows about how certain Objective-C library functions are 18/// used. Naive LLVM IR transformations which would otherwise be 19/// behavior-preserving may break these assumptions. 20/// 21//===----------------------------------------------------------------------===// 22 23#define DEBUG_TYPE "objc-arc-aa" 24#include "ObjCARC.h" 25#include "ObjCARCAliasAnalysis.h" 26#include "llvm/IR/Instruction.h" 27#include "llvm/InitializePasses.h" 28#include "llvm/PassAnalysisSupport.h" 29#include "llvm/PassSupport.h" 30 31namespace llvm { 32 class Function; 33 class Value; 34} 35 36using namespace llvm; 37using namespace llvm::objcarc; 38 39// Register this pass... 40char ObjCARCAliasAnalysis::ID = 0; 41INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa", 42 "ObjC-ARC-Based Alias Analysis", false, true, false) 43 44ImmutablePass *llvm::createObjCARCAliasAnalysisPass() { 45 return new ObjCARCAliasAnalysis(); 46} 47 48void 49ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { 50 AU.setPreservesAll(); 51 AliasAnalysis::getAnalysisUsage(AU); 52} 53 54AliasAnalysis::AliasResult 55ObjCARCAliasAnalysis::alias(const Location &LocA, const Location &LocB) { 56 if (!EnableARCOpts) 57 return AliasAnalysis::alias(LocA, LocB); 58 59 // First, strip off no-ops, including ObjC-specific no-ops, and try making a 60 // precise alias query. 61 const Value *SA = StripPointerCastsAndObjCCalls(LocA.Ptr); 62 const Value *SB = StripPointerCastsAndObjCCalls(LocB.Ptr); 63 AliasResult Result = 64 AliasAnalysis::alias(Location(SA, LocA.Size, LocA.TBAATag), 65 Location(SB, LocB.Size, LocB.TBAATag)); 66 if (Result != MayAlias) 67 return Result; 68 69 // If that failed, climb to the underlying object, including climbing through 70 // ObjC-specific no-ops, and try making an imprecise alias query. 71 const Value *UA = GetUnderlyingObjCPtr(SA); 72 const Value *UB = GetUnderlyingObjCPtr(SB); 73 if (UA != SA || UB != SB) { 74 Result = AliasAnalysis::alias(Location(UA), Location(UB)); 75 // We can't use MustAlias or PartialAlias results here because 76 // GetUnderlyingObjCPtr may return an offsetted pointer value. 77 if (Result == NoAlias) 78 return NoAlias; 79 } 80 81 // If that failed, fail. We don't need to chain here, since that's covered 82 // by the earlier precise query. 83 return MayAlias; 84} 85 86bool 87ObjCARCAliasAnalysis::pointsToConstantMemory(const Location &Loc, 88 bool OrLocal) { 89 if (!EnableARCOpts) 90 return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); 91 92 // First, strip off no-ops, including ObjC-specific no-ops, and try making 93 // a precise alias query. 94 const Value *S = StripPointerCastsAndObjCCalls(Loc.Ptr); 95 if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.TBAATag), 96 OrLocal)) 97 return true; 98 99 // If that failed, climb to the underlying object, including climbing through 100 // ObjC-specific no-ops, and try making an imprecise alias query. 101 const Value *U = GetUnderlyingObjCPtr(S); 102 if (U != S) 103 return AliasAnalysis::pointsToConstantMemory(Location(U), OrLocal); 104 105 // If that failed, fail. We don't need to chain here, since that's covered 106 // by the earlier precise query. 107 return false; 108} 109 110AliasAnalysis::ModRefBehavior 111ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) { 112 // We have nothing to do. Just chain to the next AliasAnalysis. 113 return AliasAnalysis::getModRefBehavior(CS); 114} 115 116AliasAnalysis::ModRefBehavior 117ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) { 118 if (!EnableARCOpts) 119 return AliasAnalysis::getModRefBehavior(F); 120 121 switch (GetFunctionClass(F)) { 122 case IC_NoopCast: 123 return DoesNotAccessMemory; 124 default: 125 break; 126 } 127 128 return AliasAnalysis::getModRefBehavior(F); 129} 130 131AliasAnalysis::ModRefResult 132ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) { 133 if (!EnableARCOpts) 134 return AliasAnalysis::getModRefInfo(CS, Loc); 135 136 switch (GetBasicInstructionClass(CS.getInstruction())) { 137 case IC_Retain: 138 case IC_RetainRV: 139 case IC_Autorelease: 140 case IC_AutoreleaseRV: 141 case IC_NoopCast: 142 case IC_AutoreleasepoolPush: 143 case IC_FusedRetainAutorelease: 144 case IC_FusedRetainAutoreleaseRV: 145 // These functions don't access any memory visible to the compiler. 146 // Note that this doesn't include objc_retainBlock, because it updates 147 // pointers when it copies block data. 148 return NoModRef; 149 default: 150 break; 151 } 152 153 return AliasAnalysis::getModRefInfo(CS, Loc); 154} 155 156AliasAnalysis::ModRefResult 157ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1, 158 ImmutableCallSite CS2) { 159 // TODO: Theoretically we could check for dependencies between objc_* calls 160 // and OnlyAccessesArgumentPointees calls or other well-behaved calls. 161 return AliasAnalysis::getModRefInfo(CS1, CS2); 162} 163