LLVM API Documentation
00001 //===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 /// \file 00010 /// This file defines a simple ARC-aware AliasAnalysis using special knowledge 00011 /// of Objective C to enhance other optimization passes which rely on the Alias 00012 /// Analysis infrastructure. 00013 /// 00014 /// WARNING: This file knows about certain library functions. It recognizes them 00015 /// by name, and hardwires knowledge of their semantics. 00016 /// 00017 /// WARNING: This file knows about how certain Objective-C library functions are 00018 /// used. Naive LLVM IR transformations which would otherwise be 00019 /// behavior-preserving may break these assumptions. 00020 /// 00021 //===----------------------------------------------------------------------===// 00022 00023 #include "ObjCARC.h" 00024 #include "ObjCARCAliasAnalysis.h" 00025 #include "llvm/IR/Instruction.h" 00026 #include "llvm/InitializePasses.h" 00027 #include "llvm/PassAnalysisSupport.h" 00028 #include "llvm/PassSupport.h" 00029 00030 #define DEBUG_TYPE "objc-arc-aa" 00031 00032 namespace llvm { 00033 class Function; 00034 class Value; 00035 } 00036 00037 using namespace llvm; 00038 using namespace llvm::objcarc; 00039 00040 // Register this pass... 00041 char ObjCARCAliasAnalysis::ID = 0; 00042 INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa", 00043 "ObjC-ARC-Based Alias Analysis", false, true, false) 00044 00045 ImmutablePass *llvm::createObjCARCAliasAnalysisPass() { 00046 return new ObjCARCAliasAnalysis(); 00047 } 00048 00049 void 00050 ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { 00051 AU.setPreservesAll(); 00052 AliasAnalysis::getAnalysisUsage(AU); 00053 } 00054 00055 AliasAnalysis::AliasResult 00056 ObjCARCAliasAnalysis::alias(const Location &LocA, const Location &LocB) { 00057 if (!EnableARCOpts) 00058 return AliasAnalysis::alias(LocA, LocB); 00059 00060 // First, strip off no-ops, including ObjC-specific no-ops, and try making a 00061 // precise alias query. 00062 const Value *SA = StripPointerCastsAndObjCCalls(LocA.Ptr); 00063 const Value *SB = StripPointerCastsAndObjCCalls(LocB.Ptr); 00064 AliasResult Result = 00065 AliasAnalysis::alias(Location(SA, LocA.Size, LocA.AATags), 00066 Location(SB, LocB.Size, LocB.AATags)); 00067 if (Result != MayAlias) 00068 return Result; 00069 00070 // If that failed, climb to the underlying object, including climbing through 00071 // ObjC-specific no-ops, and try making an imprecise alias query. 00072 const Value *UA = GetUnderlyingObjCPtr(SA); 00073 const Value *UB = GetUnderlyingObjCPtr(SB); 00074 if (UA != SA || UB != SB) { 00075 Result = AliasAnalysis::alias(Location(UA), Location(UB)); 00076 // We can't use MustAlias or PartialAlias results here because 00077 // GetUnderlyingObjCPtr may return an offsetted pointer value. 00078 if (Result == NoAlias) 00079 return NoAlias; 00080 } 00081 00082 // If that failed, fail. We don't need to chain here, since that's covered 00083 // by the earlier precise query. 00084 return MayAlias; 00085 } 00086 00087 bool 00088 ObjCARCAliasAnalysis::pointsToConstantMemory(const Location &Loc, 00089 bool OrLocal) { 00090 if (!EnableARCOpts) 00091 return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); 00092 00093 // First, strip off no-ops, including ObjC-specific no-ops, and try making 00094 // a precise alias query. 00095 const Value *S = StripPointerCastsAndObjCCalls(Loc.Ptr); 00096 if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.AATags), 00097 OrLocal)) 00098 return true; 00099 00100 // If that failed, climb to the underlying object, including climbing through 00101 // ObjC-specific no-ops, and try making an imprecise alias query. 00102 const Value *U = GetUnderlyingObjCPtr(S); 00103 if (U != S) 00104 return AliasAnalysis::pointsToConstantMemory(Location(U), OrLocal); 00105 00106 // If that failed, fail. We don't need to chain here, since that's covered 00107 // by the earlier precise query. 00108 return false; 00109 } 00110 00111 AliasAnalysis::ModRefBehavior 00112 ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) { 00113 // We have nothing to do. Just chain to the next AliasAnalysis. 00114 return AliasAnalysis::getModRefBehavior(CS); 00115 } 00116 00117 AliasAnalysis::ModRefBehavior 00118 ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) { 00119 if (!EnableARCOpts) 00120 return AliasAnalysis::getModRefBehavior(F); 00121 00122 switch (GetFunctionClass(F)) { 00123 case IC_NoopCast: 00124 return DoesNotAccessMemory; 00125 default: 00126 break; 00127 } 00128 00129 return AliasAnalysis::getModRefBehavior(F); 00130 } 00131 00132 AliasAnalysis::ModRefResult 00133 ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) { 00134 if (!EnableARCOpts) 00135 return AliasAnalysis::getModRefInfo(CS, Loc); 00136 00137 switch (GetBasicInstructionClass(CS.getInstruction())) { 00138 case IC_Retain: 00139 case IC_RetainRV: 00140 case IC_Autorelease: 00141 case IC_AutoreleaseRV: 00142 case IC_NoopCast: 00143 case IC_AutoreleasepoolPush: 00144 case IC_FusedRetainAutorelease: 00145 case IC_FusedRetainAutoreleaseRV: 00146 // These functions don't access any memory visible to the compiler. 00147 // Note that this doesn't include objc_retainBlock, because it updates 00148 // pointers when it copies block data. 00149 return NoModRef; 00150 default: 00151 break; 00152 } 00153 00154 return AliasAnalysis::getModRefInfo(CS, Loc); 00155 } 00156 00157 AliasAnalysis::ModRefResult 00158 ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1, 00159 ImmutableCallSite CS2) { 00160 // TODO: Theoretically we could check for dependencies between objc_* calls 00161 // and OnlyAccessesArgumentPointees calls or other well-behaved calls. 00162 return AliasAnalysis::getModRefInfo(CS1, CS2); 00163 }