Skip to content

Commit 54eada2

Browse files
committed
Add -Z small-data-threshold
This flag allows specifying the threshold size above which LLVM should not consider placing small objects in a .sdata or .sbss section.
1 parent 50be229 commit 54eada2

File tree

6 files changed

+129
-0
lines changed

6 files changed

+129
-0
lines changed

compiler/rustc_codegen_llvm/src/context.rs

+13
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,19 @@ pub unsafe fn create_module<'ll>(
351351
);
352352
}
353353

354+
if let Some(threshold) = sess.opts.unstable_opts.small_data_threshold {
355+
// Set up the small-data optimization limit for architectures that use
356+
// an LLVM module flag to control this.
357+
if sess.target.arch.starts_with("riscv") {
358+
llvm::LLVMRustAddModuleFlag(
359+
llmod,
360+
llvm::LLVMModFlagBehavior::Error,
361+
"SmallDataLimit\0".as_ptr().cast(),
362+
threshold as u32,
363+
)
364+
}
365+
}
366+
354367
// Insert `llvm.ident` metadata.
355368
//
356369
// On the wasm targets it will get hooked up to the "producer" sections

compiler/rustc_codegen_llvm/src/llvm_util.rs

+18
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,24 @@ unsafe fn configure_llvm(sess: &Session) {
118118
for arg in sess_args {
119119
add(&(*arg), true);
120120
}
121+
122+
if let Some(threshold) = sess.opts.unstable_opts.small_data_threshold {
123+
// Set up the small-data optimization limit for architectures that use
124+
// an LLVM argument to control this.
125+
match sess.target.arch.as_ref() {
126+
"hexagon" => add(&format!("--hexagon-small-data-threshold={threshold}"), false),
127+
// m68k accepts the --m68k-ssection-threshold argument but then
128+
// ignores it, so this currently has no effect on m68k
129+
"m68k" => add(&format!("--m68k-ssection-threshold={threshold}"), false),
130+
// There's currently no rustc support for the Lanai architecture, so this is untested
131+
"lanai" => add(&format!("--lanai-ssection-threshold={threshold}"), false),
132+
arch @ _ => {
133+
if arch.starts_with("mips") {
134+
add(&format!("--mips-ssection-threshold={threshold}"), false);
135+
}
136+
}
137+
}
138+
}
121139
}
122140

123141
if sess.opts.unstable_opts.llvm_time_trace {

compiler/rustc_interface/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ fn test_codegen_options_tracking_hash() {
609609
tracked!(profile_generate, SwitchWithOptPath::Enabled(None));
610610
tracked!(profile_use, Some(PathBuf::from("abc")));
611611
tracked!(relocation_model, Some(RelocModel::Pic));
612+
tracked!(small_data_threshold, Some(16));
612613
tracked!(soft_float, true);
613614
tracked!(split_debuginfo, Some(SplitDebuginfo::Packed));
614615
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));

compiler/rustc_session/src/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1792,6 +1792,8 @@ written to standard error output)"),
17921792
simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
17931793
"simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
17941794
to rust's source base directory. only meant for testing purposes"),
1795+
small_data_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
1796+
"Set the threshold for objects to be stored in a \"small data\" section"),
17951797
span_debug: bool = (false, parse_bool, [UNTRACKED],
17961798
"forward proc_macro::Span's `Debug` impl to `Span`"),
17971799
/// o/w tests have closure@path
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# `small-data-threshold`
2+
3+
-----------------------
4+
5+
This flag controls the maximum static variable size that may be included in the
6+
"small data sections" (.sdata, .sbss) supported by some architectures (RISCV,
7+
MIPS, M68K, Hexagon). Can be set to `0` to disable the use of small data
8+
sections.
+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Test for -Z small_data_threshold=...
2+
// revisions: RISCV MIPS HEXAGON M68K
3+
// assembly-output: emit-asm
4+
// compile-flags: -Z small_data_threshold=4
5+
// [RISCV] compile-flags:--target=riscv32im-unknown-none-elf
6+
// [MIPS] compile-flags:--target=mips-unknown-linux-uclibc -C relocation-model=static
7+
// [MIPS] compile-flags:-C llvm-args=-mgpopt -C llvm-args=-mlocal-sdata -C target-feature=+noabicalls
8+
// [HEXAGON] compile-flags:--target=hexagon-unknown-linux-musl -C target-feature=+small-data
9+
// [HEXAGON] compile-flags:-C llvm-args=--hexagon-statics-in-small-data
10+
// [M68K] compile-flags:--target=m68k-unknown-linux-gnu
11+
12+
#![feature(no_core, lang_items)]
13+
#![no_std]
14+
#![no_core]
15+
#![crate_type = "lib"]
16+
17+
#[lang = "sized"]
18+
trait Sized {}
19+
20+
#[lang = "drop_in_place"]
21+
fn drop_in_place<T>(_: *mut T) {}
22+
23+
#[used]
24+
#[no_mangle]
25+
// U is below the threshold, should be in sdata
26+
static mut U: u16 = 123;
27+
28+
#[used]
29+
#[no_mangle]
30+
// V is below the threshold, should be in sbss
31+
static mut V: u16 = 0;
32+
33+
#[used]
34+
#[no_mangle]
35+
// W is at the threshold, should be in sdata
36+
static mut W: u32 = 123;
37+
38+
#[used]
39+
#[no_mangle]
40+
// X is at the threshold, should be in sbss
41+
static mut X: u32 = 0;
42+
43+
#[used]
44+
#[no_mangle]
45+
// Y is over the threshold, should be in its own .data section
46+
static mut Y: u64 = 123;
47+
48+
#[used]
49+
#[no_mangle]
50+
/// Z is over the threshold, should be in its own .bss section
51+
static mut Z: u64 = 0;
52+
53+
// Currently, only MIPS and RISCV successfully put any objects in the small data
54+
// sections so the U/V/W/X tests are skipped on MIPS/Hexagon/M68K
55+
56+
// RISCV: .section .sdata,
57+
// RISCV-NOT: .section
58+
// RISCV: U:
59+
// RISCV: .section .sbss
60+
// RISV-NOT: .section
61+
// RISCV: V:
62+
// RISCV .section .sdata
63+
// RISV-NOT: .section
64+
// RISCV: W:
65+
// RISCV: .section .sbss
66+
// RISV-NOT: .section
67+
// RISCV: X:
68+
69+
// MIPS: .section .sdata,
70+
// MIPS-NOT: .section
71+
// MIPS: U:
72+
// MIPS: .section .sbss
73+
// RISV-NOT: .section
74+
// MIPS: V:
75+
// MIPS .section .sdata
76+
// RISV-NOT: .section
77+
// MIPS: W:
78+
// MIPS: .section .sbss
79+
// RISV-NOT: .section
80+
// MIPS: X:
81+
82+
// CHECK: .section .data.Y,
83+
// CHECK-NOT: .section
84+
// CHECK: Y:
85+
// CHECK: .section .bss.Z,
86+
// CHECK-NOT: .section
87+
// CHECK: Z:

0 commit comments

Comments
 (0)