LLVM API Documentation

ObjCARCAliasAnalysis.cpp
Go to the documentation of this file.
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 }