Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PowerPC] SIGILL in PPCTargetLowering for powerpc-unknown-linux-gnu with pwr9 target feature #92233

Closed
tgross35 opened this issue May 15, 2024 · 6 comments
Assignees
Labels
backend:PowerPC crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@tgross35
Copy link

tgross35 commented May 15, 2024

This only happens when 128-bit floats are involved. The reproduction comes from Rust:

#![feature(f128)]

#[no_mangle]
pub fn entry(a: u128) -> f128 {
    f128::from_bits(a)
}

Invocation:

$ rustc transmute-lib.rs --target powerpc-unknown-linux-gnu -C linker=powerpc-linux-gnu-gcc -Ctarget-cpu=pwr9 -o transmute.rs.ppc.pwr9 --crate-type=lib
Illegal instruction
$ rustc -Vv
rustc 1.80.0-nightly (9c9b56879 2024-05-05)
binary: rustc
commit-hash: 9c9b568792ef20d8459c745345dd3e79b7c7fa8c
commit-date: 2024-05-05
host: x86_64-unknown-linux-gnu
release: 1.80.0-nightly
LLVM version: 18.1.4

IR:

; ModuleID = 'transmute_lib.1e179323af95c5c5-cgu.0'
source_filename = "transmute_lib.1e179323af95c5c5-cgu.0"
target datalayout = "E-m:e-p:32:32-Fn32-i64:64-n32"
target triple = "powerpc-unknown-linux-gnu"

; core::f128::<impl f128>::from_bits
; Function Attrs: inlinehint uwtable
define internal fp128 @"_ZN4core4f12822_$LT$impl$u20$f128$GT$9from_bits17hd411f033365ec7b5E"(i128 %v) unnamed_addr #0 {
start:
  %_0 = bitcast i128 %v to fp128
  ret fp128 %_0
}

; Function Attrs: uwtable
define fp128 @entry(i128 %a) unnamed_addr #1 {
start:
; call core::f128::<impl f128>::from_bits
  %_0 = call fp128 @"_ZN4core4f12822_$LT$impl$u20$f128$GT$9from_bits17hd411f033365ec7b5E"(i128 %a)
  ret fp128 %_0
}

attributes #0 = { inlinehint uwtable "probe-stack"="inline-asm" "target-cpu"="pwr9" }
attributes #1 = { uwtable "probe-stack"="inline-asm" "target-cpu"="pwr9" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{!"rustc version 1.80.0-nightly (9c9b56879 2024-05-05)"}

Backtrace from GDB:

#0  0x00007fffeee2a599 in llvm::PPCTargetLowering::LowerOperation(llvm::SDValue, llvm::SelectionDAG&) const ()
#1  0x00007ffff0227d99 in llvm::TargetLowering::LowerOperationWrapper(llvm::SDNode*, llvm::SmallVectorImpl<llvm::SDValue>&, llvm::SelectionDAG&) const ()
#2  0x00007ffff0c68ac0 in llvm::DAGTypeLegalizer::ExpandIntegerOperand(llvm::SDNode*, unsigned int) [clone .cold] ()
#3  0x00007ffff0389b36 in llvm::DAGTypeLegalizer::run() [clone .warm] ()
#4  0x00007fffefb71b09 in llvm::SelectionDAGISel::CodeGenAndEmitDAG() ()
#5  0x00007fffefbd92c2 in llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) ()
#6  0x00007fffefb167ea in llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) ()
#7  0x00007fffeede2b1e in (anonymous namespace)::PPCDAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) ()
#8  0x00007fffefb0ee14 in llvm::FPPassManager::runOnFunction(llvm::Function&) ()
#9  0x00007fffefb0e285 in llvm::FPPassManager::runOnModule(llvm::Module&) ()
#10 0x00007ffff0074ca0 in llvm::legacy::PassManagerImpl::run(llvm::Module&) ()
#11 0x00007ffff6b58d10 in LLVMRustWriteOutputFile ()
#12 0x00007ffff6b58928 in rustc_codegen_llvm::back::write::write_output_file ()
#13 0x00007ffff6b565af in rustc_codegen_llvm::back::write::codegen ()
#14 0x00007ffff6b56285 in rustc_codegen_ssa::back::write::finish_intra_module_work::<rustc_codegen_llvm::LlvmCodegenBackend> ()
#15 0x00007ffff6b59377 in std::sys_common::backtrace::__rust_begin_short_backtrace::<<rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::ExtraBackendMethods>::spawn_named_thread<rustc_codegen_ssa::back::write::spawn_work<rustc_codegen_llvm::LlvmCodegenBackend>::{closure#0}, ()>::{closure#0}, ()> ()
#16 0x00007ffff6b58e5b in <<std::thread::Builder>::spawn_unchecked_<<rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::ExtraBackendMethods>::spawn_named_thread<rustc_codegen_ssa::back::write::spawn_work<rustc_codegen_llvm::LlvmCodegenBackend>::{closure#0}, ()>::{closure#0}, ()>::{closure#0}, ()> ()
#17 0x00007ffff19997bb in alloc::boxed::{impl#48}::call_once<(), dyn core::ops::function::FnOnce<(), Output=()>, alloc::alloc::Global> ()
#18 alloc::boxed::{impl#48}::call_once<(), alloc::boxed::Box<dyn core::ops::function::FnOnce<(), Output=()>, alloc::alloc::Global>, alloc::alloc::Global> ()
#19 std::sys::pal::unix::thread::{impl#2}::new::thread_start () at library/std/src/sys/pal/unix/thread.rs:108
@llvmbot
Copy link
Collaborator

llvmbot commented May 15, 2024

@llvm/issue-subscribers-backend-powerpc

Author: Trevor Gross (tgross35)

I don't know whether 32-bit ppc with power9 is actually valid, but it shouldn't sigill in any case.

The reproduction comes from Rust:

#![feature(f128)]

#[no_mangle]
pub fn entry(a: u128) -&gt; f128 {
    f128::from_bits(a)
}

Invocation:

$ rustc transmute-lib.rs --target powerpc-unknown-linux-gnu -C linker=powerpc-linux-gnu-gcc -Ctarget-cpu=pwr9 -o transmute.rs.ppc.pwr9 --crate-type=lib
Illegal instruction
$ rustc -Vv
rustc 1.80.0-nightly (9c9b56879 2024-05-05)
binary: rustc
commit-hash: 9c9b568792ef20d8459c745345dd3e79b7c7fa8c
commit-date: 2024-05-05
host: x86_64-unknown-linux-gnu
release: 1.80.0-nightly
LLVM version: 18.1.4

IR:

; ModuleID = 'transmute_lib.1e179323af95c5c5-cgu.0'
source_filename = "transmute_lib.1e179323af95c5c5-cgu.0"
target datalayout = "E-m:e-p:32:32-Fn32-i64:64-n32"
target triple = "powerpc-unknown-linux-gnu"

; core::f128::&lt;impl f128&gt;::from_bits
; Function Attrs: inlinehint uwtable
define internal fp128 @"_ZN4core4f12822_$LT$impl$u20$f128$GT$9from_bits17hd411f033365ec7b5E"(i128 %v) unnamed_addr #<!-- -->0 {
start:
  %_0 = bitcast i128 %v to fp128
  ret fp128 %_0
}

; Function Attrs: uwtable
define fp128 @<!-- -->entry(i128 %a) unnamed_addr #<!-- -->1 {
start:
; call core::f128::&lt;impl f128&gt;::from_bits
  %_0 = call fp128 @"_ZN4core4f12822_$LT$impl$u20$f128$GT$9from_bits17hd411f033365ec7b5E"(i128 %a)
  ret fp128 %_0
}

attributes #<!-- -->0 = { inlinehint uwtable "probe-stack"="inline-asm" "target-cpu"="pwr9" }
attributes #<!-- -->1 = { uwtable "probe-stack"="inline-asm" "target-cpu"="pwr9" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{!"rustc version 1.80.0-nightly (9c9b56879 2024-05-05)"}

Backtrace from GDB:

