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 bool ObjCARCAliasAnalysis::doInitialization(Module &M) {
00050   InitializeAliasAnalysis(this, &M.getDataLayout());
00051   return true;
00052 }
00053 
00054 void
00055 ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
00056   AU.setPreservesAll();
00057   AliasAnalysis::getAnalysisUsage(AU);
00058 }
00059 
00060 AliasAnalysis::AliasResult
00061 ObjCARCAliasAnalysis::alias(const Location &LocA, const Location &LocB) {
00062   if (!EnableARCOpts)
00063     return AliasAnalysis::alias(LocA, LocB);
00064 
00065   // First, strip off no-ops, including ObjC-specific no-ops, and try making a
00066   // precise alias query.
00067   const Value *SA = GetRCIdentityRoot(LocA.Ptr);
00068   const Value *SB = GetRCIdentityRoot(LocB.Ptr);
00069   AliasResult Result =
00070     AliasAnalysis::alias(Location(SA, LocA.Size, LocA.AATags),
00071                          Location(SB, LocB.Size, LocB.AATags));
00072   if (Result != MayAlias)
00073     return Result;
00074 
00075   // If that failed, climb to the underlying object, including climbing through
00076   // ObjC-specific no-ops, and try making an imprecise alias query.
00077   const Value *UA = GetUnderlyingObjCPtr(SA);
00078   const Value *UB = GetUnderlyingObjCPtr(SB);
00079   if (UA != SA || UB != SB) {
00080     Result = AliasAnalysis::alias(Location(UA), Location(UB));
00081     // We can't use MustAlias or PartialAlias results here because
00082     // GetUnderlyingObjCPtr may return an offsetted pointer value.
00083     if (Result == NoAlias)
00084       return NoAlias;
00085   }
00086 
00087   // If that failed, fail. We don't need to chain here, since that's covered
00088   // by the earlier precise query.
00089   return MayAlias;
00090 }
00091 
00092 bool
00093 ObjCARCAliasAnalysis::pointsToConstantMemory(const Location &Loc,
00094                                              bool OrLocal) {
00095   if (!EnableARCOpts)
00096     return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
00097 
00098   // First, strip off no-ops, including ObjC-specific no-ops, and try making
00099   // a precise alias query.
00100   const Value *S = GetRCIdentityRoot(Loc.Ptr);
00101   if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.AATags),
00102                                             OrLocal))
00103     return true;
00104 
00105   // If that failed, climb to the underlying object, including climbing through
00106   // ObjC-specific no-ops, and try making an imprecise alias query.
00107   const Value *U = GetUnderlyingObjCPtr(S);
00108   if (U != S)
00109     return AliasAnalysis::pointsToConstantMemory(Location(U), OrLocal);
00110 
00111   // If that failed, fail. We don't need to chain here, since that's covered
00112   // by the earlier precise query.
00113   return false;
00114 }
00115 
00116 AliasAnalysis::ModRefBehavior
00117 ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
00118   // We have nothing to do. Just chain to the next AliasAnalysis.
00119   return AliasAnalysis::getModRefBehavior(CS);
00120 }
00121 
00122 AliasAnalysis::ModRefBehavior
00123 ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) {
00124   if (!EnableARCOpts)
00125     return AliasAnalysis::getModRefBehavior(F);
00126 
00127   switch (GetFunctionClass(F)) {
00128   case ARCInstKind::NoopCast:
00129     return DoesNotAccessMemory;
00130   default:
00131     break;
00132   }
00133 
00134   return AliasAnalysis::getModRefBehavior(F);
00135 }
00136 
00137 AliasAnalysis::ModRefResult
00138 ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) {
00139   if (!EnableARCOpts)
00140     return AliasAnalysis::getModRefInfo(CS, Loc);
00141 
00142   switch (GetBasicARCInstKind(CS.getInstruction())) {
00143   case ARCInstKind::Retain:
00144   case ARCInstKind::RetainRV:
00145   case ARCInstKind::Autorelease:
00146   case ARCInstKind::AutoreleaseRV:
00147   case ARCInstKind::NoopCast:
00148   case ARCInstKind::AutoreleasepoolPush:
00149   case ARCInstKind::FusedRetainAutorelease:
00150   case ARCInstKind::FusedRetainAutoreleaseRV:
00151     // These functions don't access any memory visible to the compiler.
00152     // Note that this doesn't include objc_retainBlock, because it updates
00153     // pointers when it copies block data.
00154     return NoModRef;
00155   default:
00156     break;
00157   }
00158 
00159   return AliasAnalysis::getModRefInfo(CS, Loc);
00160 }
00161 
00162 AliasAnalysis::ModRefResult
00163 ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
00164                                     ImmutableCallSite CS2) {
00165   // TODO: Theoretically we could check for dependencies between objc_* calls
00166   // and OnlyAccessesArgumentPointees calls or other well-behaved calls.
00167   return AliasAnalysis::getModRefInfo(CS1, CS2);
00168 }