LLVM  mainline
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 /// TODO: Theoretically we could check for dependencies between objc_* calls
00022 /// and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls.
00023 ///
00024 //===----------------------------------------------------------------------===//
00025 
00026 #include "llvm/Analysis/ObjCARCAliasAnalysis.h"
00027 #include "llvm/Analysis/ObjCARCAnalysisUtils.h"
00028 #include "llvm/IR/Function.h"
00029 #include "llvm/IR/Instruction.h"
00030 #include "llvm/IR/Value.h"
00031 #include "llvm/InitializePasses.h"
00032 #include "llvm/PassAnalysisSupport.h"
00033 #include "llvm/PassSupport.h"
00034 
00035 #define DEBUG_TYPE "objc-arc-aa"
00036 
00037 using namespace llvm;
00038 using namespace llvm::objcarc;
00039 
00040 AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA,
00041                                    const MemoryLocation &LocB) {
00042   if (!EnableARCOpts)
00043     return AAResultBase::alias(LocA, LocB);
00044 
00045   // First, strip off no-ops, including ObjC-specific no-ops, and try making a
00046   // precise alias query.
00047   const Value *SA = GetRCIdentityRoot(LocA.Ptr);
00048   const Value *SB = GetRCIdentityRoot(LocB.Ptr);
00049   AliasResult Result =
00050       AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
00051                           MemoryLocation(SB, LocB.Size, LocB.AATags));
00052   if (Result != MayAlias)
00053     return Result;
00054 
00055   // If that failed, climb to the underlying object, including climbing through
00056   // ObjC-specific no-ops, and try making an imprecise alias query.
00057   const Value *UA = GetUnderlyingObjCPtr(SA, DL);
00058   const Value *UB = GetUnderlyingObjCPtr(SB, DL);
00059   if (UA != SA || UB != SB) {
00060     Result = AAResultBase::alias(MemoryLocation(UA), MemoryLocation(UB));
00061     // We can't use MustAlias or PartialAlias results here because
00062     // GetUnderlyingObjCPtr may return an offsetted pointer value.
00063     if (Result == NoAlias)
00064       return NoAlias;
00065   }
00066 
00067   // If that failed, fail. We don't need to chain here, since that's covered
00068   // by the earlier precise query.
00069   return MayAlias;
00070 }
00071 
00072 bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
00073                                              bool OrLocal) {
00074   if (!EnableARCOpts)
00075     return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
00076 
00077   // First, strip off no-ops, including ObjC-specific no-ops, and try making
00078   // a precise alias query.
00079   const Value *S = GetRCIdentityRoot(Loc.Ptr);
00080   if (AAResultBase::pointsToConstantMemory(
00081           MemoryLocation(S, Loc.Size, Loc.AATags), OrLocal))
00082     return true;
00083 
00084   // If that failed, climb to the underlying object, including climbing through
00085   // ObjC-specific no-ops, and try making an imprecise alias query.
00086   const Value *U = GetUnderlyingObjCPtr(S, DL);
00087   if (U != S)
00088     return AAResultBase::pointsToConstantMemory(MemoryLocation(U), OrLocal);
00089 
00090   // If that failed, fail. We don't need to chain here, since that's covered
00091   // by the earlier precise query.
00092   return false;
00093 }
00094 
00095 FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) {
00096   if (!EnableARCOpts)
00097     return AAResultBase::getModRefBehavior(F);
00098 
00099   switch (GetFunctionClass(F)) {
00100   case ARCInstKind::NoopCast:
00101     return FMRB_DoesNotAccessMemory;
00102   default:
00103     break;
00104   }
00105 
00106   return AAResultBase::getModRefBehavior(F);
00107 }
00108 
00109 ModRefInfo ObjCARCAAResult::getModRefInfo(ImmutableCallSite CS,
00110                                           const MemoryLocation &Loc) {
00111   if (!EnableARCOpts)
00112     return AAResultBase::getModRefInfo(CS, Loc);
00113 
00114   switch (GetBasicARCInstKind(CS.getInstruction())) {
00115   case ARCInstKind::Retain:
00116   case ARCInstKind::RetainRV:
00117   case ARCInstKind::Autorelease:
00118   case ARCInstKind::AutoreleaseRV:
00119   case ARCInstKind::NoopCast:
00120   case ARCInstKind::AutoreleasepoolPush:
00121   case ARCInstKind::FusedRetainAutorelease:
00122   case ARCInstKind::FusedRetainAutoreleaseRV:
00123     // These functions don't access any memory visible to the compiler.
00124     // Note that this doesn't include objc_retainBlock, because it updates
00125     // pointers when it copies block data.
00126     return MRI_NoModRef;
00127   default:
00128     break;
00129   }
00130 
00131   return AAResultBase::getModRefInfo(CS, Loc);
00132 }
00133 
00134 ObjCARCAAResult ObjCARCAA::run(Function &F, AnalysisManager<Function> *AM) {
00135   return ObjCARCAAResult(F.getParent()->getDataLayout(),
00136                          AM->getResult<TargetLibraryAnalysis>(F));
00137 }
00138 
00139 char ObjCARCAA::PassID;
00140 
00141 char ObjCARCAAWrapperPass::ID = 0;
00142 INITIALIZE_PASS_BEGIN(ObjCARCAAWrapperPass, "objc-arc-aa",
00143                       "ObjC-ARC-Based Alias Analysis", false, true)
00144 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
00145 INITIALIZE_PASS_END(ObjCARCAAWrapperPass, "objc-arc-aa",
00146                     "ObjC-ARC-Based Alias Analysis", false, true)
00147 
00148 ImmutablePass *llvm::createObjCARCAAWrapperPass() {
00149   return new ObjCARCAAWrapperPass();
00150 }
00151 
00152 ObjCARCAAWrapperPass::ObjCARCAAWrapperPass() : ImmutablePass(ID) {
00153   initializeObjCARCAAWrapperPassPass(*PassRegistry::getPassRegistry());
00154 }
00155 
00156 bool ObjCARCAAWrapperPass::doInitialization(Module &M) {
00157   Result.reset(new ObjCARCAAResult(
00158       M.getDataLayout(), getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()));
00159   return false;
00160 }
00161 
00162 bool ObjCARCAAWrapperPass::doFinalization(Module &M) {
00163   Result.reset();
00164   return false;
00165 }
00166 
00167 void ObjCARCAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
00168   AU.setPreservesAll();
00169   AU.addRequired<TargetLibraryInfoWrapperPass>();
00170 }