Home | History | Annotate | Download | only in Analysis
      1 //===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===//
      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 /// TODO: Theoretically we could check for dependencies between objc_* calls
     22 /// and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls.
     23 ///
     24 //===----------------------------------------------------------------------===//
     25 
     26 #include "llvm/Analysis/ObjCARCAliasAnalysis.h"
     27 #include "llvm/Analysis/ObjCARCAnalysisUtils.h"
     28 #include "llvm/IR/Function.h"
     29 #include "llvm/IR/Instruction.h"
     30 #include "llvm/IR/Value.h"
     31 #include "llvm/InitializePasses.h"
     32 #include "llvm/PassAnalysisSupport.h"
     33 #include "llvm/PassSupport.h"
     34 
     35 #define DEBUG_TYPE "objc-arc-aa"
     36 
     37 using namespace llvm;
     38 using namespace llvm::objcarc;
     39 
     40 AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA,
     41                                    const MemoryLocation &LocB) {
     42   if (!EnableARCOpts)
     43     return AAResultBase::alias(LocA, LocB);
     44 
     45   // First, strip off no-ops, including ObjC-specific no-ops, and try making a
     46   // precise alias query.
     47   const Value *SA = GetRCIdentityRoot(LocA.Ptr);
     48   const Value *SB = GetRCIdentityRoot(LocB.Ptr);
     49   AliasResult Result =
     50       AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
     51                           MemoryLocation(SB, LocB.Size, LocB.AATags));
     52   if (Result != MayAlias)
     53     return Result;
     54 
     55   // If that failed, climb to the underlying object, including climbing through
     56   // ObjC-specific no-ops, and try making an imprecise alias query.
     57   const Value *UA = GetUnderlyingObjCPtr(SA, DL);
     58   const Value *UB = GetUnderlyingObjCPtr(SB, DL);
     59   if (UA != SA || UB != SB) {
     60     Result = AAResultBase::alias(MemoryLocation(UA), MemoryLocation(UB));
     61     // We can't use MustAlias or PartialAlias results here because
     62     // GetUnderlyingObjCPtr may return an offsetted pointer value.
     63     if (Result == NoAlias)
     64       return NoAlias;
     65   }
     66 
     67   // If that failed, fail. We don't need to chain here, since that's covered
     68   // by the earlier precise query.
     69   return MayAlias;
     70 }
     71 
     72 bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
     73                                              bool OrLocal) {
     74   if (!EnableARCOpts)
     75     return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
     76 
     77   // First, strip off no-ops, including ObjC-specific no-ops, and try making
     78   // a precise alias query.
     79   const Value *S = GetRCIdentityRoot(Loc.Ptr);
     80   if (AAResultBase::pointsToConstantMemory(
     81           MemoryLocation(S, Loc.Size, Loc.AATags), OrLocal))
     82     return true;
     83 
     84   // If that failed, climb to the underlying object, including climbing through
     85   // ObjC-specific no-ops, and try making an imprecise alias query.
     86   const Value *U = GetUnderlyingObjCPtr(S, DL);
     87   if (U != S)
     88     return AAResultBase::pointsToConstantMemory(MemoryLocation(U), OrLocal);
     89 
     90   // If that failed, fail. We don't need to chain here, since that's covered
     91   // by the earlier precise query.
     92   return false;
     93 }
     94 
     95 FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) {
     96   if (!EnableARCOpts)
     97     return AAResultBase::getModRefBehavior(F);
     98 
     99   switch (GetFunctionClass(F)) {
    100   case ARCInstKind::NoopCast:
    101     return FMRB_DoesNotAccessMemory;
    102   default:
    103     break;
    104   }
    105 
    106   return AAResultBase::getModRefBehavior(F);
    107 }
    108 
    109 ModRefInfo ObjCARCAAResult::getModRefInfo(ImmutableCallSite CS,
    110                                           const MemoryLocation &Loc) {
    111   if (!EnableARCOpts)
    112     return AAResultBase::getModRefInfo(CS, Loc);
    113 
    114   switch (GetBasicARCInstKind(CS.getInstruction())) {
    115   case ARCInstKind::Retain:
    116   case ARCInstKind::RetainRV:
    117   case ARCInstKind::Autorelease:
    118   case ARCInstKind::AutoreleaseRV:
    119   case ARCInstKind::NoopCast:
    120   case ARCInstKind::AutoreleasepoolPush:
    121   case ARCInstKind::FusedRetainAutorelease:
    122   case ARCInstKind::FusedRetainAutoreleaseRV:
    123     // These functions don't access any memory visible to the compiler.
    124     // Note that this doesn't include objc_retainBlock, because it updates
    125     // pointers when it copies block data.
    126     return MRI_NoModRef;
    127   default:
    128     break;
    129   }
    130 
    131   return AAResultBase::getModRefInfo(CS, Loc);
    132 }
    133 
    134 ObjCARCAAResult ObjCARCAA::run(Function &F, AnalysisManager<Function> &AM) {
    135   return ObjCARCAAResult(F.getParent()->getDataLayout());
    136 }
    137 
    138 char ObjCARCAAWrapperPass::ID = 0;
    139 INITIALIZE_PASS(ObjCARCAAWrapperPass, "objc-arc-aa",
    140                 "ObjC-ARC-Based Alias Analysis", false, true)
    141 
    142 ImmutablePass *llvm::createObjCARCAAWrapperPass() {
    143   return new ObjCARCAAWrapperPass();
    144 }
    145 
    146 ObjCARCAAWrapperPass::ObjCARCAAWrapperPass() : ImmutablePass(ID) {
    147   initializeObjCARCAAWrapperPassPass(*PassRegistry::getPassRegistry());
    148 }
    149 
    150 bool ObjCARCAAWrapperPass::doInitialization(Module &M) {
    151   Result.reset(new ObjCARCAAResult(M.getDataLayout()));
    152   return false;
    153 }
    154 
    155 bool ObjCARCAAWrapperPass::doFinalization(Module &M) {
    156   Result.reset();
    157   return false;
    158 }
    159 
    160 void ObjCARCAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
    161   AU.setPreservesAll();
    162 }
    163