1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 20:23:11 +01:00

Refactor ObjCARCAliasAnalysis into its own file.

llvm-svn: 173662
This commit is contained in:
Michael Gottesman 2013-01-28 05:51:54 +00:00
parent fbc4fffb48
commit 86d4759cc7
5 changed files with 352 additions and 283 deletions

View File

@ -3,6 +3,7 @@ add_llvm_library(LLVMObjCARCOpts
ObjCARCOpts.cpp
ObjCARCExpand.cpp
ObjCARCAPElim.cpp
ObjCARCAliasAnalysis.cpp
)
add_dependencies(LLVMObjCARCOpts intrinsics_gen)

View File

@ -26,6 +26,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
@ -145,10 +146,81 @@ static raw_ostream &operator<<(raw_ostream &OS, const InstructionClass Class) {
llvm_unreachable("Unknown instruction class!");
}
/// \brief Test if the given class is objc_retain or equivalent.
static inline bool IsRetain(InstructionClass Class) {
return Class == IC_Retain ||
Class == IC_RetainRV;
}
/// \brief Test if the given class is objc_autorelease or equivalent.
static inline bool IsAutorelease(InstructionClass Class) {
return Class == IC_Autorelease ||
Class == IC_AutoreleaseRV;
}
/// \brief Test if the given class represents instructions which return their
/// argument verbatim.
static inline bool IsForwarding(InstructionClass Class) {
// objc_retainBlock technically doesn't always return its argument
// verbatim, but it doesn't matter for our purposes here.
return Class == IC_Retain ||
Class == IC_RetainRV ||
Class == IC_Autorelease ||
Class == IC_AutoreleaseRV ||
Class == IC_RetainBlock ||
Class == IC_NoopCast;
}
/// \brief Test if the given class represents instructions which do nothing if
/// passed a null pointer.
static inline bool IsNoopOnNull(InstructionClass Class) {
return Class == IC_Retain ||
Class == IC_RetainRV ||
Class == IC_Release ||
Class == IC_Autorelease ||
Class == IC_AutoreleaseRV ||
Class == IC_RetainBlock;
}
/// \brief Test if the given class represents instructions which are always safe
/// to mark with the "tail" keyword.
static inline bool IsAlwaysTail(InstructionClass Class) {
// IC_RetainBlock may be given a stack argument.
return Class == IC_Retain ||
Class == IC_RetainRV ||
Class == IC_AutoreleaseRV;
}
/// \brief Test if the given class represents instructions which are never safe
/// to mark with the "tail" keyword.
static inline bool IsNeverTail(InstructionClass Class) {
/// It is never safe to tail call objc_autorelease since by tail calling
/// objc_autorelease, we also tail call -[NSObject autorelease] which supports
/// fast autoreleasing causing our object to be potentially reclaimed from the
/// autorelease pool which violates the semantics of __autoreleasing types in
/// ARC.
return Class == IC_Autorelease;
}
/// \brief Test if the given class represents instructions which are always safe
/// to mark with the nounwind attribute.
static inline bool IsNoThrow(InstructionClass Class) {
// objc_retainBlock is not nounwind because it calls user copy constructors
// which could theoretically throw.
return Class == IC_Retain ||
Class == IC_RetainRV ||
Class == IC_Release ||
Class == IC_Autorelease ||
Class == IC_AutoreleaseRV ||
Class == IC_AutoreleasepoolPush ||
Class == IC_AutoreleasepoolPop;
}
/// \brief Determine if F is one of the special known Functions. If it isn't,
/// return IC_CallOrUser.
static inline InstructionClass GetFunctionClass(const Function *F) {
static InstructionClass GetFunctionClass(const Function *F)
LLVM_ATTRIBUTE_USED;
static InstructionClass GetFunctionClass(const Function *F) {
Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
// No arguments.
@ -236,6 +308,48 @@ static inline InstructionClass GetBasicInstructionClass(const Value *V) {
return isa<InvokeInst>(V) ? IC_CallOrUser : IC_User;
}
/// \brief This is a wrapper around getUnderlyingObject which also knows how to
/// look through objc_retain and objc_autorelease calls, which we know to return
/// their argument verbatim.
static inline const Value *GetUnderlyingObjCPtr(const Value *V) {
for (;;) {
V = GetUnderlyingObject(V);
if (!IsForwarding(GetBasicInstructionClass(V)))
break;
V = cast<CallInst>(V)->getArgOperand(0);
}
return V;
}
/// \brief This is a wrapper around Value::stripPointerCasts which also knows
/// how to look through objc_retain and objc_autorelease calls, which we know to
/// return their argument verbatim.
static inline const Value *StripPointerCastsAndObjCCalls(const Value *V) {
for (;;) {
V = V->stripPointerCasts();
if (!IsForwarding(GetBasicInstructionClass(V)))
break;
V = cast<CallInst>(V)->getArgOperand(0);
}
return V;
}
/// \brief This is a wrapper around Value::stripPointerCasts which also knows
/// how to look through objc_retain and objc_autorelease calls, which we know to
/// return their argument verbatim.
static inline Value *StripPointerCastsAndObjCCalls(Value *V) {
for (;;) {
V = V->stripPointerCasts();
if (!IsForwarding(GetBasicInstructionClass(V)))
break;
V = cast<CallInst>(V)->getArgOperand(0);
}
return V;
}
} // end namespace objcarc
} // end namespace llvm

