[DependenceAnalysis] Dependecies for loads marked with "ivnariant.load" 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
This commit is contained in:
Evgeniy Brevnov 2019-11-19 17:26:24 +07:00
parent b6d7bbfa00
commit 5f026b6d9e
1 changed files with 19 additions and 6 deletions

View File

@ -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(
@ -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()) {
@ -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)
@ -1454,7 +1470,6 @@ bool MemoryDependenceResults::getNonLocalPointerDepFromBB(
if (SkipFirstBlock)
return false;
bool foundBlock = false;
for (NonLocalDepEntry &I : llvm::reverse(*Cache)) {
if (I.getBB() != BB)
continue;
@ -1462,14 +1477,12 @@ bool MemoryDependenceResults::getNonLocalPointerDepFromBB(
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.