1
Fork 0

Rollup merge of #133452 - taiki-e:hexagon-asm-pred, r=Amanieu

Support predicate registers (clobber-only) in Hexagon inline assembly

The result of the Hexagon instructions such as comparison, store conditional, etc. is stored in predicate registers (`p[0-3]`), but currently there is no way to mark it as clobbered in `asm!`.

This is also needed for `clobber_abi` (although implementing `clobber_abi` will require the addition of support for [several more register classes](https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp#L71-L90). see also https://github.com/rust-lang/rust/issues/93335#issuecomment-2395210055).

Refs:
- [Section 6 "Conditional Execution" in Qualcomm Hexagon V73 Programmer’s Reference Manual](https://docs.qualcomm.com/bundle/publicresource/80-N2040-53_REV_AB_Qualcomm_Hexagon_V73_Programmers_Reference_Manual.pdf#page=90)
- [Register definition in LLVM](https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Hexagon/HexagonRegisterInfo.td#L155)

cc `@androm3da` (target maintainer of hexagon-unknown-{[none-elf](https://doc.rust-lang.org/nightly/rustc/platform-support/hexagon-unknown-none-elf.html#target-maintainers),[linux-musl](https://doc.rust-lang.org/nightly/rustc/platform-support/hexagon-unknown-linux-musl.html#target-maintainers)})

r? `@Amanieu`

`@rustbot` label +A-inline-assembly
(Currently there is no O-hexagon label...)
This commit is contained in:
Guillaume Gomez 2024-11-28 12:06:02 +01:00 committed by GitHub
commit 470c4f94e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 53 additions and 0 deletions

View file

@ -634,6 +634,9 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
@ -720,6 +723,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
cx.type_vector(cx.type_i64(), 2) cx.type_vector(cx.type_i64(), 2)
} }
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),

View file

@ -645,6 +645,7 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
| Arm(ArmInlineAsmRegClass::qreg_low4) => "x", | Arm(ArmInlineAsmRegClass::qreg_low4) => "x",
Arm(ArmInlineAsmRegClass::dreg) | Arm(ArmInlineAsmRegClass::qreg) => "w", Arm(ArmInlineAsmRegClass::dreg) | Arm(ArmInlineAsmRegClass::qreg) => "w",
Hexagon(HexagonInlineAsmRegClass::reg) => "r", Hexagon(HexagonInlineAsmRegClass::reg) => "r",
Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"),
LoongArch(LoongArchInlineAsmRegClass::reg) => "r", LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
LoongArch(LoongArchInlineAsmRegClass::freg) => "f", LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
Mips(MipsInlineAsmRegClass::reg) => "r", Mips(MipsInlineAsmRegClass::reg) => "r",
@ -813,6 +814,7 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
| Arm(ArmInlineAsmRegClass::qreg_low8) | Arm(ArmInlineAsmRegClass::qreg_low8)
| Arm(ArmInlineAsmRegClass::qreg_low4) => cx.type_vector(cx.type_i64(), 2), | Arm(ArmInlineAsmRegClass::qreg_low4) => cx.type_vector(cx.type_i64(), 2),
Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"),
LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),

View file

@ -7,6 +7,7 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
def_reg_class! { def_reg_class! {
Hexagon HexagonInlineAsmRegClass { Hexagon HexagonInlineAsmRegClass {
reg, reg,
preg,
} }
} }
@ -37,6 +38,7 @@ impl HexagonInlineAsmRegClass {
) -> &'static [(InlineAsmType, Option<Symbol>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg => types! { _: I8, I16, I32, F32; }, Self::reg => types! { _: I8, I16, I32, F32; },
Self::preg => &[],
} }
} }
} }
@ -71,6 +73,10 @@ def_regs! {
r26: reg = ["r26"], r26: reg = ["r26"],
r27: reg = ["r27"], r27: reg = ["r27"],
r28: reg = ["r28"], r28: reg = ["r28"],
p0: preg = ["p0"],
p1: preg = ["p1"],
p2: preg = ["p2"],
p3: preg = ["p3"],
#error = ["r19"] => #error = ["r19"] =>
"r19 is used internally by LLVM and cannot be used as an operand for inline asm", "r19 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["r29", "sp"] => #error = ["r29", "sp"] =>

View file

@ -30,6 +30,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| NVPTX | `reg32` | None\* | `r` | | NVPTX | `reg32` | None\* | `r` |
| NVPTX | `reg64` | None\* | `l` | | NVPTX | `reg64` | None\* | `l` |
| Hexagon | `reg` | `r[0-28]` | `r` | | Hexagon | `reg` | `r[0-28]` | `r` |
| Hexagon | `preg` | `p[0-3]` | Only clobbers |
| PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` | | PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` |
| PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` | | PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` |
| PowerPC | `freg` | `f[0-31]` | `f` | | PowerPC | `freg` | `f[0-31]` | `f` |
@ -70,6 +71,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` | | NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` |
| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | | Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| Hexagon | `preg` | N/A | Only clobbers |
| PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
| PowerPC | `freg` | None | `f32`, `f64` | | PowerPC | `freg` | None | `f32`, `f64` |

View file

@ -0,0 +1,37 @@
//@ revisions: hexagon
//@[hexagon] compile-flags: --target hexagon-unknown-linux-musl
//@[hexagon] needs-llvm-components: hexagon
//@ compile-flags: -Zmerge-functions=disabled
#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
#![no_core]
#[lang = "sized"]
trait Sized {}
#[rustc_builtin_macro]
macro_rules! asm {
() => {};
}
// CHECK-LABEL: @flags_clobber
// CHECK: call void asm sideeffect "", ""()
#[no_mangle]
pub unsafe fn flags_clobber() {
asm!("", options(nostack, nomem));
}
// CHECK-LABEL: @no_clobber
// CHECK: call void asm sideeffect "", ""()
#[no_mangle]
pub unsafe fn no_clobber() {
asm!("", options(nostack, nomem, preserves_flags));
}
// CHECK-LABEL: @p0_clobber
// CHECK: call void asm sideeffect "", "~{p0}"()
#[no_mangle]
pub unsafe fn p0_clobber() {
asm!("", out("p0") _, options(nostack, nomem, preserves_flags));
}