llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.39k stars 12.15k forks source link

[SPIR-V] Verifier fails with invalid uses of intrinsic global variable #110495

Open bwlodarcz opened 2 months ago

bwlodarcz commented 2 months ago

Reproducer

example.cpp

int *ptr_0 = nullptr;
void *ptr_1 = ptr_0;
  1. clang -S -emit-llvm -cl-std=clc++ --target=spir example.cpp
  2. llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown example.ll -o - 2>&1

Stack Trace

invalid uses of intrinsic global variable
ptr @llvm.global_ctors
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown global_crash.ll -o -
 #0 0x000055e5a16c0e72 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) <truncated>llvm-project/llvm/lib/Support/Unix/Signals.inc:723:22
 #1 0x000055e5a16c1289 PrintStackTraceSignalHandler(void*) <truncated>llvm-project/llvm/lib/Support/Unix/Signals.inc:798:1
 #2 0x000055e5a16be659 llvm::sys::RunSignalHandlers() <truncated>llvm-project/llvm/lib/Support/Signals.cpp:105:20
 #3 0x000055e5a16c071d SignalHandler(int) <truncated>llvm-project/llvm/lib/Support/Unix/Signals.inc:413:1
 #4 0x00007f2bc2845320 (/lib/x86_64-linux-gnu/libc.so.6+0x45320)
 #5 0x00007f2bc289eb1c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #6 0x00007f2bc289eb1c __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #7 0x00007f2bc289eb1c pthread_kill ./nptl/pthread_kill.c:89:10
 #8 0x00007f2bc284526e raise ./signal/../sysdeps/posix/raise.c:27:6
 #9 0x00007f2bc28288ff abort ./stdlib/abort.c:81:7
#10 0x000055e5a15eb3c0 llvm::report_fatal_error(llvm::Twine const&, bool) <truncated>llvm-project/llvm/lib/Support/ErrorHandling.cpp:126:9
#11 0x000055e5a15eb194 llvm::report_fatal_error(llvm::StringRef, bool) <truncated>llvm-project/llvm/lib/Support/ErrorHandling.cpp:87:68
#12 0x000055e5a096b006 (anonymous namespace)::VerifierLegacyPass::doFinalization(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/Verifier.cpp:7213:12
#13 0x000055e5a0857edb llvm::FPPassManager::doFinalization(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1472:13
#14 0x000055e5a08584bb (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1559:13
#15 0x000055e5a08530e3 llvm::legacy::PassManagerImpl::run(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:541:13
#16 0x000055e5a0858b15 llvm::legacy::PassManager::run(llvm::Module&) <truncated>llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1651:1
#17 0x000055e59edf4eea compileModule(char**, llvm::LLVMContext&) <truncated>llvm-project/llvm/tools/llc/llc.cpp:755:34
#18 0x000055e59edf2605 main <truncated>llvm-project/llvm/tools/llc/llc.cpp:412:35
#19 0x00007f2bc282a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#20 0x00007f2bc282a28b call_init ./csu/../csu/libc-start.c:128:20
#21 0x00007f2bc282a28b __libc_start_main ./csu/../csu/libc-start.c:347:5
#22 0x000055e59edf1065 _start (./llvm-project/build-debug/bin/llc+0x801065)
Aborted (core dumped)

Additional info

I localized the source of the fail in Verifier::visitGlobalVariable function during:

    840   if (GV.hasName() && (GV.getName() == "llvm.global_ctors" ||
    841                        GV.getName() == "llvm.global_dtors")) {
    842     Check(!GV.hasInitializer() || GV.hasAppendingLinkage(),
    843           "invalid linkage for intrinsic global variable", &GV);
    844     Check(GV.materialized_use_empty(),
    845           "invalid uses of intrinsic global variable", &GV);

It sets Broken variable to true in Check(GV.materialized_use_empty() which checks if UseList == nullptr if not it fails. I checked the same example with X86 backend and it works without fail.

IR

Current trunk - followed reproducer above:

; ModuleID = 'example.cpp'
source_filename = "example.cpp"
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
target triple = "spir"

@ptr_0 = dso_local addrspace(1) global ptr addrspace(4) null, align 4
@ptr_1 = dso_local addrspace(1) global ptr addrspace(4) null, align 4
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_example.cpp, ptr null }]

; Function Attrs: convergent noinline nounwind
define internal spir_func void @__cxx_global_var_init() #0 {
entry:
  %0 = load ptr addrspace(4), ptr addrspace(1) @ptr_0, align 4
  store ptr addrspace(4) %0, ptr addrspace(1) @ptr_1, align 4
  ret void
}

; Function Attrs: convergent noinline nounwind
define internal spir_kernel void @_GLOBAL__sub_I_example.cpp() #0 !kernel_arg_addr_space !5 !kernel_arg_access_qual !5 !kernel_arg_type !5 !kernel_arg_base_type !5 !kernel_arg_type_qual !5 {
entry:
  call spir_func void @__cxx_global_var_init()
  ret void
}

attributes #0 = { convergent noinline nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }

!llvm.module.flags = !{!0, !1}
!opencl.ocl.version = !{!2}
!opencl.cxx.version = !{!3}
!opencl.spir.version = !{!2}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"frame-pointer", i32 2}
!2 = !{i32 2, i32 0}
!3 = !{i32 1, i32 0}
!4 = !{!"clang version 20.0.0git (https://github.com/llvm/llvm-project e96f7788f5176dcf39c4eb53e4146f1e791adf83)"}
!5 = !{}
michalpaszkowski commented 2 months ago

@bwlodarcz Could you please attach the input LLVM IR file (Clang output)?

bwlodarcz commented 2 months ago

@michalpaszkowski Edited original message with IR.