
Currently BlockAddresses store both the Function and the BasicBlock they reference, and the BlockAddress is part of the use list of both the Function and BasicBlock. This is quite awkward, because this is not really a use of the function itself (and walks of function uses generally skip block addresses for that reason). This also has weird implications on function RAUW (as that will replace the function in block addresses in a way that generally doesn't make sense), and causes other peculiar issues, like the ability to have multiple block addresses for one block (with different functions). Instead, I believe it makes more sense to specify only the basic block and let the function be implied by the BB parent. This does mean that we may have block addresses without a function (if the BB is not inserted), but this should only happen during IR construction.
48 lines
1.8 KiB
LLVM
48 lines
1.8 KiB
LLVM
; RUN: llvm-reduce --abort-on-invalid-reduction --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
|
|
|
|
; Make sure we don't crash on blockaddress
|
|
|
|
; INTERESTING: @blockaddr.table
|
|
; INTERESTING: @blockaddr.table.addrspacecast
|
|
|
|
; RESULT: @blockaddr.table = private unnamed_addr constant [2 x ptr] [ptr inttoptr (i32 1 to ptr), ptr inttoptr (i32 1 to ptr)]
|
|
; RESULT: @blockaddr.table.addrspacecast = private unnamed_addr constant [2 x ptr addrspace(1)] [ptr addrspace(1) addrspacecast (ptr inttoptr (i32 1 to ptr) to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr inttoptr (i32 1 to ptr) to ptr addrspace(1))]
|
|
|
|
@blockaddr.table = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@foo, %L1), ptr blockaddress(@foo, %L2)]
|
|
|
|
@blockaddr.table.addrspacecast = private unnamed_addr constant [2 x ptr addrspace(1)] [
|
|
ptr addrspace(1) addrspacecast (ptr blockaddress(@foo_addrspacecast, %L1) to ptr addrspace(1)),
|
|
ptr addrspace(1) addrspacecast (ptr blockaddress(@foo_addrspacecast, %L2) to ptr addrspace(1))
|
|
]
|
|
|
|
; RESULT-NOT: define i32 @foo(
|
|
define i32 @foo(i64 %arg0) {
|
|
entry:
|
|
%gep = getelementptr inbounds [2 x ptr], ptr @blockaddr.table, 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: define i32 @foo_addrspacecast(
|
|
define i32 @foo_addrspacecast(i64 %arg0) {
|
|
entry:
|
|
%gep = getelementptr inbounds [2 x ptr addrspace(1)], ptr @blockaddr.table.addrspacecast, i64 0, i64 %arg0
|
|
%load = load ptr addrspace(1), ptr %gep, align 8
|
|
indirectbr ptr addrspace(1) %load, [label %L2, label %L1]
|
|
|
|
L1:
|
|
%phi = phi i32 [ 1, %L2 ], [ 2, %entry ]
|
|
ret i32 %phi
|
|
|
|
L2:
|
|
br label %L1
|
|
}
|