Auto merge of #56358 - nikic:mergefunc-aliases, r=rkruppe
Enable -mergefunc-use-aliases If the Rust LLVM fork is used, enable the -mergefunc-use-aliases flag, which will create aliases for merged functions, rather than inserting a call from one to the other. A number of codegen tests needed to be adjusted, because functions that previously fell below the thunk limit are now being merged. Merging is prevented in various ways now. I expect that this is going to break something, somewhere, because it isn't able to deal with aliases properly, but we won't find out until we try :) This fixes #52651. r? @rkruppe
This commit is contained in:
commit
a563ceb3b9
9 changed files with 26 additions and 10 deletions
|
@ -371,15 +371,16 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
.unwrap_or(llvm::CodeGenOptLevel::None);
|
.unwrap_or(llvm::CodeGenOptLevel::None);
|
||||||
let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal ||
|
let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal ||
|
||||||
(cgcx.lto != Lto::Fat && cgcx.opts.debugging_opts.cross_lang_lto.enabled());
|
(cgcx.lto != Lto::Fat && cgcx.opts.debugging_opts.cross_lang_lto.enabled());
|
||||||
|
with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
|
||||||
|
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
|
||||||
|
llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
|
||||||
|
});
|
||||||
|
|
||||||
have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto;
|
have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto;
|
||||||
if using_thin_buffers && !prepare_for_thin_lto {
|
if using_thin_buffers && !prepare_for_thin_lto {
|
||||||
assert!(addpass("name-anon-globals"));
|
assert!(addpass("name-anon-globals"));
|
||||||
have_name_anon_globals_pass = true;
|
have_name_anon_globals_pass = true;
|
||||||
}
|
}
|
||||||
with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
|
|
||||||
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
|
|
||||||
llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for pass in &config.passes {
|
for pass in &config.passes {
|
||||||
|
|
|
@ -1358,6 +1358,7 @@ extern "C" {
|
||||||
pub fn LLVMRustDebugMetadataVersion() -> u32;
|
pub fn LLVMRustDebugMetadataVersion() -> u32;
|
||||||
pub fn LLVMRustVersionMajor() -> u32;
|
pub fn LLVMRustVersionMajor() -> u32;
|
||||||
pub fn LLVMRustVersionMinor() -> u32;
|
pub fn LLVMRustVersionMinor() -> u32;
|
||||||
|
pub fn LLVMRustIsRustLLVM() -> bool;
|
||||||
|
|
||||||
pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
|
pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,9 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||||
if sess.opts.debugging_opts.disable_instrumentation_preinliner {
|
if sess.opts.debugging_opts.disable_instrumentation_preinliner {
|
||||||
add("-disable-preinline");
|
add("-disable-preinline");
|
||||||
}
|
}
|
||||||
|
if llvm::LLVMRustIsRustLLVM() {
|
||||||
|
add("-mergefunc-use-aliases");
|
||||||
|
}
|
||||||
|
|
||||||
for arg in &sess.opts.cg.llvm_args {
|
for arg in &sess.opts.cg.llvm_args {
|
||||||
add(&(*arg));
|
add(&(*arg));
|
||||||
|
|
|
@ -284,7 +284,7 @@ static Optional<Reloc::Model> fromRust(LLVMRustRelocMode RustReloc) {
|
||||||
report_fatal_error("Bad RelocModel.");
|
report_fatal_error("Bad RelocModel.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LLVM_RUSTLLVM
|
#ifdef LLVM_RUSTLLVM
|
||||||
/// getLongestEntryLength - Return the length of the longest entry in the table.
|
/// getLongestEntryLength - Return the length of the longest entry in the table.
|
||||||
///
|
///
|
||||||
static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
|
static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
|
||||||
|
|
|
@ -533,6 +533,14 @@ extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
|
||||||
|
|
||||||
extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
|
extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
|
||||||
|
|
||||||
|
extern "C" bool LLVMRustIsRustLLVM() {
|
||||||
|
#ifdef LLVM_RUSTLLVM
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
|
extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
|
||||||
uint32_t Value) {
|
uint32_t Value) {
|
||||||
unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
|
unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// compile-flags: -C no-prepopulate-passes
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
mod private {
|
mod private {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags: -O
|
// compile-flags: -C no-prepopulate-passes
|
||||||
// `#[no_mangle]`d functions always have external linkage, i.e. no `internal` in their `define`s
|
// `#[no_mangle]`d functions always have external linkage, i.e. no `internal` in their `define`s
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
@ -43,7 +43,7 @@ const HIDDEN: () = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// The surrounding item should not accidentally become external
|
// The surrounding item should not accidentally become external
|
||||||
// CHECK: define internal {{.*}} void @_ZN22external_no_mangle_fns1x
|
// CHECK: define internal{{.*}} void @_ZN22external_no_mangle_fns1x
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn x() {
|
fn x() {
|
||||||
// CHECK: define void @g()
|
// CHECK: define void @g()
|
||||||
|
|
|
@ -69,6 +69,6 @@ fn foo3r(n: u64) -> u64 {
|
||||||
// CHECK-LABEL: @check_foo3r
|
// CHECK-LABEL: @check_foo3r
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn check_foo3r() -> u64 {
|
pub fn check_foo3r() -> u64 {
|
||||||
// CHECK: ret i64 500005000000000
|
// CHECK: ret i64 500050000000
|
||||||
foo3r(100000)
|
foo3r(10000)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
pub enum Three { A, B, C }
|
pub enum Three { A, B, C }
|
||||||
|
|
||||||
|
#[repr(u16)]
|
||||||
pub enum Four { A, B, C, D }
|
pub enum Four { A, B, C, D }
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -32,7 +33,7 @@ pub fn three_valued(x: Three) -> Three {
|
||||||
pub fn four_valued(x: Four) -> Four {
|
pub fn four_valued(x: Four) -> Four {
|
||||||
// CHECK-LABEL: @four_valued
|
// CHECK-LABEL: @four_valued
|
||||||
// CHECK-NEXT: {{^.*:$}}
|
// CHECK-NEXT: {{^.*:$}}
|
||||||
// CHECK-NEXT: ret i8 %0
|
// CHECK-NEXT: ret i16 %0
|
||||||
match x {
|
match x {
|
||||||
Four::A => Four::A,
|
Four::A => Four::A,
|
||||||
Four::B => Four::B,
|
Four::B => Four::B,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue