llvm / llvm-project

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

[AArch64/GlobalISel] `fcmp true` / `fcmp false` used in `and` / `or` branching condition causes crash `Unknown FP condition!` #58050

Open HazyFish opened 1 year ago

HazyFish commented 1 year ago

Description

When fcmp true / fcmp false is used in and / or branching condition, llc crashes with error Unknown FP condition! for AArch64 when using GlobalISel.

Cause

The direct cause of the problem is that AArch64GISelUtils::changeFCMPPredToAArch64CC does not map predicates CmpInst::FCMP_TRUE and CmpInst::FCMP_FALSE to some AArch64CC::CondCode.

The root cause is that the developers might have assumed that fcmp true and fcmp false will be translated to an G_CONSTANT i1 in Generic MIR by IRTranslator before Instruction Selection. Such an assumption is true in most situations due to the special handling of CmpInst::FCMP_TRUE and CmpInst::FCMP_FALSE in IRTranslator::translateCompare. However, when such instruction is used in an and / or branching condition, IRTranslator::emitSwitchCase called by IRTranslator::translateBr will emit G_FCMP floatpred(false) instruction to Generic MIR here, thus failing the assumption.

Minimal Reproduction

https://godbolt.org/z/MMcG6fxer

Code

define void @f() {
BB:
  br label %BB1

BB1:                                              ; preds = %BB1, %BB
  %A1 = fcmp false float 0.5, 0.5
  %A2 = or i1 %A1, false
  br i1 %A2, label %BB1, label %BB2

BB2:                                              ; preds = %BB1
  ret void
}

Stack Trace

Unknown FP condition!
UNREACHABLE executed at /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp:105!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.  Program arguments: ./llvm-project/build-debug/bin/llc -mtriple=aarch64 -global-isel crash-reports/gisel-aarch64/1.ll
1.  Running pass 'Function Pass Manager' on module 'crash-reports/gisel-aarch64/1.ll'.
2.  Running pass 'InstructionSelect' on function '@f'
 #0 0x0000000003adad2a llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Support/Unix/Signals.inc:569:11
 #1 0x0000000003adaedb PrintStackTraceSignalHandler(void*) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Support/Unix/Signals.inc:636:1
 #2 0x0000000003ad9526 llvm::sys::RunSignalHandlers() /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Support/Signals.cpp:103:5
 #3 0x0000000003adb605 SignalHandler(int) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Support/Unix/Signals.inc:407:1
 #4 0x00007ff7231a5980 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12980)
 #5 0x00007ff722095e87 raise /build/glibc-uZu3wS/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c:51:0
 #6 0x00007ff7220977f1 abort /build/glibc-uZu3wS/glibc-2.27/stdlib/abort.c:81:0
 #7 0x0000000003a017a0 llvm::install_out_of_memory_new_handler() /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Support/ErrorHandling.cpp:193:0
 #8 0x00000000016a3f3e llvm::AArch64GISelUtils::changeFCMPPredToAArch64CC(llvm::CmpInst::Predicate, llvm::AArch64CC::CondCode&, llvm::AArch64CC::CondCode&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp:107:5
 #9 0x00000000016d22e2 (anonymous namespace)::AArch64InstructionSelector::selectCompareBranchFedByFCmp(llvm::MachineInstr&, llvm::MachineInstr&, llvm::MachineIRBuilder&) const /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp:1629:32
#10 0x00000000016ba4d3 (anonymous namespace)::AArch64InstructionSelector::selectCompareBranch(llvm::MachineInstr&, llvm::MachineFunction&, llvm::MachineRegisterInfo&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp:1749:5
#11 0x00000000016a564a (anonymous namespace)::AArch64InstructionSelector::select(llvm::MachineInstr&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp:2471:5
#12 0x0000000003fa4472 llvm::InstructionSelect::runOnMachineFunction(llvm::MachineFunction&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp:187:11
#13 0x0000000002894c85 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:91:8
#14 0x0000000002f797d6 llvm::FPPassManager::runOnFunction(llvm::Function&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1430:23
#15 0x0000000002f7e602 llvm::FPPassManager::runOnModule(llvm::Module&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1476:16
#16 0x0000000002f7a0a9 (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1545:23
#17 0x0000000002f79c1d llvm::legacy::PassManagerImpl::run(llvm::Module&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:535:16
#18 0x0000000002f7e8e1 llvm::legacy::PassManager::run(llvm::Module&) /home/henry/aflplusplus-isel/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1672:3
#19 0x0000000000d2cdbc compileModule(char**, llvm::LLVMContext&) /home/henry/aflplusplus-isel/llvm-project/llvm/tools/llc/llc.cpp:737:41
#20 0x0000000000d2b162 main /home/henry/aflplusplus-isel/llvm-project/llvm/tools/llc/llc.cpp:418:13
#21 0x00007ff722078c87 __libc_start_main /build/glibc-uZu3wS/glibc-2.27/csu/../csu/libc-start.c:344:0
#22 0x0000000000d2a96a _start (./llvm-project/build-debug/bin/llc+0xd2a96a)
llvmbot commented 1 year ago

@llvm/issue-subscribers-backend-aarch64