Repository: rust
Issue: Illegal instructions generated for Arm Cortex-R5 processor when compiling code using floating-point operations
Labels: A-LLVM,O-Arm,P-medium,I-unsound,C-bug,I-miscompile

When targeting the Arm Cortex-R5 processor, rustc and llvm generate assembly containing floating-point instructions. These are not available on the Cortex-R5 (only on the Cortex-R5**F**) and cause the processor to halt.

### Details

For example, the following code:

```rust
fn add_s(a: f32, b: f32) -> f32 {
    a + b
}

fn add_d(a: f64, b: f64) -> f64 {
    a + b
}
```
compiled with flags `--target armv7r-none-eabi -C opt-level=3 -C target-cpu=cortex-r5` generates the assembly ([compiler explorer link](https://godbolt.org/z/W1Y5oo91G)):
```asm
add_s:
        vmov    s0, r1
        vmov    s2, r0
        vadd.f32        s0, s2, s0
        vmov    r0, s0
        bx      lr

add_d:
        vmov    d0, r2, r3
        vmov    d1, r0, r1
        vadd.f64        d0, d1, d0
        vmov    r0, r1, d0
        bx      lr
```
Note the `vadd.f32` and `vadd.f64` instructions, that are available on the Cortex-R5**F** which has an FPU, but that are illegal instructions on the Cortex-R5 without an FPU.

My expectation is that, using the target `armv7r-none-eabi` (rather than `armv7r-none-eabihf`) and the target CPU `cortex-r5` (rather than `cortex-r5f`), rustc and llvm would generate legal instructions for the processor, i.e. use software floating-point features rather than hard-float instructions.

### Relevant information

Original thread on URLO: [Unexpected codegen for Cortex-R5 without FPU](https://users.rust-lang.org/t/unexpected-codegen-for-cortex-r5-without-fpu/114658/1).

The upstream LLVM CPU model for cortex-r5 includes the flag FeatureVFP3_D16, which seems OK for the R5F but wrong for the R5. However, manually disabling that feature doesn't seem to help (see below). [Link to llvm repo at tag 18.1.7](https://github.com/llvm/llvm-project/blob/768118d1ad38bf13c545828f67bd6b474d61fc55/llvm/lib/Target/ARM/ARM.td#L1443-L1450).

Information from the ARM Cortex-R Series Programmer's Guide: [6.1.6. VFP in the Cortex-R processors](https://developer.arm.com/documentation/den0042/a/Floating-Point/Floating-point-basics-and-the-IEEE-754-standard/VFP-in-the-Cortex-R-processors).

### Things that do work

<details><summary>Skipping the target-cpu flag</summary>

Compiling the snippet above with flags `--target armv7r-none-eabi -C opt-level=3` generates:

```asm
add_s:
        push    {r11, lr}
        bl      __aeabi_fadd
        pop     {r11, pc}

add_d:
        push    {r11, lr}
        bl      __aeabi_dadd
        pop     {r11, pc}
```

</details>

<details><summary>Adding the soft-float target feature</summary>

Compiling the snippet above with flags `--target armv7r-none-eabi -C opt-level=3 -C target-cpu=cortex-r5 -C target-feature=+soft-float` generates:

```asm
add_s:
        push    {r11, lr}
        bl      __aeabi_fadd
        pop     {r11, pc}

add_d:
        push    {r11, lr}
        bl      __aeabi_dadd
        pop     {r11, pc}
```


However, rustc generates the warning:

```
warning: unknown and unstable feature specified for `-Ctarget-feature`: `soft-float`
  |
  = note: it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future
  = help: consider filing a feature request

warning: 1 warning emitted
```
</details>

### Things that don't work

<details><summary>Removing the vfp3d16 target feature</summary>

Compiling the snippet above with flags `--target armv7r-none-eabi -C opt-level=3 -C target-cpu=cortex-r5 -C target-feature=-vfp3d16` generates:

```asm
add_s:
        vmov    s0, r1
        vmov    s2, r0
        vadd.f32        s0, s2, s0
        vmov    r0, s0
        bx      lr

add_d:
        vmov    d0, r2, r3
        vmov    d1, r0, r1
        vadd.f64        d0, d1, d0
        vmov    r0, r1, d0
        bx      lr
```
</details>

### Meta
I've tested both stable and nightly toolchains, with same results.

`rustc --version --verbose`:
```
rustc 1.80.0 (051478957 2024-07-21)
binary: rustc
commit-hash: 051478957371ee0084a7c0913941d2a8c4757bb9
commit-date: 2024-07-21
host: x86_64-unknown-linux-gnu
release: 1.80.0
LLVM version: 18.1.7
```