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

Many Arm microcontoller target feature flags are missing #130988

Open
6 tasks
thejpster opened this issue Sep 28, 2024 · 15 comments
Open
6 tasks

Many Arm microcontoller target feature flags are missing #130988

thejpster opened this issue Sep 28, 2024 · 15 comments
Labels
A-ABI Area: Concerning the application binary interface (ABI) A-target-feature Area: Enabling/disabling target features like AVX, Neon, etc. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@thejpster
Copy link
Contributor

thejpster commented Sep 28, 2024

@RalfJung asked me to open an issue listing all the useful Arm microcontroller feature flags that are currently entirely unsupported by Rust, not even unstably.

These are all listed at https://doc.rust-lang.org/nightly/rustc/platform-support/arm-none-eabi.html and the sub-pages, as modified by #130987.

Selecting a CPU with -C target-cpu=xxx causes LLVM to enable all the optional features of that type of CPU. However, sometimes CPUs are sold without certain features (e.g. you can get a Cortex-M4 either with or without an FPU). So, we use these -C target-feature=... flags to disable some of the things that LLVM over-enthusiastically enabled for us when we selected a target-cpu. If you don't select a target-cpu, you don't need these flags because by default, only the architecture's baseline features are enabled and you never want to turn those off.

  • -fpregs - don't emit FPU instructions
  • -fp64 - don't emit double precision FPU instructions
  • -mve - don't emit Float or Integer M-Profile Vector Extension instructions
  • -mve.fp - don't emit Float M-Profile Vector Extension instructions
  • -dsp - don't emit DSP instructions
  • +mve - do emit Integer M-Profile Vector Extension instructions (used with -fpregs because MVE uses registers shared with the FPU and those registers are present if you have Integer MVE but no FPU)

These are alongside the following target CPUs (-C target-cpu=...):

  • cortex-m0
  • cortex-m0plus
  • cortex-m3
  • cortex-m4
  • cortex-m7
  • cortex-m33
  • cortex-m35p
  • cortex-m55
  • cortex-m85

