about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAntoine Martin <antoine97.martin@gmail.com>2020-10-01 10:06:37 +0200
committerAntoine Martin <antoine97.martin@gmail.com>2020-10-01 10:06:37 +0200
commitf54bfac074657271b03f78b8847e2fbcdd1d76ad (patch)
treed8a6a7af3ce1c05392774277a8938ab869e14393
parent3bbc443cc6657b5df623101f74688ec92e35f35d (diff)
downloadrust-f54bfac074657271b03f78b8847e2fbcdd1d76ad.tar.gz
rust-f54bfac074657271b03f78b8847e2fbcdd1d76ad.zip
Implement multiple return terminators optimization
-rw-r--r--compiler/rustc_mir/src/transform/mod.rs3
-rw-r--r--compiler/rustc_mir/src/transform/multiple_return_terminators.rs38
2 files changed, 41 insertions, 0 deletions
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index 850cafcf898..67193814a40 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -33,6 +33,7 @@ pub mod inline;
 pub mod instcombine;
 pub mod instrument_coverage;
 pub mod match_branches;
+pub mod multiple_return_terminators;
 pub mod no_landing_pads;
 pub mod nrvo;
 pub mod promote_consts;
@@ -464,6 +465,7 @@ fn run_optimization_passes<'tcx>(
         &remove_unneeded_drops::RemoveUnneededDrops,
         &match_branches::MatchBranchSimplification,
         // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
+        &multiple_return_terminators::MultipleReturnTerminators,
         &instcombine::InstCombine,
         &const_prop::ConstProp,
         &simplify_branches::SimplifyBranches::new("after-const-prop"),
@@ -478,6 +480,7 @@ fn run_optimization_passes<'tcx>(
         &simplify::SimplifyCfg::new("final"),
         &nrvo::RenameReturnPlace,
         &simplify::SimplifyLocals,
+        &multiple_return_terminators::MultipleReturnTerminators,
     ];
 
     // Optimizations to run even if mir optimizations have been disabled.
diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs
new file mode 100644
index 00000000000..3c9c8454f74
--- /dev/null
+++ b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs
@@ -0,0 +1,38 @@
+//! This pass removes jumps to basic blocks containing only a return, and replaces them with a
+//! return instead.
+
+use crate::transform::{simplify, MirPass, MirSource};
+use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+pub struct MultipleReturnTerminators;
+
+impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
+        if tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
+            return;
+        }
+
+        // find basic blocks with no statement and a return terminator
+        let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks().len());
+        let bbs = body.basic_blocks_mut();
+        for idx in bbs.indices() {
+            if bbs[idx].statements.is_empty()
+                && bbs[idx].terminator().kind == TerminatorKind::Return
+            {
+                bbs_simple_returns.insert(idx);
+            }
+        }
+
+        for bb in bbs {
+            if let TerminatorKind::Goto { target } = bb.terminator().kind {
+                if bbs_simple_returns.contains(target) {
+                    bb.terminator_mut().kind = TerminatorKind::Return;
+                }
+            }
+        }
+
+        simplify::remove_dead_blocks(body)
+    }
+}