about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBjörn Steinbrink <bsteinbr@gmail.com>2013-07-25 10:53:27 +0200
committerBjörn Steinbrink <bsteinbr@gmail.com>2013-07-25 12:17:31 +0200
commite0685e22a3a7a5735f635bd28bdcb5084dd5be34 (patch)
treea84ae4838a9e69004e7c3d8977df454736670ac8
parent75a08622e8754dbc43ccd2f08031227527645d39 (diff)
downloadrust-e0685e22a3a7a5735f635bd28bdcb5084dd5be34.tar.gz
rust-e0685e22a3a7a5735f635bd28bdcb5084dd5be34.zip
Make omission of impossible if-else branches work with constants
Until now, we only optimized away impossible branches when there is a
literal true/false in the code. But since the LLVM IR builder already does
constant folding for us, we can trivially expand that to work with
constants as well.

Refs #7834
-rw-r--r--src/librustc/middle/trans/controlflow.rs58
1 files changed, 26 insertions, 32 deletions
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index 2b6c1d82418..a00cd94ad54 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -65,44 +65,38 @@ pub fn trans_if(bcx: @mut Block,
 
     let _icx = push_ctxt("trans_if");
 
-    match cond.node {
-        // `if true` and `if false` can be trans'd more efficiently,
-        // by dropping branches that are known to be impossible.
-        ast::expr_lit(@ref l) => match l.node {
-            ast::lit_bool(true) => {
-                // if true { .. } [else { .. }]
-                let then_bcx_in = scope_block(bcx, thn.info(), "if_true_then");
-                let then_bcx_out = trans_block(then_bcx_in, thn, dest);
-                let then_bcx_out = trans_block_cleanups(then_bcx_out,
-                                                        block_cleanups(then_bcx_in));
-                Br(bcx, then_bcx_in.llbb);
-                return then_bcx_out;
-            }
-            ast::lit_bool(false) => {
-                match els {
-                    // if false { .. } else { .. }
-                    Some(elexpr) => {
-                        let (else_bcx_in, else_bcx_out) =
-                            trans_if_else(bcx, elexpr, dest, "if_false_else");
-                        Br(bcx, else_bcx_in.llbb);
-                        return else_bcx_out;
-                    }
-                    // if false { .. }
-                    None => return bcx,
+    let Result {bcx, val: cond_val} =
+        expr::trans_to_datum(bcx, cond).to_result();
+
+    let cond_val = bool_to_i1(bcx, cond_val);
+
+    // Drop branches that are known to be impossible
+    if is_const(cond_val) && !is_undef(cond_val) {
+        if const_to_uint(cond_val) == 1 {
+            // if true { .. } [else { .. }]
+            let then_bcx_in = scope_block(bcx, thn.info(), "if_true_then");
+            let then_bcx_out = trans_block(then_bcx_in, thn, dest);
+            let then_bcx_out = trans_block_cleanups(then_bcx_out,
+                                                    block_cleanups(then_bcx_in));
+            Br(bcx, then_bcx_in.llbb);
+            return then_bcx_out;
+        } else {
+            match els {
+                // if false { .. } else { .. }
+                Some(elexpr) => {
+                    let (else_bcx_in, else_bcx_out) =
+                        trans_if_else(bcx, elexpr, dest, "if_false_else");
+                    Br(bcx, else_bcx_in.llbb);
+                    return else_bcx_out;
                 }
+                // if false { .. }
+                None => return bcx,
             }
-            _ => {}
-        },
-        _ => {}
+        }
     }
 
-    let Result {bcx, val: cond_val} =
-        expr::trans_to_datum(bcx, cond).to_result();
-
     let then_bcx_in = scope_block(bcx, thn.info(), "then");
 
-    let cond_val = bool_to_i1(bcx, cond_val);
-
     let then_bcx_out = trans_block(then_bcx_in, thn, dest);
     let then_bcx_out = trans_block_cleanups(then_bcx_out,
                                             block_cleanups(then_bcx_in));