Skip to content

Commit

Permalink
Fix target-cpu fpu features on Armv8-R.
Browse files Browse the repository at this point in the history
This is a follow-up to rust-lang#123159, but applied to Armv8-R.

This required llvm/llvm-project#88287 to work
properly. Now that this change exists in rustc's llvm, we can fix
Armv8-R's default fpu features. In Armv8-R's case, the default features
from LLVM for floating-point are sufficient, because there is no
integer-only variant of this architecture.

Add a run-make test that an appropriate target-cpu enables
double-precision and neon for thumbv8m.main-none-eabihf and
armv8r-none-eabihf.
  • Loading branch information
chrisnc committed Sep 15, 2024
1 parent 5e3ede2 commit 4855da1
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 6 deletions.
12 changes: 6 additions & 6 deletions compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ pub(crate) fn target() -> Target {
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
// The Cortex-R52 has two variants with respect to floating-point support:
// 1. fp-armv8, SP-only, with 16 DP (32 SP) registers
// 2. neon-fp-armv8, SP+DP, with 32 DP registers
// Use the lesser of these two options as the default, as it will produce code
// compatible with either variant.
// Armv8-R requires a minimum set of floating-point features equivalent to:
// fp-armv8, SP-only, with 16 DP (32 SP) registers
// LLVM defines Armv8-R to include these features automatically.
//
// The Cortex-R52 supports these default features and optionally includes:
// neon-fp-armv8, SP+DP, with 32 DP registers
//
// Reference:
// Arm Cortex-R52 Processor Technical Reference Manual
// - Chapter 15 Advanced SIMD and floating-point support
features: "+fp-armv8,-fp64,-d32".into(),
max_atomic_width: Some(64),
emit_debug_gdb_scripts: false,
// GCC defaults to 8 for arm-none here.
Expand Down
10 changes: 10 additions & 0 deletions tests/run-make/arm-target-cpu-fp/cortex-m85.checks
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CHECK-LABEL: vadd_q:
CHECK: vld{{.*}}
CHECK: vld{{.*}}
CHECK: vadd.f32{{.*}}q
CHECK: vst{{.*}} [r0]
CHECK: bx lr

CHECK-LABEL: vadd_f64:
CHECK: vadd.f64 d0, d0, d1
CHECK: bx lr
10 changes: 10 additions & 0 deletions tests/run-make/arm-target-cpu-fp/cortex-r52.checks
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CHECK-LABEL: vadd_q:
CHECK: vld{{.*}}
CHECK: vld{{.*}}
CHECK: vadd.f32{{.*}}q
CHECK: vst{{.*}} [r0]
CHECK: bx lr

CHECK-LABEL: vadd_f64:
CHECK: vadd.f64 d0, d0, d1
CHECK: bx lr
13 changes: 13 additions & 0 deletions tests/run-make/arm-target-cpu-fp/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![no_std]

#[no_mangle]
pub fn vadd_q(x: &mut [f32; 4], y: &[f32; 4]) {
for i in 0..4 {
x[i] += y[i];
}
}

#[no_mangle]
pub fn vadd_f64(x: f64, y: f64) -> f64 {
x + y
}
50 changes: 50 additions & 0 deletions tests/run-make/arm-target-cpu-fp/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// This tests that target-cpu correctly enables additional floating-point features.

use run_make_support::{llvm_filecheck, llvm_objdump, rustc, static_lib_name};

struct TestCase {
target: &'static str,
cpu: &'static str,
}

static CASES: &[TestCase] = &[
TestCase { target: "thumbv8m.main-none-eabihf", cpu: "cortex-m85" },
TestCase { target: "armv8r-none-eabihf", cpu: "cortex-r52" },
];

fn main() {
for case in CASES {
let lib = static_lib_name(case.cpu);
let checks = format!("{}.checks", case.cpu);

let rustc_command = || {
let mut cmd = rustc();
cmd.edition("2021")
.arg(format!("--target={}", case.target))
.arg("-Copt-level=3")
.crate_type("rlib")
.input("lib.rs")
.output(&lib);
cmd
};

let objdump_cmd = || {
let mut cmd = llvm_objdump();
cmd.arg("--arch-name=arm")
.arg(format!("--mcpu={}", case.cpu))
.disassemble()
.input(&lib);
cmd
};

// First, run without target-cpu and confirm that it fails.
rustc_command().run();
let dis = objdump_cmd().run().stdout_utf8();
llvm_filecheck().patterns(&checks).stdin_buf(dis).run_fail();

// Then, run with target-cpu and confirm that it succeeds.
rustc_command().arg(format!("-Ctarget-cpu={}", case.cpu)).run();
let dis = objdump_cmd().run().stdout_utf8();
llvm_filecheck().patterns(&checks).stdin_buf(dis).run();
}
}

0 comments on commit 4855da1

Please sign in to comment.