View File

@ -0,0 +1,164 @@
//===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -*- mode: c++ -*---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file defines a simple ARC-aware AliasAnalysis using special knowledge
/// of Objective C to enhance other optimization passes which rely on the Alias
/// Analysis infrastructure.
///
/// WARNING: This file knows about certain library functions. It recognizes them
/// by name, and hardwires knowledge of their semantics.
///
/// WARNING: This file knows about how certain Objective-C library functions are
/// used. Naive LLVM IR transformations which would otherwise be
/// behavior-preserving may break these assumptions.
///
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "objc-arc-aa"
#include "ObjCARC.h"
#include "ObjCARCAliasAnalysis.h"
#include "llvm/IR/Instruction.h"
#include "llvm/InitializePasses.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/PassSupport.h"
namespace llvm {
class Function;
class Value;
}
using namespace llvm;
using namespace llvm::objcarc;
// Register this pass...
char ObjCARCAliasAnalysis::ID = 0;
INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa",
"ObjC-ARC-Based Alias Analysis", false, true, false)
ImmutablePass *llvm::createObjCARCAliasAnalysisPass() {
return new ObjCARCAliasAnalysis();
}
void
ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AliasAnalysis::getAnalysisUsage(AU);
}
AliasAnalysis::AliasResult
ObjCARCAliasAnalysis::alias(const Location &LocA, const Location &LocB) {
if (!EnableARCOpts)
return AliasAnalysis::alias(LocA, LocB);
// First, strip off no-ops, including ObjC-specific no-ops, and try making a
// precise alias query.
const Value *SA = StripPointerCastsAndObjCCalls(LocA.Ptr);
const Value *SB = StripPointerCastsAndObjCCalls(LocB.Ptr);
AliasResult Result =
AliasAnalysis::alias(Location(SA, LocA.Size, LocA.TBAATag),
Location(SB, LocB.Size, LocB.TBAATag));
if (Result != MayAlias)
return Result;
// If that failed, climb to the underlying object, including climbing through
// ObjC-specific no-ops, and try making an imprecise alias query.
const Value *UA = GetUnderlyingObjCPtr(SA);
const Value *UB = GetUnderlyingObjCPtr(SB);
if (UA != SA || UB != SB) {
Result = AliasAnalysis::alias(Location(UA), Location(UB));
// We can't use MustAlias or PartialAlias results here because
// GetUnderlyingObjCPtr may return an offsetted pointer value.
if (Result == NoAlias)
return NoAlias;
}
// If that failed, fail. We don't need to chain here, since that's covered
// by the earlier precise query.
return MayAlias;
}
bool
ObjCARCAliasAnalysis::pointsToConstantMemory(const Location &Loc,
bool OrLocal) {
if (!EnableARCOpts)
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
// First, strip off no-ops, including ObjC-specific no-ops, and try making
// a precise alias query.
const Value *S = StripPointerCastsAndObjCCalls(Loc.Ptr);
if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.TBAATag),
OrLocal))
return true;
// If that failed, climb to the underlying object, including climbing through
// ObjC-specific no-ops, and try making an imprecise alias query.
const Value *U = GetUnderlyingObjCPtr(S);
if (U != S)
return AliasAnalysis::pointsToConstantMemory(Location(U), OrLocal);
// If that failed, fail. We don't need to chain here, since that's covered
// by the earlier precise query.
return false;
}
AliasAnalysis::ModRefBehavior
ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
// We have nothing to do. Just chain to the next AliasAnalysis.
return AliasAnalysis::getModRefBehavior(CS);
}
AliasAnalysis::ModRefBehavior
ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) {
if (!EnableARCOpts)
return AliasAnalysis::getModRefBehavior(F);
switch (GetFunctionClass(F)) {
case IC_NoopCast:
return DoesNotAccessMemory;
default:
break;
}
return AliasAnalysis::getModRefBehavior(F);
}
AliasAnalysis::ModRefResult
ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) {
if (!EnableARCOpts)
return AliasAnalysis::getModRefInfo(CS, Loc);
switch (GetBasicInstructionClass(CS.getInstruction())) {
case IC_Retain:
case IC_RetainRV:
case IC_Autorelease:
case IC_AutoreleaseRV:
case IC_NoopCast:
case IC_AutoreleasepoolPush:
case IC_FusedRetainAutorelease:
case IC_FusedRetainAutoreleaseRV:
// These functions don't access any memory visible to the compiler.
// Note that this doesn't include objc_retainBlock, because it updates
// pointers when it copies block data.
return NoModRef;
default:
break;
}
return AliasAnalysis::getModRefInfo(CS, Loc);
}
AliasAnalysis::ModRefResult
ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) {
// TODO: Theoretically we could check for dependencies between objc_* calls
// and OnlyAccessesArgumentPointees calls or other well-behaved calls.
return AliasAnalysis::getModRefInfo(CS1, CS2);
}

