mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-23 11:04:49 +00:00
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318477 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8fafa16869
commit
6d3e69e814
@ -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 {
|
||||
|
26
test/Transforms/LowerTypeTests/blockaddress-2.ll
Normal file
26
test/Transforms/LowerTypeTests/blockaddress-2.ll
Normal file
@ -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 = !{}
|
Loading…
x
Reference in New Issue
Block a user