llvm / llvm-project

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

[PowerPC] Cannot select llvm.{min,max}imum.{f32,f64} #64209

Closed Urgau closed 5 months ago

Urgau commented 1 year ago

It seems that none of these intrinsics are currently working on PowerPC:

Error output [godbolt]:

LLVM ERROR: Cannot select: 0x71ba4c0: f32 = fmaximum 0x71ba370, 0x71ba450
  0x71ba370: f32,ch = CopyFromReg 0x714d030, Register:f32 %0
    0x71ba300: f32 = Register %0
  0x71ba450: f32,ch = CopyFromReg 0x714d030, Register:f32 %1
    0x71ba3e0: f32 = Register %1
In function: _ZN1a4test17hb60f9f6975710eeaE
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.  Program arguments: /opt/compiler-explorer/clang-trunk/bin/llc -o /app/output.s -x86-asm-syntax=intel <source>
1.  Running pass 'Function Pass Manager' on module '<source>'.
2.  Running pass 'PowerPC DAG->DAG Pattern Instruction Selection' on function '@_ZN1a4test17hb60f9f6975710eeaE'
 #0 0x0000000003066278 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-trunk/bin/llc+0x3066278)
 #1 0x0000000003063e3c SignalHandler(int) Signals.cpp:0:0
 #2 0x00007fda056b9420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007fda0517c00b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300b)
 #4 0x00007fda0515b859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x22859)
 #5 0x000000000069cfa2 llvm::RISCVISAInfo::updateImplication() (.cold) RISCVISAInfo.cpp:0:0
 #6 0x0000000002e4f044 llvm::SelectionDAGISel::CannotYetSelect(llvm::SDNode*) (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e4f044)
 #7 0x0000000002e546d5 llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e546d5)
 #8 0x0000000001558153 (anonymous namespace)::PPCDAGToDAGISel::Select(llvm::SDNode*) PPCISelDAGToDAG.cpp:0:0
 #9 0x0000000002e4c6a7 llvm::SelectionDAGISel::DoInstructionSelection() (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e4c6a7)
#10 0x0000000002e58f65 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e58f65)
#11 0x0000000002e5b9b9 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e5b9b9)
#12 0x0000000002e5e086 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (.part.0) SelectionDAGISel.cpp:0:0
#13 0x000000000155ebf7 (anonymous namespace)::PPCDAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) PPCISelDAGToDAG.cpp:0:0
#14 0x0000000002443820 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) MachineFunctionPass.cpp:0:0
#15 0x00000000029263f2 llvm::FPPassManager::runOnFunction(llvm::Function&) (/opt/compiler-explorer/clang-trunk/bin/llc+0x29263f2)
#16 0x0000000002926571 llvm::FPPassManager::runOnModule(llvm::Module&) (/opt/compiler-explorer/clang-trunk/bin/llc+0x2926571)
#17 0x00000000029280e0 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/compiler-explorer/clang-trunk/bin/llc+0x29280e0)
#18 0x0000000000766170 compileModule(char**, llvm::LLVMContext&) llc.cpp:0:0
#19 0x00000000006a7ce2 main (/opt/compiler-explorer/clang-trunk/bin/llc+0x6a7ce2)
#20 0x00007fda0515d083 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24083)
#21 0x000000000075e0be _start (/opt/compiler-explorer/clang-trunk/bin/llc+0x75e0be)

Similar to https://github.com/llvm/llvm-project/issues/53353 which was for x86_64

llvmbot commented 1 year ago

@llvm/issue-subscribers-backend-powerpc

nemanjai commented 1 year ago

These are intrinsics that get lowered to SDAG nodes for which there is no default expansion or libcall. Each back end must handle them appropriately. Where does this come from? Do you have an actual use case that requires that the PowerPC back end handle these or is this just an observation?

Urgau commented 1 year ago

My use case comes from trying to implement the IEEE 754-2019 minimum and maximum operations for the Rust standard library using the appropriate LLVM intrinsics, as we have done for min and max in the past.

As for specifically needing the PowerPC backend to support this, it's because rustc does not (at least when I looked it up) and does not seem to be in the habit of supporting per-target intrinsics.

ecnelises commented 1 year ago

I once had a patch for minimum/maximum on PowerPC (using type-J instruction after ISA 3.0): https://reviews.llvm.org/D83466

But I did not have an ideal test case to ensure whether the 'Java semantics' conforms minimum/maximum of LLVM.

nemanjai commented 1 year ago

