Skip to content

Commit

Permalink
Add -Z small-data-threshold
Browse files Browse the repository at this point in the history
This flag allows specifying the threshold size above which LLVM should
not consider placing small objects in a .sdata or .sbss section.
  • Loading branch information
paulmenage committed Dec 12, 2023
1 parent 5b8bc56 commit 4660911
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 0 deletions.
13 changes: 13 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,19 @@ pub unsafe fn create_module<'ll>(
)
}

if let Some(threshold) = sess.opts.unstable_opts.small_data_threshold {
// Set up the small-data optimization limit for architectures that use
// an LLVM module flag to control this.
if sess.target.arch.starts_with("riscv") {
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"SmallDataLimit\0".as_ptr().cast(),
threshold as u32,
)
}
}

// Insert `llvm.ident` metadata.
//
// On the wasm targets it will get hooked up to the "producer" sections
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,24 @@ unsafe fn configure_llvm(sess: &Session) {
for arg in sess_args {
add(&(*arg), true);
}

if let Some(threshold) = sess.opts.unstable_opts.small_data_threshold {
// Set up the small-data optimization limit for architectures that use
// an LLVM argument to control this.
match sess.target.arch.as_ref() {
"hexagon" => add(&format!("--hexagon-small-data-threshold={threshold}"), false),
// m68k accepts the --m68k-ssection-threshold argument but then
// ignores it, so this currently has no effect on m68k
"m68k" => add(&format!("--m68k-ssection-threshold={threshold}"), false),
// There's currently no rustc support for the Lanai architecture, so this is untested
"lanai" => add(&format!("--lanai-ssection-threshold={threshold}"), false),
arch @ _ => {
if arch.starts_with("mips") {
add(&format!("--mips-ssection-threshold={threshold}"), false);
}
}
}
}
}

if sess.opts.unstable_opts.llvm_time_trace {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(share_generics, Some(true));
tracked!(show_span, Some(String::from("abc")));
tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
tracked!(small_data_threshold, Some(16));
tracked!(split_lto_unit, Some(true));
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
tracked!(stack_protector, StackProtector::All);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1857,6 +1857,8 @@ written to standard error output)"),
simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
to rust's source base directory. only meant for testing purposes"),
small_data_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
"Set the threshold for objects to be stored in a \"small data\" section"),
span_debug: bool = (false, parse_bool, [UNTRACKED],
"forward proc_macro::Span's `Debug` impl to `Span`"),
/// o/w tests have closure@path
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# `small-data-threshold`

-----------------------

This flag controls the maximum static variable size that may be included in the
"small data sections" (.sdata, .sbss) supported by some architectures (RISCV,
MIPS, M68K, Hexagon). Can be set to `0` to disable the use of small data
sections.
92 changes: 92 additions & 0 deletions tests/assembly/small_data_threshold.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Test for -Z small_data_threshold=...
// revisions: RISCV MIPS HEXAGON M68K
// assembly-output: emit-asm
// compile-flags: -Z small_data_threshold=4
// [RISCV] compile-flags: --target=riscv32im-unknown-none-elf
// [RISCV] needs-llvm-components: riscv
// [MIPS] compile-flags: --target=mips-unknown-linux-uclibc -C relocation-model=static
// [MIPS] compile-flags: -C llvm-args=-mgpopt -C llvm-args=-mlocal-sdata
// [MIPS] compile-flags: -C target-feature=+noabicalls
// [MIPS] needs-llvm-components: mips
// [HEXAGON] compile-flags: --target=hexagon-unknown-linux-musl -C target-feature=+small-data
// [HEXAGON] compile-flags: -C llvm-args=--hexagon-statics-in-small-data
// [HEXAGON] needs-llvm-components: hexagon
// [M68K] compile-flags: --target=m68k-unknown-linux-gnu
// [M68K] needs-llvm-components: m68k

#![feature(no_core, lang_items)]
#![no_std]
#![no_core]
#![crate_type = "lib"]

#[lang = "sized"]
trait Sized {}

#[lang = "drop_in_place"]
fn drop_in_place<T>(_: *mut T) {}

#[used]
#[no_mangle]
// U is below the threshold, should be in sdata
static mut U: u16 = 123;

#[used]
#[no_mangle]
// V is below the threshold, should be in sbss
static mut V: u16 = 0;

#[used]
#[no_mangle]
// W is at the threshold, should be in sdata
static mut W: u32 = 123;

#[used]
#[no_mangle]
// X is at the threshold, should be in sbss
static mut X: u32 = 0;

#[used]
#[no_mangle]
// Y is over the threshold, should be in its own .data section
static mut Y: u64 = 123;

#[used]
#[no_mangle]
/// Z is over the threshold, should be in its own .bss section
static mut Z: u64 = 0;

// Currently, only MIPS and RISCV successfully put any objects in the small data
// sections so the U/V/W/X tests are skipped on Hexagon and M68K

// RISCV: .section .sdata,
// RISCV-NOT: .section
// RISCV: U:
// RISCV: .section .sbss
// RISV-NOT: .section
// RISCV: V:
// RISCV .section .sdata
// RISV-NOT: .section
// RISCV: W:
// RISCV: .section .sbss
// RISV-NOT: .section
// RISCV: X:

// MIPS: .section .sdata,
// MIPS-NOT: .section
// MIPS: U:
// MIPS: .section .sbss
// RISV-NOT: .section
// MIPS: V:
// MIPS .section .sdata
// RISV-NOT: .section
// MIPS: W:
// MIPS: .section .sbss
// RISV-NOT: .section
// MIPS: X:

// CHECK: .section .data.Y,
// CHECK-NOT: .section
// CHECK: Y:
// CHECK: .section .bss.Z,
// CHECK-NOT: .section
// CHECK: Z:

0 comments on commit 4660911

Please sign in to comment.