Skip to content

Commit 7033283

Browse files
committed
Fix target-cpu fpu features on Armv8-R.
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 thumbv7em-none-eabihf and thumbv8m.main-none-eabihf.
1 parent 5e3ede2 commit 7033283

File tree

5 files changed

+88
-6
lines changed

5 files changed

+88
-6
lines changed

compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ pub(crate) fn target() -> Target {
2121
linker: Some("rust-lld".into()),
2222
relocation_model: RelocModel::Static,
2323
panic_strategy: PanicStrategy::Abort,
24-
// The Cortex-R52 has two variants with respect to floating-point support:
25-
// 1. fp-armv8, SP-only, with 16 DP (32 SP) registers
26-
// 2. neon-fp-armv8, SP+DP, with 32 DP registers
27-
// Use the lesser of these two options as the default, as it will produce code
28-
// compatible with either variant.
24+
// Armv8-R requires a minimum set of floating-point features equivalent to:
25+
// fp-armv8, SP-only, with 16 DP (32 SP) registers
26+
// LLVM defines Armv8-R to include these features automatically.
27+
//
28+
// The Cortex-R52 supports these default features and optionally includes:
29+
// neon-fp-armv8, SP+DP, with 32 DP registers
2930
//
3031
// Reference:
3132
// Arm Cortex-R52 Processor Technical Reference Manual
3233
// - Chapter 15 Advanced SIMD and floating-point support
33-
features: "+fp-armv8,-fp64,-d32".into(),
3434
max_atomic_width: Some(64),
3535
emit_debug_gdb_scripts: false,
3636
// GCC defaults to 8 for arm-none here.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Cortex-M7 does not have Advanced SIMD, so don't check anything in vadd_f32_q.
2+
CHECK-LABEL: vadd_f32_q:
3+
4+
// Cortex-M7 enables double-precision.
5+
CHECK-LABEL: vadd_f64:
6+
CHECK: vadd.f64 d0, d0, d1
7+
CHECK: bx lr
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Cortex-M85 enables the Helium instructions.
2+
CHECK-LABEL: vadd_f32_q:
3+
CHECK: vld{{.*}}
4+
CHECK: vld{{.*}}
5+
CHECK: vadd.f32{{.*}}q
6+
CHECK: vst{{.*}} [r0]
7+
CHECK: bx lr
8+
9+
// Cortex-M85 enables double-precision.
10+
CHECK-LABEL: vadd_f64:
11+
CHECK: vadd.f64 d0, d0, d1
12+
CHECK: bx lr
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![no_std]
2+
3+
#[no_mangle]
4+
pub fn vadd_f32_q(x: &mut [f32; 4], y: &[f32; 4]) {
5+
for i in 0..4 {
6+
x[i] += y[i];
7+
}
8+
}
9+
10+
#[no_mangle]
11+
pub fn vadd_f64(x: f64, y: f64) -> f64 {
12+
x + y
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// This tests that target-cpu correctly enables additional floating-point features.
2+
3+
use run_make_support::{llvm_filecheck, llvm_objdump, rustc, static_lib_name};
4+
5+
struct TestCase {
6+
target: &'static str,
7+
cpu: &'static str,
8+
}
9+
10+
static CASES: &[TestCase] = &[
11+
TestCase { target: "thumbv7em-none-eabihf", cpu: "cortex-m7" },
12+
TestCase { target: "thumbv8m.main-none-eabihf", cpu: "cortex-m85" },
13+
];
14+
15+
fn main() {
16+
for case in CASES {
17+
let lib = static_lib_name(case.cpu);
18+
let checks = format!("{}.checks", case.cpu);
19+
20+
let rustc_command = || {
21+
let mut cmd = rustc();
22+
cmd.edition("2021")
23+
.target(case.target)
24+
.arg("-Copt-level=3")
25+
.crate_type("rlib")
26+
.input("lib.rs")
27+
.output(&lib);
28+
cmd
29+
};
30+
31+
let objdump_cmd = || {
32+
let mut cmd = llvm_objdump();
33+
cmd.arg("--arch-name=arm")
34+
.arg(format!("--mcpu={}", case.cpu))
35+
.disassemble()
36+
.input(&lib);
37+
cmd
38+
};
39+
40+
// First, run without target-cpu and confirm that it fails.
41+
rustc_command().run();
42+
let dis = objdump_cmd().run().stdout_utf8();
43+
llvm_filecheck().patterns(&checks).stdin_buf(dis).run_fail();
44+
45+
// Then, run with target-cpu and confirm that it succeeds.
46+
rustc_command().arg(format!("-Ctarget-cpu={}", case.cpu)).run();
47+
let dis = objdump_cmd().run().stdout_utf8();
48+
llvm_filecheck().patterns(&checks).stdin_buf(dis).run();
49+
}
50+
}

0 commit comments

Comments
 (0)