Skip to content

Commit d17dd8b

Browse files
Auto merge of #136840 - Flakebi:linker-plugin-lto-fat, r=<try>
Fix linker-plugin-lto only doing thin lto try-job: *-gnu-debug
2 parents 32e7a4b + 6a1ed2f commit d17dd8b

File tree

11 files changed

+187
-25
lines changed

11 files changed

+187
-25
lines changed

compiler/rustc_codegen_llvm/src/back/write.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ pub(crate) fn codegen(
838838
"LLVM_module_codegen_make_bitcode",
839839
&*module.name,
840840
);
841-
ThinBuffer::new(llmod, config.emit_thin_lto, false)
841+
ThinBuffer::new(llmod, cgcx.lto != Lto::Fat && config.emit_thin_lto, false)
842842
};
843843
let data = thin.data();
844844
let _timer = cgcx

src/tools/run-make-support/src/external_deps/llvm.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ pub fn llvm_pdbutil() -> LlvmPdbutil {
6060
LlvmPdbutil::new()
6161
}
6262

63+
/// Construct a new `llvm-as` invocation. This assumes that `llvm-as` is available
64+
/// at `$LLVM_BIN_DIR/llvm-as`.
65+
pub fn llvm_as() -> LlvmAs {
66+
LlvmAs::new()
67+
}
68+
6369
/// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available
6470
/// at `$LLVM_BIN_DIR/llvm-dis`.
6571
pub fn llvm_dis() -> LlvmDis {
@@ -135,6 +141,13 @@ pub struct LlvmPdbutil {
135141
cmd: Command,
136142
}
137143

144+
/// A `llvm-as` invocation builder.
145+
#[derive(Debug)]
146+
#[must_use]
147+
pub struct LlvmAs {
148+
cmd: Command,
149+
}
150+
138151
/// A `llvm-dis` invocation builder.
139152
#[derive(Debug)]
140153
#[must_use]
@@ -158,6 +171,7 @@ crate::macros::impl_common_helpers!(LlvmNm);
158171
crate::macros::impl_common_helpers!(LlvmBcanalyzer);
159172
crate::macros::impl_common_helpers!(LlvmDwarfdump);
160173
crate::macros::impl_common_helpers!(LlvmPdbutil);
174+
crate::macros::impl_common_helpers!(LlvmAs);
161175
crate::macros::impl_common_helpers!(LlvmDis);
162176
crate::macros::impl_common_helpers!(LlvmObjcopy);
163177

@@ -441,6 +455,22 @@ impl LlvmObjcopy {
441455
}
442456
}
443457

