]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #35168 - scottcarr:deaggregation, r=nikomatsakis
authorbors <bors@rust-lang.org>
Thu, 4 Aug 2016 10:01:37 +0000 (03:01 -0700)
committerGitHub <noreply@github.com>
Thu, 4 Aug 2016 10:01:37 +0000 (03:01 -0700)
[MIR] Deaggregate structs to enable further optimizations

Currently, we generate MIR like:

```
tmp0 = ...;
tmp1 = ...;
tmp3 = Foo { a: ..., b: ... };
```

This PR implements "deaggregation," i.e.:

```
tmp3.0 = ...
tmp3.1 = ...
```

Currently, the code only deaggregates structs, not enums.  My understanding is that we do not have MIR to set the discriminant of an enum.

1  2 
src/librustc_driver/driver.rs

index f172f38b809686f2995c10639ca4e05945882482,657fc6c2c5b15081eefa66d27bbab4568d3da285..f1f5e194da4d16538418838c23725cad0f45e392
@@@ -88,7 -88,7 +88,7 @@@ pub fn compile_input(sess: &Session
      // We need nested scopes here, because the intermediate results can keep
      // large chunks of memory alive and we want to free them as soon as
      // possible to keep the peak memory usage low
 -    let (outputs, trans) = {
 +    let (outputs, trans, crate_name) = {
          let krate = match phase_1_parse_input(sess, cfg, input) {
              Ok(krate) => krate,
              Err(mut parse_error) => {
          };
  
          let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
 -        let id = link::find_crate_name(Some(sess), &krate.attrs, input);
 +        let crate_name = link::find_crate_name(Some(sess), &krate.attrs, input);
          let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
              phase_2_configure_and_expand(
 -                sess, &cstore, krate, &id, addl_plugins, control.make_glob_map,
 +                sess, &cstore, krate, &crate_name, addl_plugins, control.make_glob_map,
                  |expanded_crate| {
                      let mut state = CompileState::state_after_expand(
 -                        input, sess, outdir, output, &cstore, expanded_crate, &id,
 +                        input, sess, outdir, output, &cstore, expanded_crate, &crate_name,
                      );
                      controller_entry_point!(after_expand, sess, state, Ok(()));
                      Ok(())
              )?
          };
  
 -        write_out_deps(sess, &outputs, &id);
 +        write_out_deps(sess, &outputs, &crate_name);
  
          let arenas = ty::CtxtArenas::new();
  
                                                                    &resolutions,
                                                                    &expanded_crate,
                                                                    &hir_map.krate(),
 -                                                                  &id),
 +                                                                  &crate_name),
                                      Ok(()));
          }
  
                                      analysis,
                                      resolutions,
                                      &arenas,
 -                                    &id,
 +                                    &crate_name,
                                      |tcx, mir_map, analysis, result| {
              {
                  // Eventually, we will want to track plugins.
                                                                     &analysis,
                                                                     mir_map.as_ref(),
                                                                     tcx,
 -                                                                   &id);
 +                                                                   &crate_name);
                  (control.after_analysis.callback)(&mut state);
  
                  if control.after_analysis.stop == Compilation::Stop {
              // Discard interned strings as they are no longer required.
              token::clear_ident_interner();
  
 -            Ok((outputs, trans))
 +            Ok((outputs, trans, crate_name.clone()))
          })??
      };
  
 -    let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
 +    let phase5_result = phase_5_run_llvm_passes(sess, &crate_name, &trans, &outputs);
  
      controller_entry_point!(after_llvm,
                              sess,
@@@ -566,8 -566,7 +566,8 @@@ pub fn phase_2_configure_and_expand<'a
      });
  
      *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
 -    sess.crate_disambiguator.set(token::intern(&compute_crate_disambiguator(sess)));
 +    *sess.crate_disambiguator.borrow_mut() =
 +        token::intern(&compute_crate_disambiguator(sess)).as_str();
  
      time(time_passes, "recursion limit", || {
          middle::recursion_limit::update_recursion_limit(sess, &krate);
@@@ -995,6 -994,8 +995,8 @@@ pub fn phase_4_translate_to_llvm<'a, 't
          passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
          passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("elaborate-drops"));
  
+         passes.push_pass(box mir::transform::deaggregator::Deaggregator);
          passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
          passes.push_pass(box mir::transform::dump_mir::Marker("PreTrans"));
  
  /// Run LLVM itself, producing a bitcode file, assembly file or object file
  /// as a side effect.
  pub fn phase_5_run_llvm_passes(sess: &Session,
 +                               crate_name: &str,
                                 trans: &trans::CrateTranslation,
                                 outputs: &OutputFilenames) -> CompileResult {
      if sess.opts.cg.no_integrated_as {
               || write::run_passes(sess, trans, &sess.opts.output_types, outputs));
      }
  
 +    time(sess.time_passes(),
 +         "serialize work products",
 +         move || rustc_incremental::save_work_products(sess, crate_name));
 +
      if sess.err_count() > 0 {
          Err(sess.err_count())
      } else {
@@@ -1069,14 -1065,14 +1071,14 @@@ fn escape_dep_filename(filename: &str) 
      filename.replace(" ", "\\ ")
  }
  
 -fn write_out_deps(sess: &Session, outputs: &OutputFilenames, id: &str) {
 +fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) {
      let mut out_filenames = Vec::new();
      for output_type in sess.opts.output_types.keys() {
          let file = outputs.path(*output_type);
          match *output_type {
              OutputType::Exe => {
                  for output in sess.crate_types.borrow().iter() {
 -                    let p = link::filename_for_input(sess, *output, id, outputs);
 +                    let p = link::filename_for_input(sess, *output, crate_name, outputs);
                      out_filenames.push(p);
                  }
              }