[PATCH] fix non-determinism issue in SLP

Daniel Reynaud dreynaud at apple.com
Mon Jan 5 15:31:13 PST 2015


The issue was introduced in r214638:

+  for (auto &BSIter : BlocksSchedules) {
+    scheduleBlock(BSIter.second.get());
+  }

Because BlocksSchedules is a DenseMap with BasicBlock* keys, blocks are scheduled in non-deterministic order, resulting in unpredictable IR.
The following patch fixes the issue with the cost of an extra SetVector:

diff --git a/lib/Transforms/Vectorize/SLPVectorizer.cpp b/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 912e580..e04ea17 100644
--- a/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -382,8 +382,7 @@ public:
     ExternalUses.clear();
     NumLoadsWantToKeepOrder = 0;
     NumLoadsWantToChangeOrder = 0;
-    for (auto &Iter : BlocksSchedules) {
-      BlockScheduling *BS = Iter.second.get();
+    for (auto BS : BlocksSchedulesSV) {
       BS->clear();
     }
   }
@@ -807,6 +806,7 @@ private:
 
   /// Attaches the BlockScheduling structures to basic blocks.
   DenseMap<BasicBlock *, std::unique_ptr<BlockScheduling>> BlocksSchedules;
+  SetVector<BlockScheduling*> BlocksSchedulesSV;
 
   /// Performs the "real" scheduling. Done before vectorization is actually
   /// performed in a basic block.
@@ -996,6 +996,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth) {
   auto &BSRef = BlocksSchedules[BB];
   if (!BSRef) {
     BSRef = llvm::make_unique<BlockScheduling>(BB);
+    BlocksSchedulesSV.insert(BSRef.get());
   }
   BlockScheduling &BS = *BSRef.get();
 
@@ -2163,8 +2164,8 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
 Value *BoUpSLP::vectorizeTree() {
   
   // All blocks must be scheduled before any instructions are inserted.
-  for (auto &BSIter : BlocksSchedules) {
-    scheduleBlock(BSIter.second.get());
+  for (auto &BSIter : BlocksSchedulesSV) {
+    scheduleBlock(BSIter);
   }
 
   Builder.SetInsertPoint(F->getEntryBlock().begin());





More information about the llvm-commits mailing list