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
This commit is contained in:
parent
75a08622e8
commit
e0685e22a3
1 changed files with 27 additions and 33 deletions
|
|
@ -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 then_bcx_in = scope_block(bcx, thn.info(), "then");
|
||||
|
||||
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 then_bcx_in = scope_block(bcx, thn.info(), "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));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue