llvm / llvm-project

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

`x86-64-v3+avx512f` crash on `X86 DAG->DAG Instruction Selection` #106336

Open Rexicon226 opened 2 months ago

Rexicon226 commented 2 months ago

Here's a repro of the crash with clang:

target triple = "x86_64-unknown-linux-gnu"

define i32 @foo(float %0, float %1) #0 {
Entry:
  %2 = call float @llvm.fabs.f32(float %0)
  %3 = bitcast float %2 to i32
  %4 = icmp ugt i32 %3, 1
  %5 = call float @llvm.fabs.f32(float %1)
  %6 = bitcast float %5 to i32
  %7 = icmp ugt i32 %6, 1
  %8 = select i1 %4, i1 true, i1 %7
  %9 = zext i1 %8 to i32
  ret i32 %9
}

declare float @llvm.fabs.f32(float) #1
uselistorder ptr @llvm.fabs.f32, { 1, 0 }

attributes #0 = { "target-features"="+avx512f,-evex512" }

Here's a godbolt of it happening on trunk assertions: https://llvm.godbolt.org/z/aPP7dE74x

Stack Trace ``` ❯ clang-18 -c ir.ll -O3 fatal error: error in backend: Cannot select: t90: v4i1 = setcc t63, t79, setgt:ch t63: v4i32 = and t61, t91 t61: v4i32 = bitcast t86 t86: v4f32 = X86ISD::INSERTPS t72, t84, TargetConstant:i8<16> t72: v4f32 = scalar_to_vector t4 t4: f32,ch = CopyFromReg t0, Register:f32 %1 t3: f32 = Register %1 t84: v4f32 = scalar_to_vector t2 t2: f32,ch = CopyFromReg t0, Register:f32 %0 t1: f32 = Register %0 t85: i8 = TargetConstant<16> t91: v4i32,ch = X86ISD::VBROADCAST_LOAD<(load (s32) from constant-pool)> t0, t83 t83: i64 = X86ISD::WrapperRIP TargetConstantPool:i64 0 t82: i64 = TargetConstantPool 0 t79: v4i32,ch = X86ISD::VBROADCAST_LOAD<(load (s32) from constant-pool)> t0, t81 t81: i64 = X86ISD::WrapperRIP TargetConstantPool:i64 0 t80: i64 = TargetConstantPool 0 In function: __unordsf2 PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script. Stack dump: 0. Program arguments: clang-18 -c ir.ll -O3 1. Code generation 2. Running pass 'Function Pass Manager' on module 'ir.ll'. 3. Running pass 'X86 DAG->DAG Instruction Selection' on function '@__unordsf2' #0 0x000055cdf522adf0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/david/local/llvm18-assert/bin/clang-18+0x3f00df0) #1 0x000055cdf52281ff llvm::sys::RunSignalHandlers() (/home/david/local/llvm18-assert/bin/clang-18+0x3efe1ff) #2 0x000055cdf516e72a llvm::CrashRecoveryContext::HandleExit(int) (/home/david/local/llvm18-assert/bin/clang-18+0x3e4472a) #3 0x000055cdf5222792 llvm::sys::Process::Exit(int, bool) (/home/david/local/llvm18-assert/bin/clang-18+0x3ef8792) #4 0x000055cdf244fff8 LLVMErrorHandler(void*, char const*, bool) cc1_main.cpp:0:0 #5 0x000055cdf517a500 llvm::report_fatal_error(llvm::Twine const&, bool) (/home/david/local/llvm18-assert/bin/clang-18+0x3e50500) #6 0x000055cdf63756cd llvm::SelectionDAGISel::CannotYetSelect(llvm::SDNode*) (/home/david/local/llvm18-assert/bin/clang-18+0x504b6cd) #7 0x000055cdf6379dc1 llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) (/home/david/local/llvm18-assert/bin/clang-18+0x504fdc1) #8 0x000055cdf3d68977 (anonymous namespace)::X86DAGToDAGISel::Select(llvm::SDNode*) X86ISelDAGToDAG.cpp:0:0 #9 0x000055cdf6371dba llvm::SelectionDAGISel::DoInstructionSelection() (/home/david/local/llvm18-assert/bin/clang-18+0x5047dba) #10 0x000055cdf637f642 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/home/david/local/llvm18-assert/bin/clang-18+0x5055642) #11 0x000055cdf63829b8 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/home/david/local/llvm18-assert/bin/clang-18+0x50589b8) #12 0x000055cdf63846e5 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (.part.0) SelectionDAGISel.cpp:0:0 #13 0x000055cdf3d723c0 (anonymous namespace)::X86DAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) X86ISelDAGToDAG.cpp:0:0 #14 0x000055cdf45aeef7 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) MachineFunctionPass.cpp:0:0 #15 0x000055cdf4ba141e llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/david/local/llvm18-assert/bin/clang-18+0x387741e) #16 0x000055cdf4ba1669 llvm::FPPassManager::runOnModule(llvm::Module&) (/home/david/local/llvm18-assert/bin/clang-18+0x3877669) #17 0x000055cdf4ba1fb5 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/david/local/llvm18-assert/bin/clang-18+0x3877fb5) #18 0x000055cdf5498626 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr, std::unique_ptr>, clang::BackendConsumer*) (/home/david/local/llvm18-assert/bin/clang-18+0x416e626) #19 0x000055cdf5a95eb0 clang::CodeGenAction::ExecuteAction() (/home/david/local/llvm18-assert/bin/clang-18+0x476beb0) #20 0x000055cdf5d1ea39 clang::FrontendAction::Execute() (/home/david/local/llvm18-assert/bin/clang-18+0x49f4a39) #21 0x000055cdf5c99425 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/david/local/llvm18-assert/bin/clang-18+0x496f425) #22 0x000055cdf5de98c5 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/david/local/llvm18-assert/bin/clang-18+0x4abf8c5) #23 0x000055cdf24523a9 cc1_main(llvm::ArrayRef, char const*, void*) (/home/david/local/llvm18-assert/bin/clang-18+0x11283a9) #24 0x000055cdf244a0a3 ExecuteCC1Tool(llvm::SmallVectorImpl&, llvm::ToolContext const&) driver.cpp:0:0 #25 0x000055cdf5ad9cbd void llvm::function_ref::callback_fn>, std::__cxx11::basic_string, std::allocator>*, bool*) const::'lambda'()>(long) Job.cpp:0:0 #26 0x000055cdf516e660 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref) (/home/david/local/llvm18-assert/bin/clang-18+0x3e44660) #27 0x000055cdf5ada53e clang::driver::CC1Command::Execute(llvm::ArrayRef>, std::__cxx11::basic_string, std::allocator>*, bool*) const (.part.0) Job.cpp:0:0 #28 0x000055cdf5a9feba clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/david/local/llvm18-assert/bin/clang-18+0x4775eba) #29 0x000055cdf5aa098d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl>&, bool) const (/home/david/local/llvm18-assert/bin/clang-18+0x477698d) #30 0x000055cdf5aac594 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl>&) (/home/david/local/llvm18-assert/bin/clang-18+0x4782594) #31 0x000055cdf244f616 clang_main(int, char**, llvm::ToolContext const&) (/home/david/local/llvm18-assert/bin/clang-18+0x1125616) #32 0x000055cdf235fa9b main (/home/david/local/llvm18-assert/bin/clang-18+0x1035a9b) #33 0x00007f87fc5d81ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3 #34 0x00007f87fc5d828b call_init ./csu/../csu/libc-start.c:128:20 #35 0x00007f87fc5d828b __libc_start_main ./csu/../csu/libc-start.c:347:5 #36 0x000055cdf2448ce5 _start (/home/david/local/llvm18-assert/bin/clang-18+0x111ece5) clang-18: error: clang frontend command failed with exit code 70 (use -v to see invocation) ```
llvmbot commented 2 months ago

@llvm/issue-subscribers-backend-x86

Author: David Rubin (Rexicon226)

Here's a repro of the crash with clang: ```llvm target triple = "x86_64-unknown-linux-gnu" define i32 @foo(float %0, float %1) #0 { Entry: %2 = call float @llvm.fabs.f32(float %0) %3 = bitcast float %2 to i32 %4 = icmp ugt i32 %3, 1 %5 = call float @llvm.fabs.f32(float %1) %6 = bitcast float %5 to i32 %7 = icmp ugt i32 %6, 1 %8 = select i1 %4, i1 true, i1 %7 %9 = zext i1 %8 to i32 ret i32 %9 } declare float @llvm.fabs.f32(float) #1 uselistorder ptr @llvm.fabs.f32, { 1, 0 } attributes #0 = { "target-features"="+avx512f,-evex512" } ``` Here's a godbolt of it happening on trunk assertions: https://llvm.godbolt.org/z/aPP7dE74x <details> <summary>Stack Trace</summary> ``` ❯ clang-18 -c ir.ll -O3 fatal error: error in backend: Cannot select: t90: v4i1 = setcc t63, t79, setgt:ch t63: v4i32 = and t61, t91 t61: v4i32 = bitcast t86 t86: v4f32 = X86ISD::INSERTPS t72, t84, TargetConstant:i8<16> t72: v4f32 = scalar_to_vector t4 t4: f32,ch = CopyFromReg t0, Register:f32 %1 t3: f32 = Register %1 t84: v4f32 = scalar_to_vector t2 t2: f32,ch = CopyFromReg t0, Register:f32 %0 t1: f32 = Register %0 t85: i8 = TargetConstant<16> t91: v4i32,ch = X86ISD::VBROADCAST_LOAD<(load (s32) from constant-pool)> t0, t83 t83: i64 = X86ISD::WrapperRIP TargetConstantPool:i64<float 0x7FFFFFFFE0000000> 0 t82: i64 = TargetConstantPool<float 0x7FFFFFFFE0000000> 0 t79: v4i32,ch = X86ISD::VBROADCAST_LOAD<(load (s32) from constant-pool)> t0, t81 t81: i64 = X86ISD::WrapperRIP TargetConstantPool:i64<i32 1> 0 t80: i64 = TargetConstantPool<i32 1> 0 In function: __unordsf2 PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script. Stack dump: 0. Program arguments: clang-18 -c ir.ll -O3 1. Code generation 2. Running pass 'Function Pass Manager' on module 'ir.ll'. 3. Running pass 'X86 DAG->DAG Instruction Selection' on function '@__unordsf2' #0 0x000055cdf522adf0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/david/local/llvm18-assert/bin/clang-18+0x3f00df0) #1 0x000055cdf52281ff llvm::sys::RunSignalHandlers() (/home/david/local/llvm18-assert/bin/clang-18+0x3efe1ff) #2 0x000055cdf516e72a llvm::CrashRecoveryContext::HandleExit(int) (/home/david/local/llvm18-assert/bin/clang-18+0x3e4472a) #3 0x000055cdf5222792 llvm::sys::Process::Exit(int, bool) (/home/david/local/llvm18-assert/bin/clang-18+0x3ef8792) #4 0x000055cdf244fff8 LLVMErrorHandler(void*, char const*, bool) cc1_main.cpp:0:0 #5 0x000055cdf517a500 llvm::report_fatal_error(llvm::Twine const&, bool) (/home/david/local/llvm18-assert/bin/clang-18+0x3e50500) #6 0x000055cdf63756cd llvm::SelectionDAGISel::CannotYetSelect(llvm::SDNode*) (/home/david/local/llvm18-assert/bin/clang-18+0x504b6cd) #7 0x000055cdf6379dc1 llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) (/home/david/local/llvm18-assert/bin/clang-18+0x504fdc1) #8 0x000055cdf3d68977 (anonymous namespace)::X86DAGToDAGISel::Select(llvm::SDNode*) X86ISelDAGToDAG.cpp:0:0 #9 0x000055cdf6371dba llvm::SelectionDAGISel::DoInstructionSelection() (/home/david/local/llvm18-assert/bin/clang-18+0x5047dba) #10 0x000055cdf637f642 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/home/david/local/llvm18-assert/bin/clang-18+0x5055642) #11 0x000055cdf63829b8 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/home/david/local/llvm18-assert/bin/clang-18+0x50589b8) #12 0x000055cdf63846e5 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (.part.0) SelectionDAGISel.cpp:0:0 #13 0x000055cdf3d723c0 (anonymous namespace)::X86DAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) X86ISelDAGToDAG.cpp:0:0 #14 0x000055cdf45aeef7 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) MachineFunctionPass.cpp:0:0 #15 0x000055cdf4ba141e llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/david/local/llvm18-assert/bin/clang-18+0x387741e) #16 0x000055cdf4ba1669 llvm::FPPassManager::runOnModule(llvm::Module&) (/home/david/local/llvm18-assert/bin/clang-18+0x3877669) #17 0x000055cdf4ba1fb5 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/david/local/llvm18-assert/bin/clang-18+0x3877fb5) #18 0x000055cdf5498626 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/home/david/local/llvm18-assert/bin/clang-18+0x416e626) #19 0x000055cdf5a95eb0 clang::CodeGenAction::ExecuteAction() (/home/david/local/llvm18-assert/bin/clang-18+0x476beb0) #20 0x000055cdf5d1ea39 clang::FrontendAction::Execute() (/home/david/local/llvm18-assert/bin/clang-18+0x49f4a39) #21 0x000055cdf5c99425 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/david/local/llvm18-assert/bin/clang-18+0x496f425) #22 0x000055cdf5de98c5 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/david/local/llvm18-assert/bin/clang-18+0x4abf8c5) #23 0x000055cdf24523a9 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/david/local/llvm18-assert/bin/clang-18+0x11283a9) #24 0x000055cdf244a0a3 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0 #25 0x000055cdf5ad9cbd void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0 #26 0x000055cdf516e660 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/home/david/local/llvm18-assert/bin/clang-18+0x3e44660) #27 0x000055cdf5ada53e clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0 #28 0x000055cdf5a9feba clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/david/local/llvm18-assert/bin/clang-18+0x4775eba) #29 0x000055cdf5aa098d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/home/david/local/llvm18-assert/bin/clang-18+0x477698d) #30 0x000055cdf5aac594 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/home/david/local/llvm18-assert/bin/clang-18+0x4782594) #31 0x000055cdf244f616 clang_main(int, char**, llvm::ToolContext const&) (/home/david/local/llvm18-assert/bin/clang-18+0x1125616) #32 0x000055cdf235fa9b main (/home/david/local/llvm18-assert/bin/clang-18+0x1035a9b) #33 0x00007f87fc5d81ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3 #34 0x00007f87fc5d828b call_init ./csu/../csu/libc-start.c:128:20 #35 0x00007f87fc5d828b __libc_start_main ./csu/../csu/libc-start.c:347:5 #36 0x000055cdf2448ce5 _start (/home/david/local/llvm18-assert/bin/clang-18+0x111ece5) clang-18: error: clang frontend command failed with exit code 70 (use -v to see invocation) ``` </details>
phoebewang commented 2 months ago

How this IR getting generated? I assume using -march=x86-64-v3 -mavx512f will get "target-features"="+avx512f,+evex512".

The "+avx512f,-evex512" is a bad combination. -evex512 requires target has +avx512vl feature.

Rexicon226 commented 2 months ago

How this IR getting generated? I assume using -march=x86-64-v3 -mavx512f will get "target-features"="+avx512f,+evex512".

The "+avx512f,-evex512" is a bad combination. -evex512 requires target has +avx512vl feature.

You make a very good point. This comes from the Zig compiler, where I was setting the avx512f flag manually, without evex512 being enabled. That was my oversight. Still, should the crash happen? What's the policy on invalid target features attr in the IR?

phoebewang commented 2 months ago

AFAIK, target features can be organized arbitrarily. The evex512 is the only exception. Theoretically, we can solve the crash in backend, but it doesn't have much value, because there's no such a target mapping to this combination. So we carefully handled it in Clang frontend. Other front end should do similar thing to avoid such combination.