I really think we should implement these in a subtarget-independent way. We should emit the necessary code to do the comparison and to propagate NaN's as the semantics require. It may be slow on subtargets that don't have the instructions that just do the right thing, but it will at least work.

ecnelises commented 1 year ago

arm64 supports maxnum and maximum natively (fmaxnm and fmax). I did a test on an arm64 machine, and use following C code to emit xsmaxjdp for llvm.maximum.f64 on ppc64le, however the result shows difference from arm64's: ppc type-j max instruction keeps signaling NaNs while fmax on arm64 always makes them quiet. LLVM langref does not mention handling for singaling NaNs in that part, so maybe that still conforms the spec.

xsmaxjdp.c.txt

Anyway, x86 lowers it customly, we can do it in a similar way.

ecnelises commented 1 year ago

https://reviews.llvm.org/D158053

llvmbot commented 5 months ago

@llvm/issue-subscribers-backend-arm

Author: None (Urgau)

It seems that none of these intrinsics are currently working on PowerPC: - llvm.minimum.f32 - llvm.minimum.f64 - llvm.maximum.f32 - llvm.maximum.f64 Error output [\[godbolt\]](https://godbolt.org/z/cMzhbYKjG): ``` LLVM ERROR: Cannot select: 0x71ba4c0: f32 = fmaximum 0x71ba370, 0x71ba450 0x71ba370: f32,ch = CopyFromReg 0x714d030, Register:f32 %0 0x71ba300: f32 = Register %0 0x71ba450: f32,ch = CopyFromReg 0x714d030, Register:f32 %1 0x71ba3e0: f32 = Register %1 In function: _ZN1a4test17hb60f9f6975710eeaE PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace. Stack dump: 0. Program arguments: /opt/compiler-explorer/clang-trunk/bin/llc -o /app/output.s -x86-asm-syntax=intel <source> 1. Running pass 'Function Pass Manager' on module '<source>'. 2. Running pass 'PowerPC DAG->DAG Pattern Instruction Selection' on function '@_ZN1a4test17hb60f9f6975710eeaE' #0 0x0000000003066278 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-trunk/bin/llc+0x3066278) #1 0x0000000003063e3c SignalHandler(int) Signals.cpp:0:0 #2 0x00007fda056b9420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420) #3 0x00007fda0517c00b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300b) #4 0x00007fda0515b859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x22859) #5 0x000000000069cfa2 llvm::RISCVISAInfo::updateImplication() (.cold) RISCVISAInfo.cpp:0:0 #6 0x0000000002e4f044 llvm::SelectionDAGISel::CannotYetSelect(llvm::SDNode*) (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e4f044) #7 0x0000000002e546d5 llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e546d5) #8 0x0000000001558153 (anonymous namespace)::PPCDAGToDAGISel::Select(llvm::SDNode*) PPCISelDAGToDAG.cpp:0:0 #9 0x0000000002e4c6a7 llvm::SelectionDAGISel::DoInstructionSelection() (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e4c6a7) #10 0x0000000002e58f65 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e58f65) #11 0x0000000002e5b9b9 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/opt/compiler-explorer/clang-trunk/bin/llc+0x2e5b9b9) #12 0x0000000002e5e086 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (.part.0) SelectionDAGISel.cpp:0:0 #13 0x000000000155ebf7 (anonymous namespace)::PPCDAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) PPCISelDAGToDAG.cpp:0:0 #14 0x0000000002443820 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) MachineFunctionPass.cpp:0:0 #15 0x00000000029263f2 llvm::FPPassManager::runOnFunction(llvm::Function&) (/opt/compiler-explorer/clang-trunk/bin/llc+0x29263f2) #16 0x0000000002926571 llvm::FPPassManager::runOnModule(llvm::Module&) (/opt/compiler-explorer/clang-trunk/bin/llc+0x2926571) #17 0x00000000029280e0 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/compiler-explorer/clang-trunk/bin/llc+0x29280e0) #18 0x0000000000766170 compileModule(char**, llvm::LLVMContext&) llc.cpp:0:0 #19 0x00000000006a7ce2 main (/opt/compiler-explorer/clang-trunk/bin/llc+0x6a7ce2) #20 0x00007fda0515d083 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24083) #21 0x000000000075e0be _start (/opt/compiler-explorer/clang-trunk/bin/llc+0x75e0be) ``` Similar to https://github.com/llvm/llvm-project/issues/53353 which was for x86_64