about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <arielb1@mail.tau.ac.il>2017-04-20 01:20:50 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2017-04-22 21:00:50 +0300
commit3bf00450cb9413b3c8e1e52fb7dfeaf31eb93b83 (patch)
tree9daf2ace5d0f2e5a9e4c6c6141acbfda33d1693e
parent9cc77d7690fc723b264962a4d01a6221be87d80e (diff)
downloadrust-3bf00450cb9413b3c8e1e52fb7dfeaf31eb93b83.tar.gz
rust-3bf00450cb9413b3c8e1e52fb7dfeaf31eb93b83.zip
remove cleanup branches to the resume block
This improves LLVM performance by 10% lost during the shimmir transition.
-rw-r--r--src/librustc_mir/transform/simplify.rs34
-rw-r--r--src/test/codegen/drop.rs2
-rw-r--r--src/test/codegen/personality_lifetimes.rs1
3 files changed, 36 insertions, 1 deletions
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index 0a8f147b214..ef7990653ba 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -124,6 +124,8 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
                     self.collapse_goto_chain(successor, &mut changed);
                 }
 
+                changed |= self.simplify_unwind(&mut terminator);
+
                 let mut new_stmts = vec![];
                 let mut inner_changed = true;
                 while inner_changed {
@@ -238,6 +240,38 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
         true
     }
 
+    // turn an unwind branch to a resume block into a None
+    fn simplify_unwind(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
+        let unwind = match terminator.kind {
+            TerminatorKind::Drop { ref mut unwind, .. } |
+            TerminatorKind::DropAndReplace { ref mut unwind, .. } |
+            TerminatorKind::Call { cleanup: ref mut unwind, .. } |
+            TerminatorKind::Assert { cleanup: ref mut unwind, .. } =>
+                unwind,
+            _ => return false
+        };
+
+        if let &mut Some(unwind_block) = unwind {
+            let is_resume_block = match self.basic_blocks[unwind_block] {
+                BasicBlockData {
+                    ref statements,
+                    terminator: Some(Terminator {
+                        kind: TerminatorKind::Resume, ..
+                    }), ..
+                } if statements.is_empty() => true,
+                _ => false
+            };
+            if is_resume_block {
+                debug!("simplifying unwind to {:?} from {:?}",
+                       unwind_block, terminator.source_info);
+                *unwind = None;
+            }
+            return is_resume_block;
+        }
+
+        false
+    }
+
     fn strip_nops(&mut self) {
         for blk in self.basic_blocks.iter_mut() {
             blk.statements.retain(|stmt| if let StatementKind::Nop = stmt.kind {
diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs
index a4bd5cf2c15..d7e2cb6d9a5 100644
--- a/src/test/codegen/drop.rs
+++ b/src/test/codegen/drop.rs
@@ -36,7 +36,7 @@ pub fn droppy() {
 // CHECK-NOT: call{{.*}}drop{{.*}}SomeUniqueName
 // CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName
 // CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName
-// CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName
+// CHECK: call{{.*}}drop{{.*}}SomeUniqueName
 // CHECK-NOT: {{(call|invoke).*}}drop{{.*}}SomeUniqueName
 // The next line checks for the } that ends the function definition
 // CHECK-LABEL: {{^[}]}}
diff --git a/src/test/codegen/personality_lifetimes.rs b/src/test/codegen/personality_lifetimes.rs
index e0de64b26df..9fd600b32e6 100644
--- a/src/test/codegen/personality_lifetimes.rs
+++ b/src/test/codegen/personality_lifetimes.rs
@@ -37,5 +37,6 @@ pub fn test() {
     // CHECK: bitcast{{.*}}personalityslot
     // CHECK-NEXT: call void @llvm.lifetime.start
     might_unwind();
+    let _t = S;
     might_unwind();
 }