[Constant Hoisting] Don't update the use list while traversing it - DOH!
authorJuergen Ributzka <juergen@apple.com>
Sat, 8 Feb 2014 00:20:45 +0000 (00:20 +0000)
committerJuergen Ributzka <juergen@apple.com>
Sat, 8 Feb 2014 00:20:45 +0000 (00:20 +0000)
This fix first traverses the whole use list of the constant expression and
keeps track of the instructions that need to be updated. Then perform the
fixup afterwards.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201008 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/ConstantHoisting.cpp

index c4cf85f95267656e587e3c141f18eeafc322b464..28a31a970252493e921b43ab2e2a2f94191d95c8 100644 (file)
@@ -350,14 +350,19 @@ void ConstantHoisting::EmitBaseConstants(Function &F, User *U,
   }
   assert(isa<ConstantExpr>(U) && "Expected a ConstantExpr.");
   ConstantExpr *CE = cast<ConstantExpr>(U);
+  SmallVector<std::pair<Instruction *, Instruction *>, 8> WorkList;
+  DEBUG(dbgs() << "Visit ConstantExpr " << *CE << '\n');
   for (Value::use_iterator UU = CE->use_begin(), E = CE->use_end();
        UU != E; ++UU) {
+    DEBUG(dbgs() << "Check user "; UU->print(dbgs()); dbgs() << '\n');
     // We only handel instructions here and won't walk down a ConstantExpr chain
     // to replace all ConstExpr with instructions.
     if (Instruction *I = dyn_cast<Instruction>(*UU)) {
       // Only update constant expressions in the current function.
-      if (I->getParent()->getParent() != &F)
+      if (I->getParent()->getParent() != &F) {
+        DEBUG(dbgs() << "Not in the same function - skip.\n");
         continue;
+      }
 
       Instruction *Mat = Base;
       Instruction *InsertBefore = getMatInsertPt(I, DT);
@@ -380,12 +385,18 @@ void ConstantHoisting::EmitBaseConstants(Function &F, User *U,
       // Use the same debug location as the instruction we are about to update.
       ICE->setDebugLoc(I->getDebugLoc());
 
-      DEBUG(dbgs() << "Create instruction: " << *ICE << '\n');
-      DEBUG(dbgs() << "Update: " << *I << '\n');
-      I->replaceUsesOfWith(CE, ICE);
-      DEBUG(dbgs() << "To: " << *I << '\n');
+      WorkList.push_back(std::make_pair(I, ICE));
+    } else {
+      DEBUG(dbgs() << "Not an instruction - skip.\n");
     }
   }
+  SmallVectorImpl<std::pair<Instruction *, Instruction *> >::iterator I, E;
+  for (I = WorkList.begin(), E = WorkList.end(); I != E; ++I) {
+    DEBUG(dbgs() << "Create instruction: " << *I->second << '\n');
+    DEBUG(dbgs() << "Update: " << *I->first << '\n');
+    I->first->replaceUsesOfWith(CE, I->second);
+    DEBUG(dbgs() << "To: " << *I->first << '\n');
+  }
 }
 
 /// \brief Hoist and hide the base constant behind a bitcast and emit