diff options
-rw-r--r-- | llvm/lib/IR/Value.cpp | 10 | ||||
-rw-r--r-- | llvm/test/Transforms/LowerTypeTests/blockaddress-2.ll | 26 |
2 files changed, 35 insertions, 1 deletions
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index bfd39114b3f..50235d8d30f 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::replaceUsesOutsideBlock(Value *New, BasicBlock *BB) { } 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 @@ void Value::replaceUsesExceptBlockAddr(Value *New) { // 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 { diff --git a/llvm/test/Transforms/LowerTypeTests/blockaddress-2.ll b/llvm/test/Transforms/LowerTypeTests/blockaddress-2.ll new file mode 100644 index 00000000000..b39a7bc3532 --- /dev/null +++ b/llvm/test/Transforms/LowerTypeTests/blockaddress-2.ll @@ -0,0 +1,26 @@ +; RUN: opt -S %s -lowertypetests | FileCheck %s + +; CHECK: @badfileops = internal global %struct.f { void ()* @bad_f, void ()* @bad_f } +; CHECK: @bad_f = internal alias void (), void ()* @.cfi.jumptable +; CHECK: define internal void @bad_f.cfi() !type !0 { +; CHECK-NEXT: ret void + +target triple = "x86_64-unknown-linux" + +%struct.f = type { void ()*, void ()* } +@badfileops = internal global %struct.f { void ()* @bad_f, void ()* @bad_f }, align 8 + +declare i1 @llvm.type.test(i8*, metadata) + +define internal void @bad_f() !type !1 { + ret void +} + +define internal fastcc void @do_f() unnamed_addr !type !2 { + %1 = tail call i1 @llvm.type.test(i8* undef, metadata !"_ZTSFiP4fileP3uioP5ucrediP6threadE"), !nosanitize !3 + ret void +} + +!1 = !{i64 0, !"_ZTSFiP4fileP3uioP5ucrediP6threadE"} +!2 = !{i64 0, !"_ZTSFiP6threadiP4fileP3uioliE"} +!3 = !{} |