#<!-- -->0  0x00007fffeee2a599 in llvm::PPCTargetLowering::LowerOperation(llvm::SDValue, llvm::SelectionDAG&amp;) const ()
#<!-- -->1  0x00007ffff0227d99 in llvm::TargetLowering::LowerOperationWrapper(llvm::SDNode*, llvm::SmallVectorImpl&lt;llvm::SDValue&gt;&amp;, llvm::SelectionDAG&amp;) const ()
#<!-- -->2  0x00007ffff0c68ac0 in llvm::DAGTypeLegalizer::ExpandIntegerOperand(llvm::SDNode*, unsigned int) [clone .cold] ()
#<!-- -->3  0x00007ffff0389b36 in llvm::DAGTypeLegalizer::run() [clone .warm] ()
#<!-- -->4  0x00007fffefb71b09 in llvm::SelectionDAGISel::CodeGenAndEmitDAG() ()
#<!-- -->5  0x00007fffefbd92c2 in llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&amp;) ()
#<!-- -->6  0x00007fffefb167ea in llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&amp;) ()
#<!-- -->7  0x00007fffeede2b1e in (anonymous namespace)::PPCDAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&amp;) ()
#<!-- -->8  0x00007fffefb0ee14 in llvm::FPPassManager::runOnFunction(llvm::Function&amp;) ()
#<!-- -->9  0x00007fffefb0e285 in llvm::FPPassManager::runOnModule(llvm::Module&amp;) ()
#<!-- -->10 0x00007ffff0074ca0 in llvm::legacy::PassManagerImpl::run(llvm::Module&amp;) ()
#<!-- -->11 0x00007ffff6b58d10 in LLVMRustWriteOutputFile ()
#<!-- -->12 0x00007ffff6b58928 in rustc_codegen_llvm::back::write::write_output_file ()
#<!-- -->13 0x00007ffff6b565af in rustc_codegen_llvm::back::write::codegen ()
#<!-- -->14 0x00007ffff6b56285 in rustc_codegen_ssa::back::write::finish_intra_module_work::&lt;rustc_codegen_llvm::LlvmCodegenBackend&gt; ()
#<!-- -->15 0x00007ffff6b59377 in std::sys_common::backtrace::__rust_begin_short_backtrace::&lt;&lt;rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::ExtraBackendMethods&gt;::spawn_named_thread&lt;rustc_codegen_ssa::back::write::spawn_work&lt;rustc_codegen_llvm::LlvmCodegenBackend&gt;::{closure#<!-- -->0}, ()&gt;::{closure#<!-- -->0}, ()&gt; ()
#<!-- -->16 0x00007ffff6b58e5b in &lt;&lt;std::thread::Builder&gt;::spawn_unchecked_&lt;&lt;rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::ExtraBackendMethods&gt;::spawn_named_thread&lt;rustc_codegen_ssa::back::write::spawn_work&lt;rustc_codegen_llvm::LlvmCodegenBackend&gt;::{closure#<!-- -->0}, ()&gt;::{closure#<!-- -->0}, ()&gt;::{closure#<!-- -->0}, ()&gt; ()
#<!-- -->17 0x00007ffff19997bb in alloc::boxed::{impl#<!-- -->48}::call_once&lt;(), dyn core::ops::function::FnOnce&lt;(), Output=()&gt;, alloc::alloc::Global&gt; ()
#<!-- -->18 alloc::boxed::{impl#<!-- -->48}::call_once&lt;(), alloc::boxed::Box&lt;dyn core::ops::function::FnOnce&lt;(), Output=()&gt;, alloc::alloc::Global&gt;, alloc::alloc::Global&gt; ()
#<!-- -->19 std::sys::pal::unix::thread::{impl#<!-- -->2}::new::thread_start () at library/std/src/sys/pal/unix/thread.rs:108

@chenzheng1030
Copy link
Collaborator

I've fixed the crash in 3d8c2f0103556674a36b7252dd2f726912768527

Please note that __i128 is not supported in clang frontend for target powerpc-unknown-linux-gnu. See https://godbolt.org/z/M1onxvb5W
I think the float 128 support especially ieee128 is not well tested on target powerpc-unknown-linux-gnu either.

Maybe rust should also disable the __i128 support for target powerpc-unknown-linux-gnu

@tgross35
Copy link
Author

I've fixed the crash in 3d8c2f0103556674a36b7252dd2f726912768527

Great, thank you for the quick fix!

Please note that __i128 is not supported in clang frontend for target powerpc-unknown-linux-gnu. See https://godbolt.org/z/M1onxvb5W I think the float 128 support especially ieee128 is not well tested on target powerpc-unknown-linux-gnu either.

Maybe rust should also disable the __i128 support for target powerpc-unknown-linux-gnu

Integer types i128 and u128 have been around for years on all platforms without many big issues, so those won't be going anywhere (in fact, Clang could probably enable them on more targets based on this evidence). f128 support is indeed buggy almost everywhere - but it's currently an unstable feature and will be for a while, so we are just trying to identify what bugs exist before deciding what exactly will eventually be stabilized.

@chenzheng1030
Copy link
Collaborator

f128 support is indeed buggy almost everywhere - but it's currently an unstable feature and will be for a while, so we are just trying to identify what bugs exist before deciding what exactly will eventually be stabilized.

Thank you! If you are going to check the f128 support status in LLVM backend for powerpc-unknown-linux-gnu, I am glad to investigate issues you get.

@tgross35
Copy link
Author

Thank you :) If you are familiar with that platform, do you know if QEMU has some limitations with this target? I was hitting a SIGILL at stxvd2x in testing (rust-lang/compiler-builtins#606 (comment)) but think this seems like a qemu problem rather than bad codegen.

@chenzheng1030
Copy link
Collaborator

Thank you :) If you are familiar with that platform, do you know if QEMU has some limitations with this target?

Unfortunately I don't have much knowledge about the QEMU. For the SIGILL at stxvd2x, 1: Is the simulated target PWR7 or above? 2: Does the address match stxvd2x alignment requirement according to the PPC user manual?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:PowerPC crash Prefer [crash-on-valid] or [crash-on-invalid]
Projects
None yet
Development

No branches or pull requests

4 participants