Changeset View
Changeset View
Standalone View
Standalone View
lib/Analysis/BasicAliasAnalysis.cpp
Show First 20 Lines • Show All 482 Lines • ▼ Show 20 Lines | if (!Visited.insert(V).second) { | ||||
Visited.clear(); | Visited.clear(); | ||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal); | return AAResultBase::pointsToConstantMemory(Loc, OrLocal); | ||||
} | } | ||||
// An alloca instruction defines local memory. | // An alloca instruction defines local memory. | ||||
if (OrLocal && isa<AllocaInst>(V)) | if (OrLocal && isa<AllocaInst>(V)) | ||||
continue; | continue; | ||||
if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) | |||||
if (InvInfo.GetStartInstruction(AI)) continue; | |||||
// A global constant counts as local memory for our purposes. | // A global constant counts as local memory for our purposes. | ||||
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { | if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { | ||||
// Note: this doesn't require GV to be "ODR" because it isn't legal for a | // Note: this doesn't require GV to be "ODR" because it isn't legal for a | ||||
// global to be marked constant in some modules and non-constant in | // global to be marked constant in some modules and non-constant in | ||||
// others. GV may even be a declaration, not a definition. | // others. GV may even be a declaration, not a definition. | ||||
if (!GV->isConstant()) { | if (!GV->isConstant() && !InvInfo.GetStartInstruction(GV)) { | ||||
nlewycky: This seems like a really bad interface. The Pass which sets up the InvInfo has to decide… | |||||
Visited.clear(); | Visited.clear(); | ||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal); | return AAResultBase::pointsToConstantMemory(Loc, OrLocal); | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
// If both select values point to local memory, then so does the select. | // If both select values point to local memory, then so does the select. | ||||
if (const SelectInst *SI = dyn_cast<SelectInst>(V)) { | if (const SelectInst *SI = dyn_cast<SelectInst>(V)) { | ||||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | AliasResult BasicAAResult::alias(const MemoryLocation &LocA, | ||||
// shrink_and_clear so it quickly returns to the inline capacity of the | // shrink_and_clear so it quickly returns to the inline capacity of the | ||||
// SmallDenseMap if it ever grows larger. | // SmallDenseMap if it ever grows larger. | ||||
// FIXME: This should really be shrink_to_inline_capacity_and_clear(). | // FIXME: This should really be shrink_to_inline_capacity_and_clear(). | ||||
AliasCache.shrink_and_clear(); | AliasCache.shrink_and_clear(); | ||||
VisitedPhiBBs.clear(); | VisitedPhiBBs.clear(); | ||||
return Alias; | return Alias; | ||||
} | } | ||||
static bool isInvariantIntrinsic(ImmutableCallSite CS) { | |||||
const IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction()); | |||||
return II && (II->getIntrinsicID() == Intrinsic::invariant_start || | |||||
II->getIntrinsicID() == Intrinsic::invariant_end); | |||||
} | |||||
/// Checks to see if the specified callsite can clobber the specified memory | /// Checks to see if the specified callsite can clobber the specified memory | ||||
/// object. | /// object. | ||||
/// | /// | ||||
/// Since we only look at local properties of this function, we really can't | /// Since we only look at local properties of this function, we really can't | ||||
/// say much about this query. We do, however, use simple "address taken" | /// say much about this query. We do, however, use simple "address taken" | ||||
/// analysis on local objects. | /// analysis on local objects. | ||||
ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS, | ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS, | ||||
const MemoryLocation &Loc) { | const MemoryLocation &Loc) { | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS, | ||||
} | } | ||||
// While the assume intrinsic is marked as arbitrarily writing so that | // While the assume intrinsic is marked as arbitrarily writing so that | ||||
// proper control dependencies will be maintained, it never aliases any | // proper control dependencies will be maintained, it never aliases any | ||||
// particular memory location. | // particular memory location. | ||||
if (isAssumeIntrinsic(CS)) | if (isAssumeIntrinsic(CS)) | ||||
return MRI_NoModRef; | return MRI_NoModRef; | ||||
// Invariant intrinsics follow the same pattern as assume intrinsic. | |||||
if (isInvariantIntrinsic(CS)) return MRI_NoModRef; | |||||
// The AAResultBase base class has some smarts, lets use them. | // The AAResultBase base class has some smarts, lets use them. | ||||
return AAResultBase::getModRefInfo(CS, Loc); | return AAResultBase::getModRefInfo(CS, Loc); | ||||
} | } | ||||
ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS1, | ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS1, | ||||
ImmutableCallSite CS2) { | ImmutableCallSite CS2) { | ||||
// While the assume intrinsic is marked as arbitrarily writing so that | // While the assume intrinsic is marked as arbitrarily writing so that | ||||
// proper control dependencies will be maintained, it never aliases any | // proper control dependencies will be maintained, it never aliases any | ||||
// particular memory location. | // particular memory location. | ||||
if (isAssumeIntrinsic(CS1) || isAssumeIntrinsic(CS2)) | if (isAssumeIntrinsic(CS1) || isAssumeIntrinsic(CS2)) | ||||
return MRI_NoModRef; | return MRI_NoModRef; | ||||
// Invariant intrinsics follow the same pattern as assume intrinsic. | |||||
if (isInvariantIntrinsic(CS1) || isInvariantIntrinsic(CS2)) | |||||
return MRI_NoModRef; | |||||
// The AAResultBase base class has some smarts, lets use them. | // The AAResultBase base class has some smarts, lets use them. | ||||
return AAResultBase::getModRefInfo(CS1, CS2); | return AAResultBase::getModRefInfo(CS1, CS2); | ||||
} | } | ||||
/// Provide ad-hoc rules to disambiguate accesses through two GEP operators, | /// Provide ad-hoc rules to disambiguate accesses through two GEP operators, | ||||
/// both having the exact same pointer operand. | /// both having the exact same pointer operand. | ||||
static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1, | static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1, | ||||
uint64_t V1Size, | uint64_t V1Size, | ||||
▲ Show 20 Lines • Show All 769 Lines • ▼ Show 20 Lines | |||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
char BasicAA::PassID; | char BasicAA::PassID; | ||||
BasicAAResult BasicAA::run(Function &F, AnalysisManager<Function> *AM) { | BasicAAResult BasicAA::run(Function &F, AnalysisManager<Function> *AM) { | ||||
return BasicAAResult(F.getParent()->getDataLayout(), | return BasicAAResult(F.getParent()->getDataLayout(), | ||||
AM->getResult<TargetLibraryAnalysis>(F), | AM->getResult<TargetLibraryAnalysis>(F), | ||||
AM->getResult<AssumptionAnalysis>(F), | AM->getResult<AssumptionAnalysis>(F), | ||||
F.getParent()->getInvariantInfo(), | |||||
AM->getCachedResult<DominatorTreeAnalysis>(F), | AM->getCachedResult<DominatorTreeAnalysis>(F), | ||||
AM->getCachedResult<LoopAnalysis>(F)); | AM->getCachedResult<LoopAnalysis>(F)); | ||||
} | } | ||||
char BasicAAWrapperPass::ID = 0; | char BasicAAWrapperPass::ID = 0; | ||||
void BasicAAWrapperPass::anchor() {} | void BasicAAWrapperPass::anchor() {} | ||||
INITIALIZE_PASS_BEGIN(BasicAAWrapperPass, "basicaa", | INITIALIZE_PASS_BEGIN(BasicAAWrapperPass, "basicaa", | ||||
Show All 10 Lines | |||||
bool BasicAAWrapperPass::runOnFunction(Function &F) { | bool BasicAAWrapperPass::runOnFunction(Function &F) { | ||||
auto &ACT = getAnalysis<AssumptionCacheTracker>(); | auto &ACT = getAnalysis<AssumptionCacheTracker>(); | ||||
auto &TLIWP = getAnalysis<TargetLibraryInfoWrapperPass>(); | auto &TLIWP = getAnalysis<TargetLibraryInfoWrapperPass>(); | ||||
auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>(); | auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>(); | ||||
auto *LIWP = getAnalysisIfAvailable<LoopInfoWrapperPass>(); | auto *LIWP = getAnalysisIfAvailable<LoopInfoWrapperPass>(); | ||||
Result.reset(new BasicAAResult(F.getParent()->getDataLayout(), TLIWP.getTLI(), | Result.reset(new BasicAAResult(F.getParent()->getDataLayout(), TLIWP.getTLI(), | ||||
ACT.getAssumptionCache(F), | ACT.getAssumptionCache(F), | ||||
F.getParent()->getInvariantInfo(), | |||||
DTWP ? &DTWP->getDomTree() : nullptr, | DTWP ? &DTWP->getDomTree() : nullptr, | ||||
LIWP ? &LIWP->getLoopInfo() : nullptr)); | LIWP ? &LIWP->getLoopInfo() : nullptr)); | ||||
return false; | return false; | ||||
} | } | ||||
void BasicAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { | void BasicAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { | ||||
AU.setPreservesAll(); | AU.setPreservesAll(); | ||||
AU.addRequired<AssumptionCacheTracker>(); | AU.addRequired<AssumptionCacheTracker>(); | ||||
AU.addRequired<TargetLibraryInfoWrapperPass>(); | AU.addRequired<TargetLibraryInfoWrapperPass>(); | ||||
} | } | ||||
BasicAAResult llvm::createLegacyPMBasicAAResult(Pass &P, Function &F) { | BasicAAResult llvm::createLegacyPMBasicAAResult(Pass &P, Function &F) { | ||||
return BasicAAResult( | return BasicAAResult( | ||||
F.getParent()->getDataLayout(), | F.getParent()->getDataLayout(), | ||||
P.getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(), | P.getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(), | ||||
P.getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F)); | P.getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F), | ||||
F.getParent()->getInvariantInfo()); | |||||
} | } |
This seems like a really bad interface. The Pass which sets up the InvInfo has to decide whether to add or not add an invariant intrinsic based on which instruction the caller of pointsToConstantMemory is going to be reasoning about. pointsToConstantMemory could be called by a utility used by the pass, and referring to a point in the program before (or after) the call to invariant.start/end.