From b27a161939620626ca5fdcb9f4dd486a6ed1e827 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 2 Aug 2018 18:10:26 +0200 Subject: [PATCH] Annotate functions in LLVM with target-cpu, same as Clang does. --- src/librustc_codegen_llvm/attributes.rs | 18 +++++++++++++ src/librustc_codegen_llvm/base.rs | 1 + src/librustc_codegen_llvm/context.rs | 3 +++ src/test/codegen/target-cpu-on-functions.rs | 28 +++++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 src/test/codegen/target-cpu-on-functions.rs diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index c52f8944108..714e8914e48 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -123,6 +123,15 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator { .filter(|l| !l.is_empty()) } +pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + let target_cpu = CString::new(cx.tcx.sess.target_cpu().to_string()).unwrap(); + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + cstr("target-cpu\0"), + target_cpu.as_c_str()); +} + /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) /// attributes. pub fn from_fn_attrs(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value, id: DefId) { @@ -167,6 +176,15 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value, id: DefId) { Some(true) | None => {} } + // Always annotate functions with the target-cpu they are compiled for. + // Without this, ThinLTO won't inline Rust functions into Clang generated + // functions (because Clang annotates functions this way too). + // NOTE: For now we just apply this if -Zcross-lang-lto is specified, since + // it introduce a little overhead and isn't really necessary otherwise. + if cx.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() { + apply_target_cpu_attr(cx, llfn); + } + let features = llvm_target_features(cx.tcx.sess) .map(|s| s.to_string()) .chain( diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 41336165684..13e8426155a 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -596,6 +596,7 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) { // `main` should respect same config for frame pointer elimination as rest of code attributes::set_frame_pointer_elimination(cx, llfn); + attributes::apply_target_cpu_attr(cx, llfn); let bx = Builder::new_block(cx, llfn, "top"); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 2f557d0b099..7a308bb6e88 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use attributes; use common; use llvm; use rustc::dep_graph::DepGraphSafe; @@ -381,6 +382,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { declare::declare_cfn(self, name, fty) } }; + attributes::apply_target_cpu_attr(self, llfn); self.eh_personality.set(Some(llfn)); llfn } @@ -412,6 +414,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty); attributes::unwind(llfn, true); + attributes::apply_target_cpu_attr(self, llfn); unwresume.set(Some(llfn)); llfn } diff --git a/src/test/codegen/target-cpu-on-functions.rs b/src/test/codegen/target-cpu-on-functions.rs new file mode 100644 index 00000000000..c2765a46caa --- /dev/null +++ b/src/test/codegen/target-cpu-on-functions.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This test makes sure that functions get annotated with the proper +// "target-cpu" attribute in LLVM. + +// only-x86_64 +// compile-flags: -C no-prepopulate-passes -C panic=abort + +#![crate_type = "staticlib"] + +// CHECK-LABEL: define {{.*}} @exported() {{.*}} #0 +#[no_mangle] +pub extern fn exported() { + not_exported(); +} + +// CHECK-LABEL: define {{.*}} @_ZN23target_cpu_on_functions12not_exported{{.*}}() {{.*}} #0 +fn not_exported() {} + +// CHECK: attributes #0 = {{.*}} "target-cpu"="x86-64"