If you don't want to use -C target-cpu... then the following additional flags can enable certain features. However, these aren't currently mentioned in the documentation (except +mve because it's listed above).

  • +mve - M-Profile Vector Extensions (integer)
  • +mve.fp - M-Profile Vector Extensions (floating point)
  • +dsp - DSP extensions
  • +fp-armv8d16sp - single precision FPU for Armv8-M
  • +fp-armv8d16 - double precision FPU for Armv8-M
  • +vfp4d16sp - single precision FPU for Armv7E-M
  • +vfp4d16 - double precision FPU for Armv7E-M
@thejpster thejpster added the C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC label Sep 28, 2024
@thejpster
Copy link
Contributor Author

thejpster commented Sep 28, 2024

I find this example code useful in Godbolt for checking what the flags do and don't do:

#![no_std]

#[no_mangle]
pub fn f32_add(x: [f32; 4], y: [f32; 4]) -> [f32; 4] {
    [
        (x[0] * 2.0) + y[0],
        (x[1] * 2.0) + y[1],
        (x[2] * 2.0) + y[2],
        (x[3] * 2.0) + y[3],
    ]
}

#[no_mangle]
pub fn f64_add(x: [f64; 4], y: [f64; 4]) -> [f64; 4] {
    [
        (x[0] * 2.0) + y[0],
        (x[1] * 2.0) + y[1],
        (x[2] * 2.0) + y[2],
        (x[3] * 2.0) + y[3],
    ]
}

#[no_mangle]
pub fn i32_add(x: [i32; 4], y: [i32; 4]) -> [i32; 4] {
    [
        (x[0] * 2) + y[0],
        (x[1] * 2) + y[1],
        (x[2] * 2) + y[2],
        (x[3] * 2) + y[3],
    ]
}

At opt-level=3 it will auto-vectorise on CPUs with MVE support.

@RalfJung
Copy link
Member

Cc @rust-lang/compiler
(not sure which team is mainly in charge of target features, t-compiler or t-lang?)

None of these features are currently listed as known ARM features in rustc, so they all cause a warning. And yet our docs recommend people to use them. So that's clearly not great.

fpregs is particularly tricky since disabling it on an eabihf target is unsound as it changes the float ABI. On eabi targets it's fine because those have +soft-float anyway, which forces the soft-float ABI. So we'll need to stabilize this in a way where particular targets opt-in to supporting this feature, or something like that.

@jieyouxu jieyouxu added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. I-compiler-nominated Nominated for discussion during a compiler team meeting. A-target-feature Area: Enabling/disabling target features like AVX, Neon, etc. A-ABI Area: Concerning the application binary interface (ABI) labels Sep 28, 2024
@jieyouxu
Copy link
Member

Nominating for T-compiler triage meeting next week.

cc https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/stabilizing.20compiler.20flags.20for.20Rust-for-Linux. T-compiler probably wants to have a dedicated design meeting for target-features, target-cpu, target specs and how they are tracked in a dep graph.

@RalfJung
Copy link
Member

RalfJung commented Sep 28, 2024

The avx512 mess would also fall in that general category (but is off-topic here).

EDIT: and #131058, as well.

@thejpster
Copy link
Contributor Author

I wrote up a blog looking into what some of these flags do - https://www.thejpster.org.uk/blog/blog-2024-09-29/.

@apiraino
Copy link
Contributor

apiraino commented Oct 3, 2024

T-compiler visited this during the triage meeting, will probably need a design meeting (about the recent discussions around target-feature and ABI).

@rustbot label -I-compiler-nominated

@rustbot rustbot removed the I-compiler-nominated Nominated for discussion during a compiler team meeting. label Oct 3, 2024
@thejpster
Copy link
Contributor Author

I learned about do-while-loop-with-tail-predication and was so impressed I wrote up a second blog post: https://thejpster.org.uk/blog/blog-2024-10-03/

You really want compiler-builtin's memcpy and memset compiled with MVE, if you possibly can.

@RalfJung RalfJung removed the C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC label Oct 30, 2024
@RalfJung RalfJung changed the title Tracking Issue for Arm microcontoller feature flags Many Arm microcontoller feature flags are missing Oct 30, 2024
@RalfJung
Copy link
Member

This is not really a tracking issue since there's no unstable implementation being tracked here. Currently, these flags are just wholly unsupported by Rust, and we show a corresponding warning. So I updated the docs and labels accordingly.

Adding support for fpreg is blocked on #129884 and some further rework, also see #132351.

@thejpster does any of the other flags affect ABI, i.e. can toggling it on or off change which registers are being used to pass function arguments?

@thejpster
Copy link
Contributor Author

Not to my knowledge, but you should ask the Embedded Devices Cortex-M group too.

@RalfJung
Copy link
Member

How does one contact that group?
(I found this one but that seems to be ARM in general, not embedded/microcontollers.)

@jieyouxu
Copy link
Member

jieyouxu commented Oct 30, 2024

How does one contact that group? (I found this one but that seems to be ARM in general, not embedded/microcontollers.)

Maybe https://github.com/rust-embedded/wg?
Specifically, https://github.com/rust-embedded/wg#the-cortex-m-team

@thejpster
Copy link
Contributor Author

I've asked via the Rust Embedded Matrix room. I don't think have a ping group for just that sub-group but they probably should.

@RalfJung
Copy link
Member

Cc @adamgreig @therealprof

@adamgreig
Copy link
Member

I believe the only relevant variation to the standard Arm ABI for these platforms is around VFP/SIMD register arguments, but I'm not completely confident on which flags cause LLVM to use it. It seems like only fpregs and soft-float do, but I would have expected that enabling mve or mve.fp could also enable passing (vector) arguments using the VFP registers. I don't believe fp64, dsp, or any of the specific FPU flags would change it.

If Rust had support for RWPI that also changes the ABI, but it (and LLVM) currently doesn't.

@thejpster
Copy link
Contributor Author

I don't think turning on MVE changes the ABI, in the same way that turning on the FPU doesn't change the ABI. I'm pretty sure the ABI (i.e. use of VFP registers in the calling convention) is controlled by a separate flag.

But someone could do some tests in Godbolt to show this.

@RalfJung RalfJung changed the title Many Arm microcontoller feature flags are missing Many Arm microcontoller target feature flags are missing Nov 16, 2024
bors added a commit to rust-lang-ci/rust that referenced this issue Dec 13, 2024
…s, r=workingjubilee

forbid toggling x87 and fpregs on hard-float targets

Part of rust-lang#116344, follow-up to rust-lang#129884:

The `x87`  target feature on x86 and the `fpregs` target feature on ARM must not be disabled on a hardfloat target, as that would change the float ABI. However, *enabling* `fpregs` on ARM is [explicitly requested](rust-lang#130988) as it seems to be useful. Therefore, we need to refine the distinction of "forbidden" target features and "allowed" target features: all (un)stable target features can determine on a per-target basis whether they should be allowed to be toggled or not. `fpregs` then checks whether the current target has the `soft-float` feature, and if yes, `fpregs` is permitted -- otherwise, it is not. (Same for `x87` on x86).

Also fixes rust-lang#132351. Since `fpregs` and `x87` can be enabled on some builds and disabled on others, it would make sense that one can query it via `cfg`. Therefore, I made them behave in `cfg` like any other unstable target feature.

The first commit prepares the infrastructure, but does not change behavior. The second commit then wires up `fpregs` and `x87` with that new infrastructure.

r? `@workingjubilee`
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Dec 15, 2024
…ingjubilee

forbid toggling x87 and fpregs on hard-float targets

Part of rust-lang/rust#116344, follow-up to rust-lang/rust#129884:

The `x87`  target feature on x86 and the `fpregs` target feature on ARM must not be disabled on a hardfloat target, as that would change the float ABI. However, *enabling* `fpregs` on ARM is [explicitly requested](rust-lang/rust#130988) as it seems to be useful. Therefore, we need to refine the distinction of "forbidden" target features and "allowed" target features: all (un)stable target features can determine on a per-target basis whether they should be allowed to be toggled or not. `fpregs` then checks whether the current target has the `soft-float` feature, and if yes, `fpregs` is permitted -- otherwise, it is not. (Same for `x87` on x86).

Also fixes rust-lang/rust#132351. Since `fpregs` and `x87` can be enabled on some builds and disabled on others, it would make sense that one can query it via `cfg`. Therefore, I made them behave in `cfg` like any other unstable target feature.

The first commit prepares the infrastructure, but does not change behavior. The second commit then wires up `fpregs` and `x87` with that new infrastructure.

r? `@workingjubilee`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ABI Area: Concerning the application binary interface (ABI) A-target-feature Area: Enabling/disabling target features like AVX, Neon, etc. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants