Support floats in input/output in vector registers of PowerPC inline assembly

This commit is contained in:
Taiki Endo 2024-11-29 03:10:07 +09:00
parent 0f8ebba54a
commit df8feb5067
7 changed files with 120 additions and 12 deletions

View file

@ -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),
}
}

View file

@ -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_r1862535963
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 => &[],
}

View file

@ -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` |

View file

@ -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");

View file

@ -170,7 +170,7 @@ error: type `i32` cannot be used with this register class
LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available
| ^
|
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:79:28
@ -178,7 +178,7 @@ error: type `i32` cannot be used with this register class
LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available
| ^
|
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:87:35
@ -186,7 +186,7 @@ error: type `i32` cannot be used with this register class
LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
| ^
|
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:109:27

View file

@ -186,7 +186,7 @@ error: type `i32` cannot be used with this register class
LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available
| ^
|
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:79:28
@ -194,7 +194,7 @@ error: type `i32` cannot be used with this register class
LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available
| ^
|
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
error: `vsx` target feature is not enabled
--> $DIR/bad-reg.rs:84:35
@ -210,7 +210,7 @@ error: type `i32` cannot be used with this register class
LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
| ^
|
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:109:27

View file

@ -170,7 +170,7 @@ error: type `i32` cannot be used with this register class
LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available
| ^
|
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:79:28
@ -178,7 +178,7 @@ error: type `i32` cannot be used with this register class
LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available
| ^
|
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:87:35
@ -186,7 +186,7 @@ error: type `i32` cannot be used with this register class
LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
| ^
|
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
= note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:109:27