Skip to content

Commit

Permalink
Support floats in input/output in vector registers of PowerPC inline …
Browse files Browse the repository at this point in the history
…assembly
  • Loading branch information
taiki-e committed Nov 28, 2024
1 parent 0f8ebba commit df8feb5
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 12 deletions.
42 changes: 42 additions & 0 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand Down Expand Up @@ -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,
}
}
Expand Down Expand Up @@ -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),
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/asm/powerpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => &[],
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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` |
Expand Down
66 changes: 66 additions & 0 deletions tests/assembly/asm/powerpc-types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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");
6 changes: 3 additions & 3 deletions tests/ui/asm/powerpc/bad-reg.aix64.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -170,23 +170,23 @@ 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
|
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
|
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
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/asm/powerpc/bad-reg.powerpc64.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,15 @@ 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
|
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
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -170,23 +170,23 @@ 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
|
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
|
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
Expand Down

0 comments on commit df8feb5

Please sign in to comment.