Current implementation of Value::replaceUsesExceptBlockAddr() uses UseList
iterator to walk the list which keeps changing inside the loop. When the
UseList contains several uses with the same user, we end processing the same
user more than once, which leads to an assert.
With this fix, unique users are saved and processed later to avoid
processing duplicates.
Differential Revision: https://reviews.llvm.org/D39864
llvm-svn: 318477
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index bfd3911..50235d8 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -15,6 +15,7 @@
#include "LLVMContextImpl.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
@@ -456,6 +457,7 @@
}
void Value::replaceUsesExceptBlockAddr(Value *New) {
+ SmallSetVector<Constant *, 4> Constants;
use_iterator UI = use_begin(), E = use_end();
for (; UI != E;) {
Use &U = *UI;
@@ -468,13 +470,19 @@
// constant because they are uniqued.
if (auto *C = dyn_cast<Constant>(U.getUser())) {
if (!isa<GlobalValue>(C)) {
- C->handleOperandChange(this, New);
+ // Save unique users to avoid processing operand replacement
+ // more than once.
+ Constants.insert(C);
continue;
}
}
U.set(New);
}
+
+ // Process operand replacement of saved constants.
+ for (auto *C : Constants)
+ C->handleOperandChange(this, New);
}
namespace {