1 //===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -*- mode: c++ -*---===// 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 31 namespace llvm { 32 class Function; 33 class Value; 34 } 35 36 using namespace llvm; 37 using namespace llvm::objcarc; 38 39 // Register this pass... 40 char ObjCARCAliasAnalysis::ID = 0; 41 INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa", 42 "ObjC-ARC-Based Alias Analysis", false, true, false) 43 44 ImmutablePass *llvm::createObjCARCAliasAnalysisPass() { 45 return new ObjCARCAliasAnalysis(); 46 } 47 48 void 49 ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { 50 AU.setPreservesAll(); 51 AliasAnalysis::getAnalysisUsage(AU); 52 } 53 54 AliasAnalysis::AliasResult 55 ObjCARCAliasAnalysis::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 86 bool 87 ObjCARCAliasAnalysis::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 110 AliasAnalysis::ModRefBehavior 111 ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) { 112 // We have nothing to do. Just chain to the next AliasAnalysis. 113 return AliasAnalysis::getModRefBehavior(CS); 114 } 115 116 AliasAnalysis::ModRefBehavior 117 ObjCARCAliasAnalysis::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 131 AliasAnalysis::ModRefResult 132 ObjCARCAliasAnalysis::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 156 AliasAnalysis::ModRefResult 157 ObjCARCAliasAnalysis::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