Skip to content

Commit

Permalink
[DependenceAnalysis] Dependecies for loads marked with "ivnariant.loa…
Browse files Browse the repository at this point in the history
…d" should not be shared with general accesses. Fix for https://bugs.llvm.org/show_bug.cgi?id=42151

Summary:
Dependence anlysis has a mechanism to cache results. Thus for particular memory access the cache keep track of side effects in basic blocks. The problem is that for invariant loads dependepce analysis legally ignores many dependencies due to a special semantic rules for such loads. But later results calculated for invariant load retrived from the cache for general case acceses. As a result we have wrong dependence information causing GVN to do illegal transformation. Fixes, T42151.

Proposed solution is to disable caching of invariant loads. I think such loads a pretty rare and it doesn't make sense to extend caching mechanism for them.

Reviewers: reames, chandlerc, skatkov, morisset, jdoerfert

Reviewed By: reames

Subscribers: hiraditya, test, jdoerfert, lebedev.ri, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D64405
  • Loading branch information
ebrevnov committed Nov 19, 2019
1 parent b6d7bbf commit 5f026b6
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,11 @@ MemDepResult MemoryDependenceResults::GetNonLocalInfoForBlock(
Instruction *QueryInst, const MemoryLocation &Loc, bool isLoad,
BasicBlock *BB, NonLocalDepInfo *Cache, unsigned NumSortedEntries) {

bool isInvariantLoad = false;

if (LoadInst *LI = dyn_cast_or_null<LoadInst>(QueryInst))
isInvariantLoad = LI->getMetadata(LLVMContext::MD_invariant_load);

// Do a binary search to see if we already have an entry for this block in
// the cache set. If so, find it.
NonLocalDepInfo::iterator Entry = std::upper_bound(
Expand All @@ -990,6 +995,13 @@ MemDepResult MemoryDependenceResults::GetNonLocalInfoForBlock(
if (Entry != Cache->begin() + NumSortedEntries && Entry->getBB() == BB)
ExistingResult = &*Entry;

// Use cached result for invariant load only if there is no dependency for non
// invariant load. In this case invariant load can not have any dependency as
// well.
if (ExistingResult && isInvariantLoad &&
!ExistingResult->getResult().isNonFuncLocal())
ExistingResult = nullptr;

// If we have a cached entry, and it is non-dirty, use it as the value for
// this dependency.
if (ExistingResult && !ExistingResult->getResult().isDirty()) {
Expand Down Expand Up @@ -1018,6 +1030,10 @@ MemDepResult MemoryDependenceResults::GetNonLocalInfoForBlock(
MemDepResult Dep =
getPointerDependencyFrom(Loc, isLoad, ScanPos, BB, QueryInst);

// Don't cache results for invariant load.
if (isInvariantLoad)
return Dep;

// If we had a dirty entry for the block, update it. Otherwise, just add
// a new entry.
if (ExistingResult)
Expand Down Expand Up @@ -1454,22 +1470,19 @@ bool MemoryDependenceResults::getNonLocalPointerDepFromBB(
if (SkipFirstBlock)
return false;

bool foundBlock = false;
for (NonLocalDepEntry &I : llvm::reverse(*Cache)) {
if (I.getBB() != BB)
continue;

assert((GotWorklistLimit || I.getResult().isNonLocal() ||
!DT.isReachableFromEntry(BB)) &&
"Should only be here with transparent block");
foundBlock = true;
I.setResult(MemDepResult::getUnknown());
Result.push_back(
NonLocalDepResult(I.getBB(), I.getResult(), Pointer.getAddr()));
break;
}
(void)foundBlock; (void)GotWorklistLimit;
assert((foundBlock || GotWorklistLimit) && "Current block not in cache?");
// Go ahead and report unknown dependence.
Result.push_back(
NonLocalDepResult(BB, MemDepResult::getUnknown(), Pointer.getAddr()));
}

// Okay, we're done now. If we added new values to the cache, re-sort it.
Expand Down

0 comments on commit 5f026b6

Please sign in to comment.