View File

@ -0,0 +1,71 @@
//===- ObjCARCAliasAnalysis.h - ObjC ARC Optimization -*- mode: c++ -*-----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares a simple ARC-aware AliasAnalysis using special knowledge
/// of Objective C to enhance other optimization passes which rely on the Alias
/// Analysis infrastructure.
///
/// WARNING: This file knows about certain library functions. It recognizes them
/// by name, and hardwires knowledge of their semantics.
///
/// WARNING: This file knows about how certain Objective-C library functions are
/// used. Naive LLVM IR transformations which would otherwise be
/// behavior-preserving may break these assumptions.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_OBJCARC_OBJCARCALIASANALYSIS_H
#define LLVM_TRANSFORMS_OBJCARC_OBJCARCALIASANALYSIS_H
namespace llvm {
namespace objcarc {
/// \brief This is a simple alias analysis implementation that uses knowledge
/// of ARC constructs to answer queries.
///
/// TODO: This class could be generalized to know about other ObjC-specific
/// tricks. Such as knowing that ivars in the non-fragile ABI are non-aliasing
/// even though their offsets are dynamic.
class ObjCARCAliasAnalysis : public ImmutablePass,
public AliasAnalysis {
public:
static char ID; // Class identification, replacement for typeinfo
ObjCARCAliasAnalysis() : ImmutablePass(ID) {
initializeObjCARCAliasAnalysisPass(*PassRegistry::getPassRegistry());
}
private:
virtual void initializePass() {
InitializeAliasAnalysis(this);
}
/// This method is used when a pass implements an analysis interface through
/// multiple inheritance. If needed, it should override this to adjust the
/// this pointer as needed for the specified pass info.
virtual void *getAdjustedAnalysisPointer(const void *PI) {
if (PI == &AliasAnalysis::ID)
return static_cast<AliasAnalysis *>(this);
return this;
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual AliasResult alias(const Location &LocA, const Location &LocB);
virtual bool pointsToConstantMemory(const Location &Loc, bool OrLocal);
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS);
virtual ModRefBehavior getModRefBehavior(const Function *F);
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
const Location &Loc);
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2);
};
} // namespace objcarc
} // namespace llvm
#endif // LLVM_TRANSFORMS_OBJCARC_OBJCARCALIASANALYSIS_H

View File

