Skip to content

Commit

Permalink
[MemDepAnalysis] Allow caller to pass in an OrderedBasicBlock.
Browse files Browse the repository at this point in the history
If the caller can preserve the OBB, we can avoid recomputing the order
for each getDependency call.

Reviewers: efriedma, rnk, hfinkel

Reviewed By: rnk

Differential Revision: https://reviews.llvm.org/D59788

llvm-svn: 357206
  • Loading branch information
fhahn committed Mar 28, 2019
1 parent 471171c commit 6c30243
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 23 deletions.
19 changes: 10 additions & 9 deletions llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
Expand Up @@ -381,7 +381,8 @@ class MemoryDependenceResults {
///
/// See the class comment for more details. It is illegal to call this on
/// non-memory instructions.
MemDepResult getDependency(Instruction *QueryInst);
MemDepResult getDependency(Instruction *QueryInst,
OrderedBasicBlock *OBB = nullptr);

/// Perform a full dependency query for the specified call, returning the set
/// of blocks that the value is potentially live across.
Expand Down Expand Up @@ -447,14 +448,14 @@ class MemoryDependenceResults {
BasicBlock::iterator ScanIt,
BasicBlock *BB,
Instruction *QueryInst = nullptr,
unsigned *Limit = nullptr);

MemDepResult getSimplePointerDependencyFrom(const MemoryLocation &MemLoc,
bool isLoad,
BasicBlock::iterator ScanIt,
BasicBlock *BB,
Instruction *QueryInst,
unsigned *Limit = nullptr);
unsigned *Limit = nullptr,
OrderedBasicBlock *OBB = nullptr);

MemDepResult
getSimplePointerDependencyFrom(const MemoryLocation &MemLoc, bool isLoad,
BasicBlock::iterator ScanIt, BasicBlock *BB,
Instruction *QueryInst, unsigned *Limit,
OrderedBasicBlock *OBB);

/// This analysis looks for other loads and stores with invariant.group
/// metadata and the same pointer operand. Returns Unknown if it does not
Expand Down
33 changes: 19 additions & 14 deletions llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
Expand Up @@ -326,7 +326,8 @@ static bool isVolatile(Instruction *Inst) {

MemDepResult MemoryDependenceResults::getPointerDependencyFrom(
const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt,
BasicBlock *BB, Instruction *QueryInst, unsigned *Limit) {
BasicBlock *BB, Instruction *QueryInst, unsigned *Limit,
OrderedBasicBlock *OBB) {
MemDepResult InvariantGroupDependency = MemDepResult::getUnknown();
if (QueryInst != nullptr) {
if (auto *LI = dyn_cast<LoadInst>(QueryInst)) {
Expand All @@ -337,7 +338,7 @@ MemDepResult MemoryDependenceResults::getPointerDependencyFrom(
}
}
MemDepResult SimpleDep = getSimplePointerDependencyFrom(
MemLoc, isLoad, ScanIt, BB, QueryInst, Limit);
MemLoc, isLoad, ScanIt, BB, QueryInst, Limit, OBB);
if (SimpleDep.isDef())
return SimpleDep;
// Non-local invariant group dependency indicates there is non local Def
Expand Down Expand Up @@ -438,14 +439,13 @@ MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,

MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt,
BasicBlock *BB, Instruction *QueryInst, unsigned *Limit) {
BasicBlock *BB, Instruction *QueryInst, unsigned *Limit,
OrderedBasicBlock *OBB) {
bool isInvariantLoad = false;

if (!Limit) {
unsigned DefaultLimit = BlockScanLimit;
return getSimplePointerDependencyFrom(MemLoc, isLoad, ScanIt, BB, QueryInst,
&DefaultLimit);
}
unsigned DefaultLimit = BlockScanLimit;
if (!Limit)
Limit = &DefaultLimit;

// We must be careful with atomic accesses, as they may allow another thread
// to touch this location, clobbering it. We are conservative: if the
Expand Down Expand Up @@ -487,11 +487,14 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(

const DataLayout &DL = BB->getModule()->getDataLayout();

// Create a numbered basic block to lazily compute and cache instruction
// If the caller did not provide an ordered basic block,
// create one to lazily compute and cache instruction
// positions inside a BB. This is used to provide fast queries for relative
// position between two instructions in a BB and can be used by
// AliasAnalysis::callCapturesBefore.
OrderedBasicBlock OBB(BB);
OrderedBasicBlock OBBTmp(BB);
if (!OBB)
OBB = &OBBTmp;

// Return "true" if and only if the instruction I is either a non-simple
// load or a non-simple store.
Expand Down Expand Up @@ -682,7 +685,7 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
ModRefInfo MR = AA.getModRefInfo(Inst, MemLoc);
// If necessary, perform additional analysis.
if (isModAndRefSet(MR))
MR = AA.callCapturesBefore(Inst, MemLoc, &DT, &OBB);
MR = AA.callCapturesBefore(Inst, MemLoc, &DT, OBB);
switch (clearMust(MR)) {
case ModRefInfo::NoModRef:
// If the call has no effect on the queried pointer, just ignore it.
Expand All @@ -708,7 +711,8 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
return MemDepResult::getNonFuncLocal();
}

MemDepResult MemoryDependenceResults::getDependency(Instruction *QueryInst) {
MemDepResult MemoryDependenceResults::getDependency(Instruction *QueryInst,
OrderedBasicBlock *OBB) {
Instruction *ScanPos = QueryInst;

// Check for a cached result
Expand Down Expand Up @@ -746,8 +750,9 @@ MemDepResult MemoryDependenceResults::getDependency(Instruction *QueryInst) {
if (auto *II = dyn_cast<IntrinsicInst>(QueryInst))
isLoad |= II->getIntrinsicID() == Intrinsic::lifetime_start;

LocalCache = getPointerDependencyFrom(
MemLoc, isLoad, ScanPos->getIterator(), QueryParent, QueryInst);
LocalCache =
getPointerDependencyFrom(MemLoc, isLoad, ScanPos->getIterator(),
QueryParent, QueryInst, nullptr, OBB);
} else if (auto *QueryCall = dyn_cast<CallBase>(QueryInst)) {
bool isReadOnly = AA.onlyReadsMemory(QueryCall);
LocalCache = getCallDependencyFrom(QueryCall, isReadOnly,
Expand Down

0 comments on commit 6c30243

Please sign in to comment.