Just avoid crashing for now, we should be able to replace the blockaddresses themselves. BlockAddress::handleOperandChangeImpl assumes it can cast to Function. The verifier seems nonexistent and the langref isn't particularly explicit on what's allowed as a blockaddress operand. As far as I can tell bugpoint isn't doing anything to handle this. Something low level is broken with BlockAddress handling, demonstrated by reduce-functions-blockaddress-wrong-function.ll. The BasicBlock destructor of the deleted function is triggering replacement of blockaddresses for the kept function in some cases. I've only half debugged this but it seems like blockaddress is handled too-specially compared to other Constants. I have tentative patches to allow any constant to be a blockaddress input, but having the verifier check if it's really a function/block. https://reviews.llvm.org/D140909
39 lines
1.1 KiB
LLVM
39 lines
1.1 KiB
LLVM
; RUN: llvm-reduce --delta-passes=functions --test FileCheck --test-arg --check-prefixes=INTERESTING --test-arg %s --test-arg --input-file %s -o %t
|
|
; RUN: FileCheck --check-prefixes=RESULT --input-file=%t %s
|
|
|
|
; FIXME: This testcase exhibits nonsensical behavior. The first
|
|
; function has blockaddress references. When the second function is
|
|
; deleted, it causes the blockreferences from the first to be replaced
|
|
; with inttoptr.
|
|
|
|
; INTERESTING: @blockaddr.table.other
|
|
|
|
; RESULT: @blockaddr.table.other = private unnamed_addr constant [2 x ptr] [ptr inttoptr (i32 1 to ptr), ptr inttoptr (i32 1 to ptr)]
|
|
|
|
@blockaddr.table.other = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@bar, %L1), ptr blockaddress(@bar, %L2)]
|
|
|
|
|
|
; RESULT: define i32 @bar(
|
|
define i32 @bar(i64 %arg0) {
|
|
entry:
|
|
%gep = getelementptr inbounds [2 x ptr], ptr @blockaddr.table.other, i64 0, i64 %arg0
|
|
%load = load ptr, ptr %gep, align 8
|
|
indirectbr ptr %load, [label %L2, label %L1]
|
|
|
|
L1:
|
|
%phi = phi i32 [ 1, %L2 ], [ 2, %entry ]
|
|
ret i32 %phi
|
|
|
|
L2:
|
|
br label %L1
|
|
}
|
|
|
|
; RESULT-NOT: @unused
|
|
define void @unused() {
|
|
entry:
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|