[LoopSink] Make the enforcement of determinism deterministic.
authorBenjamin Kramer <benny.kra@googlemail.com>
Fri, 6 Jul 2018 14:20:58 +0000 (14:20 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Fri, 6 Jul 2018 14:20:58 +0000 (14:20 +0000)
LoopBlockNumber is a DenseMap<BasicBlock*, int>, comparing the result of
find() will compare a pair<BasicBlock*, int>. That's of course depending
on pointer ordering which varies from run to run. Reverse iteration
doesn't find this because we're copying to a vector first.

This bug has been there since 2016 but only recently showed up on clang
selfhost with FDO and ThinLTO, which is also why I didn't manage to get
a reasonable test case for this. Add an assert that would've caught
this.

llvm-svn: 336439

llvm/lib/Transforms/Scalar/LoopSink.cpp

index 3cc53ea..760177c 100644 (file)
@@ -202,15 +202,17 @@ static bool sinkInstruction(Loop &L, Instruction &I,
                              BBsToSinkInto.end());
   llvm::sort(SortedBBsToSinkInto.begin(), SortedBBsToSinkInto.end(),
              [&](BasicBlock *A, BasicBlock *B) {
-               return *LoopBlockNumber.find(A) < *LoopBlockNumber.find(B);
+               return LoopBlockNumber.find(A)->second <
+                      LoopBlockNumber.find(B)->second;
              });
 
   BasicBlock *MoveBB = *SortedBBsToSinkInto.begin();
   // FIXME: Optimize the efficiency for cloned value replacement. The current
   //        implementation is O(SortedBBsToSinkInto.size() * I.num_uses()).
-  for (BasicBlock *N : SortedBBsToSinkInto) {
-    if (N == MoveBB)
-      continue;
+  for (BasicBlock *N : makeArrayRef(SortedBBsToSinkInto).drop_front(1)) {
+    assert(LoopBlockNumber.find(N)->second >
+               LoopBlockNumber.find(MoveBB)->second &&
+           "BBs not sorted!");
     // Clone I and replace its uses.
     Instruction *IC = I.clone();
     IC->setName(I.getName());