@ -30,6 +30,7 @@
#define DEBUG_TYPE "objc-arc-opts"
#include "ObjCARC.h"
#include "ObjCARCAliasAnalysis.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
@ -131,7 +132,6 @@ namespace {
/// \defgroup ARCUtilities Utility declarations/definitions specific to ARC.
/// @{
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Transforms/Utils/Local.h"
@ -260,76 +260,6 @@ static InstructionClass GetInstructionClass(const Value *V) {
return IC_None;
}
/// \brief Test if the given class is objc_retain or equivalent.
static bool IsRetain(InstructionClass Class) {
return Class == IC_Retain ||
Class == IC_RetainRV;
}
/// \brief Test if the given class is objc_autorelease or equivalent.
static bool IsAutorelease(InstructionClass Class) {
return Class == IC_Autorelease ||
Class == IC_AutoreleaseRV;
}
/// \brief Test if the given class represents instructions which return their
/// argument verbatim.
static bool IsForwarding(InstructionClass Class) {
// objc_retainBlock technically doesn't always return its argument
// verbatim, but it doesn't matter for our purposes here.
return Class == IC_Retain ||
Class == IC_RetainRV ||
Class == IC_Autorelease ||
Class == IC_AutoreleaseRV ||
Class == IC_RetainBlock ||
Class == IC_NoopCast;
}
/// \brief Test if the given class represents instructions which do nothing if
/// passed a null pointer.
static bool IsNoopOnNull(InstructionClass Class) {
return Class == IC_Retain ||
Class == IC_RetainRV ||
Class == IC_Release ||
Class == IC_Autorelease ||
Class == IC_AutoreleaseRV ||
Class == IC_RetainBlock;
}
/// \brief Test if the given class represents instructions which are always safe
/// to mark with the "tail" keyword.
static bool IsAlwaysTail(InstructionClass Class) {
// IC_RetainBlock may be given a stack argument.
return Class == IC_Retain ||
Class == IC_RetainRV ||
Class == IC_AutoreleaseRV;
}
/// \brief Test if the given class represents instructions which are never safe
/// to mark with the "tail" keyword.
static bool IsNeverTail(InstructionClass Class) {
/// It is never safe to tail call objc_autorelease since by tail calling
/// objc_autorelease, we also tail call -[NSObject autorelease] which supports
/// fast autoreleasing causing our object to be potentially reclaimed from the
/// autorelease pool which violates the semantics of __autoreleasing types in
/// ARC.
return Class == IC_Autorelease;
}
/// \brief Test if the given class represents instructions which are always safe
/// to mark with the nounwind attribute.
static bool IsNoThrow(InstructionClass Class) {
// objc_retainBlock is not nounwind because it calls user copy constructors
// which could theoretically throw.
return Class == IC_Retain ||
Class == IC_RetainRV ||
Class == IC_Release ||
Class == IC_Autorelease ||
Class == IC_AutoreleaseRV ||
Class == IC_AutoreleasepoolPush ||
Class == IC_AutoreleasepoolPop;
}
/// \brief Erase the given instruction.
///
/// Many ObjC calls return their argument verbatim,
@ -354,46 +284,6 @@ static void EraseInstruction(Instruction *CI) {
RecursivelyDeleteTriviallyDeadInstructions(OldArg);
}
/// \brief This is a wrapper around getUnderlyingObject which also knows how to
/// look through objc_retain and objc_autorelease calls, which we know to return
/// their argument verbatim.
static const Value *GetUnderlyingObjCPtr(const Value *V) {
for (;;) {
V = GetUnderlyingObject(V);
if (!IsForwarding(GetBasicInstructionClass(V)))
break;
V = cast<CallInst>(V)->getArgOperand(0);
}
return V;
}
/// \brief This is a wrapper around Value::stripPointerCasts which also knows
/// how to look through objc_retain and objc_autorelease calls, which we know to
/// return their argument verbatim.
static const Value *StripPointerCastsAndObjCCalls(const Value *V) {
for (;;) {
V = V->stripPointerCasts();
if (!IsForwarding(GetBasicInstructionClass(V)))
break;
V = cast<CallInst>(V)->getArgOperand(0);
}
return V;
}
/// \brief This is a wrapper around Value::stripPointerCasts which also knows
/// how to look through objc_retain and objc_autorelease calls, which we know to
/// return their argument verbatim.
static Value *StripPointerCastsAndObjCCalls(Value *V) {
for (;;) {
V = V->stripPointerCasts();
if (!IsForwarding(GetBasicInstructionClass(V)))
break;
V = cast<CallInst>(V)->getArgOperand(0);
}
return V;
}
/// \brief Assuming the given instruction is one of the special calls such as
/// objc_retain or objc_release, return the argument value, stripped of no-op
/// casts and forwarding calls.
@ -551,177 +441,6 @@ static bool DoesObjCBlockEscape(const Value *BlockPtr) {
return false;
}
/// @}
///
/// \defgroup ARCAA Extends alias analysis using ObjC specific knowledge.
/// @{
namespace {
/// \brief This is a simple alias analysis implementation that uses knowledge
/// of ARC constructs to answer queries.
///
/// TODO: This class could be generalized to know about other ObjC-specific
/// tricks. Such as knowing that ivars in the non-fragile ABI are non-aliasing
/// even though their offsets are dynamic.
class ObjCARCAliasAnalysis : public ImmutablePass,
public AliasAnalysis {
public:
static char ID; // Class identification, replacement for typeinfo
ObjCARCAliasAnalysis() : ImmutablePass(ID) {
initializeObjCARCAliasAnalysisPass(*PassRegistry::getPassRegistry());
}
private:
virtual void initializePass() {
InitializeAliasAnalysis(this);
}
/// This method is used when a pass implements an analysis interface through
/// multiple inheritance. If needed, it should override this to adjust the
/// this pointer as needed for the specified pass info.
virtual void *getAdjustedAnalysisPointer(const void *PI) {
if (PI == &AliasAnalysis::ID)
return static_cast<AliasAnalysis *>(this);
return this;
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual AliasResult alias(const Location &LocA, const Location &LocB);
virtual bool pointsToConstantMemory(const Location &Loc, bool OrLocal);
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS);
virtual ModRefBehavior getModRefBehavior(const Function *F);
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
const Location &Loc);
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2);
};
} // End of anonymous namespace
// Register this pass...
char ObjCARCAliasAnalysis::ID = 0;
INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa",
"ObjC-ARC-Based Alias Analysis", false, true, false)
ImmutablePass *llvm::createObjCARCAliasAnalysisPass() {
return new ObjCARCAliasAnalysis();
}
void
ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AliasAnalysis::getAnalysisUsage(AU);
}
AliasAnalysis::AliasResult
ObjCARCAliasAnalysis::alias(const Location &LocA, const Location &LocB) {
if (!EnableARCOpts)
return AliasAnalysis::alias(LocA, LocB);
// First, strip off no-ops, including ObjC-specific no-ops, and try making a
// precise alias query.
const Value *SA = StripPointerCastsAndObjCCalls(LocA.Ptr);
const Value *SB = StripPointerCastsAndObjCCalls(LocB.Ptr);
AliasResult Result =
AliasAnalysis::alias(Location(SA, LocA.Size, LocA.TBAATag),
Location(SB, LocB.Size, LocB.TBAATag));
if (Result != MayAlias)
return Result;
// If that failed, climb to the underlying object, including climbing through
// ObjC-specific no-ops, and try making an imprecise alias query.
const Value *UA = GetUnderlyingObjCPtr(SA);
const Value *UB = GetUnderlyingObjCPtr(SB);
if (UA != SA || UB != SB) {
Result = AliasAnalysis::alias(Location(UA), Location(UB));
// We can't use MustAlias or PartialAlias results here because
// GetUnderlyingObjCPtr may return an offsetted pointer value.
if (Result == NoAlias)
return NoAlias;
}
// If that failed, fail. We don't need to chain here, since that's covered
// by the earlier precise query.
return MayAlias;
}
bool
ObjCARCAliasAnalysis::pointsToConstantMemory(const Location &Loc,
bool OrLocal) {
if (!EnableARCOpts)
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
// First, strip off no-ops, including ObjC-specific no-ops, and try making
// a precise alias query.
const Value *S = StripPointerCastsAndObjCCalls(Loc.Ptr);
if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.TBAATag),
OrLocal))
return true;
// If that failed, climb to the underlying object, including climbing through
// ObjC-specific no-ops, and try making an imprecise alias query.
const Value *U = GetUnderlyingObjCPtr(S);
if (U != S)
return AliasAnalysis::pointsToConstantMemory(Location(U), OrLocal);
// If that failed, fail. We don't need to chain here, since that's covered
// by the earlier precise query.
return false;
}
AliasAnalysis::ModRefBehavior
ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
// We have nothing to do. Just chain to the next AliasAnalysis.
return AliasAnalysis::getModRefBehavior(CS);
}
AliasAnalysis::ModRefBehavior
ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) {
if (!EnableARCOpts)
return AliasAnalysis::getModRefBehavior(F);
switch (GetFunctionClass(F)) {
case IC_NoopCast:
return DoesNotAccessMemory;
default:
break;
}
return AliasAnalysis::getModRefBehavior(F);
}
AliasAnalysis::ModRefResult
ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) {
if (!EnableARCOpts)
return AliasAnalysis::getModRefInfo(CS, Loc);
switch (GetBasicInstructionClass(CS.getInstruction())) {
case IC_Retain:
case IC_RetainRV:
case IC_Autorelease:
case IC_AutoreleaseRV:
case IC_NoopCast:
case IC_AutoreleasepoolPush:
case IC_FusedRetainAutorelease:
case IC_FusedRetainAutoreleaseRV:
// These functions don't access any memory visible to the compiler.
// Note that this doesn't include objc_retainBlock, because it updates
// pointers when it copies block data.
return NoModRef;
default:
break;
}
return AliasAnalysis::getModRefInfo(CS, Loc);
}
AliasAnalysis::ModRefResult
ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) {
// TODO: Theoretically we could check for dependencies between objc_* calls
// and OnlyAccessesArgumentPointees calls or other well-behaved calls.
return AliasAnalysis::getModRefInfo(CS1, CS2);
}
/// @}
///
/// \defgroup ARCOpt ARC Optimization.