auto merge of #8041 : dotdash/rust/const_if_else, r=huonw

This commit is contained in:
bors 2013-07-26 09:46:49 -07:00
commit 544ef6cf35
2 changed files with 37 additions and 41 deletions

View File

@ -850,6 +850,12 @@ pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
}
}
pub fn is_const(v: ValueRef) -> bool {
unsafe {
llvm::LLVMIsConstant(v) == True
}
}
pub fn const_to_int(v: ValueRef) -> c_longlong {
unsafe {
llvm::LLVMConstIntGetSExtValue(v)

View File

@ -65,44 +65,36 @@ 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 { .. }]
return do with_scope(bcx, thn.info(), "if_true_then") |bcx| {
let bcx_out = trans_block(bcx, thn, dest);
trans_block_cleanups(bcx_out, block_cleanups(bcx))
}
} else {
match els {
// if false { .. } else { .. }
Some(elexpr) => {
return do with_scope(bcx, elexpr.info(), "if_false_then") |bcx| {
let bcx_out = trans_if_else(bcx, elexpr, dest);
trans_block_cleanups(bcx_out, block_cleanups(bcx))
}
}
// 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));
@ -113,7 +105,8 @@ pub fn trans_if(bcx: @mut Block,
// 'else' context
let (else_bcx_in, next_bcx) = match els {
Some(elexpr) => {
let (else_bcx_in, else_bcx_out) = trans_if_else(bcx, elexpr, dest, "else");
let else_bcx_in = scope_block(bcx, elexpr.info(), "else");
let else_bcx_out = trans_if_else(else_bcx_in, elexpr, dest);
(else_bcx_in, join_blocks(bcx, [then_bcx_out, else_bcx_out]))
}
_ => {
@ -131,9 +124,8 @@ pub fn trans_if(bcx: @mut Block,
return next_bcx;
// trans `else [ if { .. } ... | { .. } ]`
fn trans_if_else(bcx: @mut Block, elexpr: @ast::expr,
dest: expr::Dest, scope_name: &str) -> (@mut Block, @mut Block) {
let else_bcx_in = scope_block(bcx, elexpr.info(), scope_name);
fn trans_if_else(else_bcx_in: @mut Block, elexpr: @ast::expr,
dest: expr::Dest) -> @mut Block {
let else_bcx_out = match elexpr.node {
ast::expr_if(_, _, _) => {
let elseif_blk = ast_util::block_from_expr(elexpr);
@ -143,11 +135,9 @@ pub fn trans_if(bcx: @mut Block,
trans_block(else_bcx_in, blk, dest)
}
// would be nice to have a constraint on ifs
_ => bcx.tcx().sess.bug("strange alternative in if")
_ => else_bcx_in.tcx().sess.bug("strange alternative in if")
};
let else_bcx_out = trans_block_cleanups(else_bcx_out,
block_cleanups(else_bcx_in));
(else_bcx_in, else_bcx_out)
trans_block_cleanups(else_bcx_out, block_cleanups(else_bcx_in))
}
}