diff options
| author | Björn Steinbrink <bsteinbr@gmail.com> | 2013-07-25 10:53:27 +0200 |
|---|---|---|
| committer | Björn Steinbrink <bsteinbr@gmail.com> | 2013-07-25 12:17:31 +0200 |
| commit | e0685e22a3a7a5735f635bd28bdcb5084dd5be34 (patch) | |
| tree | a84ae4838a9e69004e7c3d8977df454736670ac8 | |
| parent | 75a08622e8754dbc43ccd2f08031227527645d39 (diff) | |
| download | rust-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.rs | 58 |
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)); |
