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#include "ObjCARC.h" 24#include "ObjCARCAliasAnalysis.h" 25#include "llvm/IR/Instruction.h" 26#include "llvm/InitializePasses.h" 27#include "llvm/PassAnalysisSupport.h" 28#include "llvm/PassSupport.h" 29 30#define DEBUG_TYPE "objc-arc-aa" 31 32namespace llvm { 33 class Function; 34 class Value; 35} 36 37using namespace llvm; 38using namespace llvm::objcarc; 39 40// Register this pass... 41char ObjCARCAliasAnalysis::ID = 0; 42INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa", 43 "ObjC-ARC-Based Alias Analysis", false, true, false) 44 45ImmutablePass *llvm::createObjCARCAliasAnalysisPass() { 46 return new ObjCARCAliasAnalysis(); 47} 48 49void 50ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { 51 AU.setPreservesAll(); 52 AliasAnalysis::getAnalysisUsage(AU); 53} 54 55AliasAnalysis::AliasResult 56ObjCARCAliasAnalysis::alias(const Location &LocA, const Location &LocB) { 57 if (!EnableARCOpts) 58 return AliasAnalysis::alias(LocA, LocB); 59 60 // First, strip off no-ops, including ObjC-specific no-ops, and try making a 61 // precise alias query. 62 const Value *SA = StripPointerCastsAndObjCCalls(LocA.Ptr); 63 const Value *SB = StripPointerCastsAndObjCCalls(LocB.Ptr); 64 AliasResult Result = 65 AliasAnalysis::alias(Location(SA, LocA.Size, LocA.TBAATag), 66 Location(SB, LocB.Size, LocB.TBAATag)); 67 if (Result != MayAlias) 68 return Result; 69 70 // If that failed, climb to the underlying object, including climbing through 71 // ObjC-specific no-ops, and try making an imprecise alias query. 72 const Value *UA = GetUnderlyingObjCPtr(SA); 73 const Value *UB = GetUnderlyingObjCPtr(SB); 74 if (UA != SA || UB != SB) { 75 Result = AliasAnalysis::alias(Location(UA), Location(UB)); 76 // We can't use MustAlias or PartialAlias results here because 77 // GetUnderlyingObjCPtr may return an offsetted pointer value. 78 if (Result == NoAlias) 79 return NoAlias; 80 } 81 82 // If that failed, fail. We don't need to chain here, since that's covered 83 // by the earlier precise query. 84 return MayAlias; 85} 86 87bool 88ObjCARCAliasAnalysis::pointsToConstantMemory(const Location &Loc, 89 bool OrLocal) { 90 if (!EnableARCOpts) 91 return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); 92 93 // First, strip off no-ops, including ObjC-specific no-ops, and try making 94 // a precise alias query. 95 const Value *S = StripPointerCastsAndObjCCalls(Loc.Ptr); 96 if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.TBAATag), 97 OrLocal)) 98 return true; 99 100 // If that failed, climb to the underlying object, including climbing through 101 // ObjC-specific no-ops, and try making an imprecise alias query. 102 const Value *U = GetUnderlyingObjCPtr(S); 103 if (U != S) 104 return AliasAnalysis::pointsToConstantMemory(Location(U), OrLocal); 105 106 // If that failed, fail. We don't need to chain here, since that's covered 107 // by the earlier precise query. 108 return false; 109} 110 111AliasAnalysis::ModRefBehavior 112ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) { 113 // We have nothing to do. Just chain to the next AliasAnalysis. 114 return AliasAnalysis::getModRefBehavior(CS); 115} 116 117AliasAnalysis::ModRefBehavior 118ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) { 119 if (!EnableARCOpts) 120 return AliasAnalysis::getModRefBehavior(F); 121 122 switch (GetFunctionClass(F)) { 123 case IC_NoopCast: 124 return DoesNotAccessMemory; 125 default: 126 break; 127 } 128 129 return AliasAnalysis::getModRefBehavior(F); 130} 131 132AliasAnalysis::ModRefResult 133ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) { 134 if (!EnableARCOpts) 135 return AliasAnalysis::getModRefInfo(CS, Loc); 136 137 switch (GetBasicInstructionClass(CS.getInstruction())) { 138 case IC_Retain: 139 case IC_RetainRV: 140 case IC_Autorelease: 141 case IC_AutoreleaseRV: 142 case IC_NoopCast: 143 case IC_AutoreleasepoolPush: 144 case IC_FusedRetainAutorelease: 145 case IC_FusedRetainAutoreleaseRV: 146 // These functions don't access any memory visible to the compiler. 147 // Note that this doesn't include objc_retainBlock, because it updates 148 // pointers when it copies block data. 149 return NoModRef; 150 default: 151 break; 152 } 153 154 return AliasAnalysis::getModRefInfo(CS, Loc); 155} 156 157AliasAnalysis::ModRefResult 158ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1, 159 ImmutableCallSite CS2) { 160 // TODO: Theoretically we could check for dependencies between objc_* calls 161 // and OnlyAccessesArgumentPointees calls or other well-behaved calls. 162 return AliasAnalysis::getModRefInfo(CS1, CS2); 163} 164