1263508Sdim//===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim/// \file 10249259Sdim/// This file defines a simple ARC-aware AliasAnalysis using special knowledge 11249259Sdim/// of Objective C to enhance other optimization passes which rely on the Alias 12249259Sdim/// Analysis infrastructure. 13249259Sdim/// 14249259Sdim/// WARNING: This file knows about certain library functions. It recognizes them 15249259Sdim/// by name, and hardwires knowledge of their semantics. 16249259Sdim/// 17249259Sdim/// WARNING: This file knows about how certain Objective-C library functions are 18249259Sdim/// used. Naive LLVM IR transformations which would otherwise be 19249259Sdim/// behavior-preserving may break these assumptions. 20249259Sdim/// 21249259Sdim//===----------------------------------------------------------------------===// 22249259Sdim 23249259Sdim#define DEBUG_TYPE "objc-arc-aa" 24249259Sdim#include "ObjCARC.h" 25249259Sdim#include "ObjCARCAliasAnalysis.h" 26249259Sdim#include "llvm/IR/Instruction.h" 27249259Sdim#include "llvm/InitializePasses.h" 28249259Sdim#include "llvm/PassAnalysisSupport.h" 29249259Sdim#include "llvm/PassSupport.h" 30249259Sdim 31249259Sdimnamespace llvm { 32249259Sdim class Function; 33249259Sdim class Value; 34249259Sdim} 35249259Sdim 36249259Sdimusing namespace llvm; 37249259Sdimusing namespace llvm::objcarc; 38249259Sdim 39249259Sdim// Register this pass... 40249259Sdimchar ObjCARCAliasAnalysis::ID = 0; 41249259SdimINITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa", 42249259Sdim "ObjC-ARC-Based Alias Analysis", false, true, false) 43249259Sdim 44249259SdimImmutablePass *llvm::createObjCARCAliasAnalysisPass() { 45249259Sdim return new ObjCARCAliasAnalysis(); 46249259Sdim} 47249259Sdim 48249259Sdimvoid 49249259SdimObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { 50249259Sdim AU.setPreservesAll(); 51249259Sdim AliasAnalysis::getAnalysisUsage(AU); 52249259Sdim} 53249259Sdim 54249259SdimAliasAnalysis::AliasResult 55249259SdimObjCARCAliasAnalysis::alias(const Location &LocA, const Location &LocB) { 56249259Sdim if (!EnableARCOpts) 57249259Sdim return AliasAnalysis::alias(LocA, LocB); 58249259Sdim 59249259Sdim // First, strip off no-ops, including ObjC-specific no-ops, and try making a 60249259Sdim // precise alias query. 61249259Sdim const Value *SA = StripPointerCastsAndObjCCalls(LocA.Ptr); 62249259Sdim const Value *SB = StripPointerCastsAndObjCCalls(LocB.Ptr); 63249259Sdim AliasResult Result = 64249259Sdim AliasAnalysis::alias(Location(SA, LocA.Size, LocA.TBAATag), 65249259Sdim Location(SB, LocB.Size, LocB.TBAATag)); 66249259Sdim if (Result != MayAlias) 67249259Sdim return Result; 68249259Sdim 69249259Sdim // If that failed, climb to the underlying object, including climbing through 70249259Sdim // ObjC-specific no-ops, and try making an imprecise alias query. 71249259Sdim const Value *UA = GetUnderlyingObjCPtr(SA); 72249259Sdim const Value *UB = GetUnderlyingObjCPtr(SB); 73249259Sdim if (UA != SA || UB != SB) { 74249259Sdim Result = AliasAnalysis::alias(Location(UA), Location(UB)); 75249259Sdim // We can't use MustAlias or PartialAlias results here because 76249259Sdim // GetUnderlyingObjCPtr may return an offsetted pointer value. 77249259Sdim if (Result == NoAlias) 78249259Sdim return NoAlias; 79249259Sdim } 80249259Sdim 81249259Sdim // If that failed, fail. We don't need to chain here, since that's covered 82249259Sdim // by the earlier precise query. 83249259Sdim return MayAlias; 84249259Sdim} 85249259Sdim 86249259Sdimbool 87249259SdimObjCARCAliasAnalysis::pointsToConstantMemory(const Location &Loc, 88249259Sdim bool OrLocal) { 89249259Sdim if (!EnableARCOpts) 90249259Sdim return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); 91249259Sdim 92249259Sdim // First, strip off no-ops, including ObjC-specific no-ops, and try making 93249259Sdim // a precise alias query. 94249259Sdim const Value *S = StripPointerCastsAndObjCCalls(Loc.Ptr); 95249259Sdim if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.TBAATag), 96249259Sdim OrLocal)) 97249259Sdim return true; 98249259Sdim 99249259Sdim // If that failed, climb to the underlying object, including climbing through 100249259Sdim // ObjC-specific no-ops, and try making an imprecise alias query. 101249259Sdim const Value *U = GetUnderlyingObjCPtr(S); 102249259Sdim if (U != S) 103249259Sdim return AliasAnalysis::pointsToConstantMemory(Location(U), OrLocal); 104249259Sdim 105249259Sdim // If that failed, fail. We don't need to chain here, since that's covered 106249259Sdim // by the earlier precise query. 107249259Sdim return false; 108249259Sdim} 109249259Sdim 110249259SdimAliasAnalysis::ModRefBehavior 111249259SdimObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) { 112249259Sdim // We have nothing to do. Just chain to the next AliasAnalysis. 113249259Sdim return AliasAnalysis::getModRefBehavior(CS); 114249259Sdim} 115249259Sdim 116249259SdimAliasAnalysis::ModRefBehavior 117249259SdimObjCARCAliasAnalysis::getModRefBehavior(const Function *F) { 118249259Sdim if (!EnableARCOpts) 119249259Sdim return AliasAnalysis::getModRefBehavior(F); 120249259Sdim 121249259Sdim switch (GetFunctionClass(F)) { 122249259Sdim case IC_NoopCast: 123249259Sdim return DoesNotAccessMemory; 124249259Sdim default: 125249259Sdim break; 126249259Sdim } 127249259Sdim 128249259Sdim return AliasAnalysis::getModRefBehavior(F); 129249259Sdim} 130249259Sdim 131249259SdimAliasAnalysis::ModRefResult 132249259SdimObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) { 133249259Sdim if (!EnableARCOpts) 134249259Sdim return AliasAnalysis::getModRefInfo(CS, Loc); 135249259Sdim 136249259Sdim switch (GetBasicInstructionClass(CS.getInstruction())) { 137249259Sdim case IC_Retain: 138249259Sdim case IC_RetainRV: 139249259Sdim case IC_Autorelease: 140249259Sdim case IC_AutoreleaseRV: 141249259Sdim case IC_NoopCast: 142249259Sdim case IC_AutoreleasepoolPush: 143249259Sdim case IC_FusedRetainAutorelease: 144249259Sdim case IC_FusedRetainAutoreleaseRV: 145249259Sdim // These functions don't access any memory visible to the compiler. 146249259Sdim // Note that this doesn't include objc_retainBlock, because it updates 147249259Sdim // pointers when it copies block data. 148249259Sdim return NoModRef; 149249259Sdim default: 150249259Sdim break; 151249259Sdim } 152249259Sdim 153249259Sdim return AliasAnalysis::getModRefInfo(CS, Loc); 154249259Sdim} 155249259Sdim 156249259SdimAliasAnalysis::ModRefResult 157249259SdimObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1, 158249259Sdim ImmutableCallSite CS2) { 159249259Sdim // TODO: Theoretically we could check for dependencies between objc_* calls 160249259Sdim // and OnlyAccessesArgumentPointees calls or other well-behaved calls. 161249259Sdim return AliasAnalysis::getModRefInfo(CS1, CS2); 162249259Sdim} 163