ObjCARCAliasAnalysis.cpp [plain text]
#include "llvm/Analysis/ObjCARCAliasAnalysis.h"
#include "llvm/Analysis/ObjCARCAnalysisUtils.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Value.h"
#include "llvm/InitializePasses.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/PassSupport.h"
#define DEBUG_TYPE "objc-arc-aa"
using namespace llvm;
using namespace llvm::objcarc;
AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA,
const MemoryLocation &LocB) {
if (!EnableARCOpts)
return AAResultBase::alias(LocA, LocB);
const Value *SA = GetRCIdentityRoot(LocA.Ptr);
const Value *SB = GetRCIdentityRoot(LocB.Ptr);
AliasResult Result =
AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
MemoryLocation(SB, LocB.Size, LocB.AATags));
if (Result != MayAlias)
return Result;
const Value *UA = GetUnderlyingObjCPtr(SA, DL);
const Value *UB = GetUnderlyingObjCPtr(SB, DL);
if (UA != SA || UB != SB) {
Result = AAResultBase::alias(MemoryLocation(UA), MemoryLocation(UB));
if (Result == NoAlias)
return NoAlias;
}
return MayAlias;
}
bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
bool OrLocal) {
if (!EnableARCOpts)
return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
const Value *S = GetRCIdentityRoot(Loc.Ptr);
if (AAResultBase::pointsToConstantMemory(
MemoryLocation(S, Loc.Size, Loc.AATags), OrLocal))
return true;
const Value *U = GetUnderlyingObjCPtr(S, DL);
if (U != S)
return AAResultBase::pointsToConstantMemory(MemoryLocation(U), OrLocal);
return false;
}
FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) {
if (!EnableARCOpts)
return AAResultBase::getModRefBehavior(F);
switch (GetFunctionClass(F)) {
case ARCInstKind::NoopCast:
return FMRB_DoesNotAccessMemory;
default:
break;
}
return AAResultBase::getModRefBehavior(F);
}
ModRefInfo ObjCARCAAResult::getModRefInfo(ImmutableCallSite CS,
const MemoryLocation &Loc) {
if (!EnableARCOpts)
return AAResultBase::getModRefInfo(CS, Loc);
switch (GetBasicARCInstKind(CS.getInstruction())) {
case ARCInstKind::Retain:
case ARCInstKind::RetainRV:
case ARCInstKind::Autorelease:
case ARCInstKind::AutoreleaseRV:
case ARCInstKind::NoopCast:
case ARCInstKind::AutoreleasepoolPush:
case ARCInstKind::FusedRetainAutorelease:
case ARCInstKind::FusedRetainAutoreleaseRV:
return MRI_NoModRef;
default:
break;
}
return AAResultBase::getModRefInfo(CS, Loc);
}
ObjCARCAAResult ObjCARCAA::run(Function &F, AnalysisManager<Function> *AM) {
return ObjCARCAAResult(F.getParent()->getDataLayout());
}
char ObjCARCAA::PassID;
char ObjCARCAAWrapperPass::ID = 0;
INITIALIZE_PASS(ObjCARCAAWrapperPass, "objc-arc-aa",
"ObjC-ARC-Based Alias Analysis", false, true)
ImmutablePass *llvm::createObjCARCAAWrapperPass() {
return new ObjCARCAAWrapperPass();
}
ObjCARCAAWrapperPass::ObjCARCAAWrapperPass() : ImmutablePass(ID) {
initializeObjCARCAAWrapperPassPass(*PassRegistry::getPassRegistry());
}
bool ObjCARCAAWrapperPass::doInitialization(Module &M) {
Result.reset(new ObjCARCAAResult(M.getDataLayout()));
return false;
}
bool ObjCARCAAWrapperPass::doFinalization(Module &M) {
Result.reset();
return false;
}
void ObjCARCAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}