about summary refs log tree commit diff
path: root/src/librustc_codegen_ssa
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-01-26 07:08:18 +0000
committerbors <bors@rust-lang.org>2019-01-26 07:08:18 +0000
commit42eb5ff4042236ec3635035332e059afa7d63f9d (patch)
tree2add28d90e48f64c036bf3dd0b37f454979e44e2 /src/librustc_codegen_ssa
parent9df043b543bb9bc3e50bc243811c58d52a3aefea (diff)
parentce289c6c9911c7ea55b7f30b125d3c38ed359da4 (diff)
downloadrust-42eb5ff4042236ec3635035332e059afa7d63f9d.tar.gz
rust-42eb5ff4042236ec3635035332e059afa7d63f9d.zip
Auto merge of #55641 - nagisa:optimize-attr, r=pnkfelix
Implement optimize(size) and optimize(speed) attributes

This PR implements both `optimize(size)` and `optimize(speed)` attributes.

While the functionality itself works fine now, this PR is not yet complete: the code might be messy in places and, most importantly, the compiletest must be improved with functionality to run tests with custom optimization levels. Otherwise the new attribute cannot be tested properly. Oh, and not all of the RFC is implemented – attribute propagation is not implemented for example.

# TODO

* [x] Improve compiletest so that tests can be written;
* [x] Assign a proper error number (E9999 currently, no idea how to allocate a number properly);
* [ ] Perhaps reduce the duplication in LLVM attribute assignment code…
Diffstat (limited to 'src/librustc_codegen_ssa')
-rw-r--r--src/librustc_codegen_ssa/back/write.rs3
-rw-r--r--src/librustc_codegen_ssa/base.rs37
-rw-r--r--src/librustc_codegen_ssa/traits/backend.rs5
3 files changed, 40 insertions, 5 deletions
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 39bdc70f832..67d4d408bab 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -982,6 +982,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         None
     };
 
+    let ol = tcx.backend_optimization_level(LOCAL_CRATE);
     let cgcx = CodegenContext::<B> {
         backend: backend.clone(),
         crate_types: sess.crate_types.borrow().clone(),
@@ -1005,7 +1006,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         regular_module_config: modules_config,
         metadata_module_config: metadata_config,
         allocator_module_config: allocator_config,
-        tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, false)),
+        tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, ol, false)),
         total_cgus,
         msvc_imps_needed: msvc_imps_needed(tcx),
         target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 38caacba4d0..84e55ce0f22 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -551,7 +551,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
                                                             &["crate"],
                                                             Some("metadata")).as_str()
                                                                              .to_string();
-    let metadata_llvm_module = backend.new_metadata(tcx.sess, &metadata_cgu_name);
+    let metadata_llvm_module = backend.new_metadata(tcx, &metadata_cgu_name);
     let metadata = time(tcx.sess, "write metadata", || {
         backend.write_metadata(tcx, &metadata_llvm_module)
     });
@@ -636,7 +636,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
                                                        &["crate"],
                                                        Some("allocator")).as_str()
                                                                          .to_string();
-        let modules = backend.new_metadata(tcx.sess, &llmod_id);
+        let modules = backend.new_metadata(tcx, &llmod_id);
         time(tcx.sess, "write allocator module", || {
             backend.codegen_allocator(tcx, &modules, kind)
         });
@@ -897,6 +897,39 @@ fn is_codegened_item(tcx: TyCtxt, id: DefId) -> bool {
 }
 
 pub fn provide_both(providers: &mut Providers) {
+    providers.backend_optimization_level = |tcx, cratenum| {
+        let for_speed = match tcx.sess.opts.optimize {
+            // If globally no optimisation is done, #[optimize] has no effect.
+            //
+            // This is done because if we ended up "upgrading" to `-O2` here, we’d populate the
+            // pass manager and it is likely that some module-wide passes (such as inliner or
+            // cross-function constant propagation) would ignore the `optnone` annotation we put
+            // on the functions, thus necessarily involving these functions into optimisations.
+            config::OptLevel::No => return config::OptLevel::No,
+            // If globally optimise-speed is already specified, just use that level.
+            config::OptLevel::Less => return config::OptLevel::Less,
+            config::OptLevel::Default => return config::OptLevel::Default,
+            config::OptLevel::Aggressive => return config::OptLevel::Aggressive,
+            // If globally optimize-for-size has been requested, use -O2 instead (if optimize(size)
+            // are present).
+            config::OptLevel::Size => config::OptLevel::Default,
+            config::OptLevel::SizeMin => config::OptLevel::Default,
+        };
+
+        let (defids, _) = tcx.collect_and_partition_mono_items(cratenum);
+        for id in &*defids {
+            let hir::CodegenFnAttrs { optimize, .. } = tcx.codegen_fn_attrs(*id);
+            match optimize {
+                attr::OptimizeAttr::None => continue,
+                attr::OptimizeAttr::Size => continue,
+                attr::OptimizeAttr::Speed => {
+                    return for_speed;
+                }
+            }
+        }
+        return tcx.sess.opts.optimize;
+    };
+
     providers.dllimport_foreign_items = |tcx, krate| {
         let module_map = tcx.foreign_modules(krate);
         let module_map = module_map.iter()
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index 8c026059dc4..73c7614d913 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -6,7 +6,7 @@ use super::CodegenObject;
 use rustc::middle::allocator::AllocatorKind;
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::mir::mono::Stats;
-use rustc::session::Session;
+use rustc::session::{Session, config};
 use rustc::ty::TyCtxt;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use std::sync::Arc;
@@ -32,7 +32,7 @@ impl<'tcx, T> Backend<'tcx> for T where
 }
 
 pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send {
-    fn new_metadata(&self, sess: &Session, mod_name: &str) -> Self::Module;
+    fn new_metadata(&self, sess: TyCtxt, mod_name: &str) -> Self::Module;
     fn write_metadata<'b, 'gcx>(
         &self,
         tcx: TyCtxt<'b, 'gcx, 'gcx>,
@@ -50,6 +50,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
     fn target_machine_factory(
         &self,
         sess: &Session,
+        opt_level: config::OptLevel,
         find_features: bool,
     ) -> Arc<dyn Fn() -> Result<Self::TargetMachine, String> + Send + Sync>;
     fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str;