GVN: Fix non-determinism in map iteration.

Iterating over a DenseMaop is non-deterministic and results to unpredictable IR
output.

Based on a patch by Daniel Reynaud!

llvm-svn: 208728
This commit is contained in:
Benjamin Kramer 2014-05-13 21:06:40 +00:00
parent d97f95e2f2
commit 3f085ba6d6
1 changed files with 7 additions and 4 deletions

View File

@ -19,6 +19,7 @@
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/Hashing.h" #include "llvm/ADT/Hashing.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
@ -1539,7 +1540,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
// Check to see how many predecessors have the loaded value fully // Check to see how many predecessors have the loaded value fully
// available. // available.
DenseMap<BasicBlock*, Value*> PredLoads; MapVector<BasicBlock *, Value *> PredLoads;
DenseMap<BasicBlock*, char> FullyAvailableBlocks; DenseMap<BasicBlock*, char> FullyAvailableBlocks;
for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i) for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i)
FullyAvailableBlocks[ValuesPerBlock[i].BB] = true; FullyAvailableBlocks[ValuesPerBlock[i].BB] = true;
@ -1553,7 +1554,6 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
if (IsValueFullyAvailableInBlock(Pred, FullyAvailableBlocks, 0)) { if (IsValueFullyAvailableInBlock(Pred, FullyAvailableBlocks, 0)) {
continue; continue;
} }
PredLoads[Pred] = nullptr;
if (Pred->getTerminator()->getNumSuccessors() != 1) { if (Pred->getTerminator()->getNumSuccessors() != 1) {
if (isa<IndirectBrInst>(Pred->getTerminator())) { if (isa<IndirectBrInst>(Pred->getTerminator())) {
@ -1570,11 +1570,14 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
} }
CriticalEdgePred.push_back(Pred); CriticalEdgePred.push_back(Pred);
} else {
// Only add the predecessors that will not be split for now.
PredLoads[Pred] = nullptr;
} }
} }
// Decide whether PRE is profitable for this load. // Decide whether PRE is profitable for this load.
unsigned NumUnavailablePreds = PredLoads.size(); unsigned NumUnavailablePreds = PredLoads.size() + CriticalEdgePred.size();
assert(NumUnavailablePreds != 0 && assert(NumUnavailablePreds != 0 &&
"Fully available value should already be eliminated!"); "Fully available value should already be eliminated!");
@ -1588,7 +1591,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
// Split critical edges, and update the unavailable predecessors accordingly. // Split critical edges, and update the unavailable predecessors accordingly.
for (BasicBlock *OrigPred : CriticalEdgePred) { for (BasicBlock *OrigPred : CriticalEdgePred) {
BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB); BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB);
PredLoads.erase(OrigPred); assert(!PredLoads.count(OrigPred) && "Split edges shouldn't be in map!");
PredLoads[NewPred] = nullptr; PredLoads[NewPred] = nullptr;
DEBUG(dbgs() << "Split critical edge " << OrigPred->getName() << "->" DEBUG(dbgs() << "Split critical edge " << OrigPred->getName() << "->"
<< LoadBB->getName() << '\n'); << LoadBB->getName() << '\n');