458+
impl LlvmAs {
459+
/// Construct a new `llvm-as` invocation. This assumes that `llvm-as` is available
460+
/// at `$LLVM_BIN_DIR/llvm-as`.
461+
pub fn new() -> Self {
462+
let llvm_as = llvm_bin_dir().join("llvm-as");
463+
let cmd = Command::new(llvm_as);
464+
Self { cmd }
465+
}
466+
467+
/// Provide an input file.
468+
pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
469+
self.cmd.arg(path.as_ref());
470+
self
471+
}
472+
}
473+
444474
impl LlvmDis {
445475
/// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available
446476
/// at `$LLVM_BIN_DIR/llvm-dis`.

src/tools/run-make-support/src/external_deps/rustc.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@ impl Rustc {
173173
self
174174
}
175175

176+
/// This flag enables LTO in the specified form.
177+
pub fn lto(&mut self, option: &str) -> &mut Self {
178+
self.cmd.arg(format!("-Clto={option}"));
179+
self
180+
}
181+
176182
/// This flag defers LTO optimizations to the linker.
177183
pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
178184
self.cmd.arg(format!("-Clinker-plugin-lto={option}"));

src/tools/run-make-support/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ pub use crate::external_deps::clang::{Clang, clang};
6363
pub use crate::external_deps::htmldocck::htmldocck;
6464
pub use crate::external_deps::llvm::{
6565
self, LlvmAr, LlvmBcanalyzer, LlvmDis, LlvmDwarfdump, LlvmFilecheck, LlvmNm, LlvmObjcopy,
66-
LlvmObjdump, LlvmProfdata, LlvmReadobj, llvm_ar, llvm_bcanalyzer, llvm_dis, llvm_dwarfdump,
67-
llvm_filecheck, llvm_nm, llvm_objcopy, llvm_objdump, llvm_profdata, llvm_readobj,
66+
LlvmObjdump, LlvmProfdata, LlvmReadobj, llvm_ar, llvm_as, llvm_bcanalyzer, llvm_dis,
67+
llvm_dwarfdump, llvm_filecheck, llvm_nm, llvm_objcopy, llvm_objdump, llvm_profdata,
68+
llvm_readobj,
6869
};
6970
pub use crate::external_deps::python::python_command;
7071
pub use crate::external_deps::rustc::{self, Rustc, bare_rustc, rustc, rustc_path};

tests/run-make/cross-lang-lto-clang/rmake.rs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,53 +28,68 @@ static C_NEVER_INLINED_PATTERN: &'static str = "bl.*<c_never_inlined>";
2828
static C_NEVER_INLINED_PATTERN: &'static str = "call.*c_never_inlined";
2929

3030
fn main() {
31+
test_lto(false);
32+
test_lto(true);
33+
}
34+
35+
fn test_lto(fat_lto: bool) {
36+
let lto = if fat_lto { "fat" } else { "thin" };
37+
let clang_lto = if fat_lto { "full" } else { "thin" };
38+
println!("Running {lto} lto");
39+
3140
rustc()
41+
.lto(lto)
3242
.linker_plugin_lto("on")
3343
.output(static_lib_name("rustlib-xlto"))
3444
.opt_level("2")
3545
.codegen_units(1)
3646
.input("rustlib.rs")
3747
.run();
3848
clang()
39-
.lto("thin")
49+
.lto(clang_lto)
4050
.use_ld("lld")
4151
.arg("-lrustlib-xlto")
4252
.out_exe("cmain")
4353
.input("cmain.c")
4454
.arg("-O3")
4555
.run();
56+
57+
let dump = llvm_objdump().disassemble().input("cmain").run();
4658
// Make sure we don't find a call instruction to the function we expect to
4759
// always be inlined.
48-
llvm_objdump()
49-
.disassemble()
50-
.input("cmain")
51-
.run()
52-
.assert_stdout_not_contains_regex(RUST_ALWAYS_INLINED_PATTERN);
60+
dump.assert_stdout_not_contains_regex(RUST_ALWAYS_INLINED_PATTERN);
5361
// As a sanity check, make sure we do find a call instruction to a
5462
// non-inlined function
55-
llvm_objdump()
56-
.disassemble()
57-
.input("cmain")
58-
.run()
59-
.assert_stdout_contains_regex(RUST_NEVER_INLINED_PATTERN);
60-
clang().input("clib.c").lto("thin").arg("-c").out_exe("clib.o").arg("-O2").run();
63+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
64+
dump.assert_stdout_contains_regex(RUST_NEVER_INLINED_PATTERN);
65+
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
66+
{
67+
if !fat_lto {
68+
dump.assert_stdout_contains_regex(RUST_NEVER_INLINED_PATTERN);
69+
} else {
70+
// fat lto inlines this anyway
71+
dump.assert_stdout_not_contains_regex(RUST_NEVER_INLINED_PATTERN);
72+
}
73+
}
74+
75+
clang().input("clib.c").lto(clang_lto).arg("-c").out_exe("clib.o").arg("-O2").run();
6176
llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run();
6277
rustc()
78+
.lto(lto)
6379
.linker_plugin_lto("on")
6480
.opt_level("2")
6581
.linker(&env_var("CLANG"))
6682
.link_arg("-fuse-ld=lld")
6783
.input("main.rs")
6884
.output("rsmain")
6985
.run();
70-
llvm_objdump()
71-
.disassemble()
72-
.input("rsmain")
73-
.run()
74-
.assert_stdout_not_contains_regex(C_ALWAYS_INLINED_PATTERN);
75-
llvm_objdump()
76-
.disassemble()
77-
.input("rsmain")
78-
.run()
79-
.assert_stdout_contains_regex(C_NEVER_INLINED_PATTERN);
86+
87+
let dump = llvm_objdump().disassemble().input("rsmain").run();
88+
dump.assert_stdout_not_contains_regex(C_ALWAYS_INLINED_PATTERN);
89+
if !fat_lto {
90+
dump.assert_stdout_contains_regex(C_NEVER_INLINED_PATTERN);
91+
} else {
92+
// fat lto inlines this anyway
93+
dump.assert_stdout_not_contains_regex(C_NEVER_INLINED_PATTERN);
94+
}
8095
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![allow(internal_features)]
2+
#![feature(no_core, lang_items)]
3+
#![no_core]
4+
#![crate_type = "rlib"]
5+
6+
#[lang = "pointee_sized"]
7+
trait PointeeSized {}
8+
#[lang = "meta_sized"]
9+
trait MetaSized: PointeeSized {}
10+
#[lang = "sized"]
11+
trait Sized: MetaSized {}
12+
13+
pub fn foo() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![allow(internal_features)]
2+
#![feature(no_core, lang_items)]
3+
#![no_core]
4+
#![crate_type = "cdylib"]
5+
6+
extern crate lib;
7+
8+
#[unsafe(no_mangle)]
9+
pub fn bar() {
10+
lib::foo();
11+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Compile a library with lto=fat, then compile a binary with lto=thin
2+
// and check that lto is applied with the library.
3+
// The goal is to mimic the standard library being build with lto=fat
4+
// and allowing users to build with lto=thin.
5+
6+
//@ only-x86_64-unknown-linux-gnu
7+
8+
use run_make_support::{dynamic_lib_name, llvm_objdump, rustc};
9+
10+
fn main() {
11+
rustc().input("lib.rs").opt_level("3").lto("fat").run();
12+
rustc().input("main.rs").panic("abort").opt_level("3").lto("thin").run();
13+
14+
llvm_objdump()
15+
.input(dynamic_lib_name("main"))
16+
.arg("--disassemble-symbols=bar")
17+
.run()
18+
// The called function should be inlined.
19+
// Check that we have a ret (to detect tail
20+
// calls with a jmp) and no call.
21+
.assert_stdout_contains("bar")
22+
.assert_stdout_contains("ret")
23+
.assert_stdout_not_contains("foo")
24+
.assert_stdout_not_contains("call");
25+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2+
target triple = "x86_64-unknown-linux-gnu"
3+
4+
define void @ir_callee() {
5+
ret void
6+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![allow(internal_features)]
2+
#![feature(no_core, lang_items)]
3+
#![no_core]
4+
#![crate_type = "cdylib"]
5+
6+
#[lang = "pointee_sized"]
7+
trait PointeeSized {}
8+
#[lang = "meta_sized"]
9+
trait MetaSized: PointeeSized {}
10+
#[lang = "sized"]
11+
trait Sized: MetaSized {}
12+
13+
extern "C" {
14+
fn ir_callee();
15+
}
16+
17+
#[no_mangle]
18+
extern "C" fn rs_foo() {
19+
unsafe {
20+
ir_callee();
21+
}
22+
}

0 commit comments

Comments
 (0)