From ba7916a62ceae9c5cf262aa437e1f3bc01971ebf Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 29 Nov 2024 02:30:07 +0900 Subject: [PATCH] Support floats in input/output in vector registers of PowerPC inline assembly --- compiler/rustc_codegen_llvm/src/asm.rs | 42 ++++++++++++ compiler/rustc_target/src/asm/powerpc.rs | 4 +- .../asm-experimental-arch.md | 2 +- tests/assembly/asm/powerpc-types.rs | 66 +++++++++++++++++++ 4 files changed, 111 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 1483d576362b2..d1804cb49ad19 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -1040,6 +1040,26 @@ fn llvm_fixup_input<'ll, 'tcx>( let value = bx.or(value, bx.const_u32(0xFFFF_0000)); bx.bitcast(value, bx.type_f32()) } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F32) => + { + let value = bx.insert_element( + bx.const_undef(bx.type_vector(bx.type_f32(), 4)), + value, + bx.const_usize(0), + ); + bx.bitcast(value, bx.type_vector(bx.type_f32(), 4)) + } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F64) => + { + let value = bx.insert_element( + bx.const_undef(bx.type_vector(bx.type_f64(), 2)), + value, + bx.const_usize(0), + ); + bx.bitcast(value, bx.type_vector(bx.type_f64(), 2)) + } _ => value, } } @@ -1175,6 +1195,18 @@ fn llvm_fixup_output<'ll, 'tcx>( let value = bx.trunc(value, bx.type_i16()); bx.bitcast(value, bx.type_f16()) } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F32) => + { + let value = bx.bitcast(value, bx.type_vector(bx.type_f32(), 4)); + bx.extract_element(value, bx.const_usize(0)) + } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F64) => + { + let value = bx.bitcast(value, bx.type_vector(bx.type_f64(), 2)); + bx.extract_element(value, bx.const_usize(0)) + } _ => value, } } @@ -1299,6 +1331,16 @@ fn llvm_fixup_output_type<'ll, 'tcx>( { cx.type_f32() } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F32) => + { + cx.type_vector(cx.type_f32(), 4) + } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F64) => + { + cx.type_vector(cx.type_f64(), 2) + } _ => layout.llvm_type(cx), } } diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index a5a96b87e367a..42a58e6725bd1 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -51,10 +51,10 @@ impl PowerPCInlineAsmRegClass { } } Self::freg => types! { _: F32, F64; }, - // FIXME: vsx also supports integers and floats: https://github.com/rust-lang/rust/pull/131551#discussion_r1797651773 + // FIXME: vsx also supports integers?: https://github.com/rust-lang/rust/pull/131551#discussion_r1797651773 Self::vreg => types! { altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4); - vsx: VecI64(2), VecF64(2); + vsx: F32, F64, VecI64(2), VecF64(2); }, Self::cr | Self::xer => &[], } diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index f2d0caa5e37cc..c2f4170d7d295 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -76,7 +76,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `freg` | None | `f32`, `f64` | | PowerPC | `vreg` | `altivec` | `i8x16`, `i16x8`, `i32x4`, `f32x4` | -| PowerPC | `vreg` | `vsx` | `i64x2`, `f64x2` | +| PowerPC | `vreg` | `vsx` | `f32`, `f64`, `i64x2`, `f64x2` | | PowerPC | `cr` | N/A | Only clobbers | | PowerPC | `xer` | N/A | Only clobbers | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs index d67e0f66f66f5..aa35c4d886581 100644 --- a/tests/assembly/asm/powerpc-types.rs +++ b/tests/assembly/asm/powerpc-types.rs @@ -225,6 +225,28 @@ check!(vreg_f32x4, f32x4, vreg, "vmr"); #[cfg(vsx)] check!(vreg_f64x2, f64x2, vreg, "vmr"); +// powerpc_vsx-LABEL: vreg_f32: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f32: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_f32, f32, vreg, "vmr"); + +// powerpc_vsx-LABEL: vreg_f64: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_f64, f64, vreg, "vmr"); + // CHECK-LABEL: reg_i8_r0: // CHECK: #APP // CHECK: mr 0, 0 @@ -365,6 +387,28 @@ check_reg!(vreg_f32x4_v0, f32x4, "0", "v0", "vmr"); #[cfg(vsx)] check_reg!(vreg_f64x2_v0, f64x2, "0", "v0", "vmr"); +// powerpc_vsx-LABEL: vreg_f32_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f32_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f32_v0, f32, "0", "v0", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64_v0, f64, "0", "v0", "vmr"); + // powerpc_altivec-LABEL: vreg_i8x16_v18: // powerpc_altivec: #APP // powerpc_altivec: vmr 18, 18 @@ -430,3 +474,25 @@ check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr"); // powerpc64_vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_f32_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f32_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f32_v18, f32, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64_v18, f64, "18", "v18", "vmr");