Skip to content

Commit 1df34e4

Browse files
committed
Fix target-cpu fpu features on Armv8-R.
This is a follow-up to #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 1df34e4

File tree

5 files changed

+93
-6
lines changed

5 files changed

+93
-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,55 @@
1+
// This tests that target-cpu correctly enables additional features for some Arm targets.
2+
// These targets were originally defined in such a way that features provided by target-cpu would be
3+
// disabled by the target spec itself. This was fixed in #123159.
4+
5+
// FIXME: This test should move to tests/assembly when building without #![no_core] in
6+
// that environment is possible, tracked by #130375.
7+
8+
use run_make_support::{llvm_filecheck, llvm_objdump, rustc, static_lib_name};
9+
10+
struct TestCase {
11+
target: &'static str,
12+
cpu: &'static str,
13+
}
14+
15+
static CASES: &[TestCase] = &[
16+
TestCase { target: "thumbv7em-none-eabihf", cpu: "cortex-m7" },
17+
TestCase { target: "thumbv8m.main-none-eabihf", cpu: "cortex-m85" },
18+
];
19+
20+
fn main() {
21+
for case in CASES {
22+
let lib = static_lib_name(case.cpu);
23+
let checks = format!("{}.checks", case.cpu);
24+
25+
let rustc_command = || {
26+
let mut cmd = rustc();
27+
cmd.edition("2021")
28+
.target(case.target)
29+
.arg("-Copt-level=3")
30+
.crate_type("rlib")
31+
.input("lib.rs")
32+
.output(&lib);
33+
cmd
34+
};
35+
36+
let objdump_command = || {
37+
let mut cmd = llvm_objdump();
38+
cmd.arg("--arch-name=arm")
39+
.arg(format!("--mcpu={}", case.cpu))
40+
.disassemble()
41+
.input(&lib);
42+
cmd
43+
};
44+
45+
// First, run without target-cpu and confirm that it fails.
46+
rustc_command().run();
47+
let dis = objdump_command().run().stdout_utf8();
48+
llvm_filecheck().patterns(&checks).stdin_buf(dis).run_fail();
49+
50+
// Then, run with target-cpu and confirm that it succeeds.
51+
rustc_command().arg(format!("-Ctarget-cpu={}", case.cpu)).run();
52+
let dis = objdump_command().run().stdout_utf8();
53+
llvm_filecheck().patterns(&checks).stdin_buf(dis).run();
54+
}
55+
}

0 commit comments

Comments
 (0)