Skip to content

Commit 4797dd4

Browse files
committed
rustc: selectively trans branches for if <literal-bool>.
That is, the `b` branch in `if true { a } else { b }` will not be trans'd, and that expression will be exactly the same as `a`. This means that, for example, macros conditionally expanding to `if false { .. }` (like debug!) will not waste time in LLVM (or trans).
1 parent e252277 commit 4797dd4

File tree

1 file changed

+55
-17
lines changed

1 file changed

+55
-17
lines changed

Diff for: src/librustc/middle/trans/controlflow.rs

+55-17
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,38 @@ pub fn trans_if(bcx: block,
6363
let _indenter = indenter();
6464

6565
let _icx = push_ctxt("trans_if");
66+
67+
match cond.node {
68+
// `if true` and `if false` can be trans'd more efficiently,
69+
// by dropping branches that are known to be impossible.
70+
ast::expr_lit(@ref l) => match l.node {
71+
ast::lit_bool(true) => {
72+
// if true { .. } [else { .. }]
73+
let then_bcx_in = scope_block(bcx, thn.info(), "if_true_then");
74+
let then_bcx_out = trans_block(then_bcx_in, thn, dest);
75+
let then_bcx_out = trans_block_cleanups(then_bcx_out,
76+
block_cleanups(then_bcx_in));
77+
Br(bcx, then_bcx_in.llbb);
78+
return then_bcx_out;
79+
}
80+
ast::lit_bool(false) => {
81+
match els {
82+
// if false { .. } else { .. }
83+
Some(elexpr) => {
84+
let (else_bcx_in, else_bcx_out) =
85+
trans_if_else(bcx, elexpr, dest, "if_false_else");
86+
Br(bcx, else_bcx_in.llbb);
87+
return else_bcx_out;
88+
}
89+
// if false { .. }
90+
None => return bcx,
91+
}
92+
}
93+
_ => {}
94+
},
95+
_ => {}
96+
}
97+
6698
let Result {bcx, val: cond_val} =
6799
expr::trans_to_datum(bcx, cond).to_result();
68100

@@ -80,22 +112,8 @@ pub fn trans_if(bcx: block,
80112
// 'else' context
81113
let (else_bcx_in, next_bcx) = match els {
82114
Some(elexpr) => {
83-
let else_bcx_in = scope_block(bcx, els.info(), "else");
84-
let else_bcx_out = match elexpr.node {
85-
ast::expr_if(_, _, _) => {
86-
let elseif_blk = ast_util::block_from_expr(elexpr);
87-
trans_block(else_bcx_in, &elseif_blk, dest)
88-
}
89-
ast::expr_block(ref blk) => {
90-
trans_block(else_bcx_in, blk, dest)
91-
}
92-
// would be nice to have a constraint on ifs
93-
_ => bcx.tcx().sess.bug("strange alternative in if")
94-
};
95-
let else_bcx_out = trans_block_cleanups(else_bcx_out,
96-
block_cleanups(else_bcx_in));
97-
98-
(else_bcx_in, join_blocks(bcx, [then_bcx_out, else_bcx_out]))
115+
let (else_bcx_in, else_bcx_out) = trans_if_else(bcx, elexpr, dest, "else");
116+
(else_bcx_in, join_blocks(bcx, [then_bcx_out, else_bcx_out]))
99117
}
100118
_ => {
101119
let next_bcx = sub_block(bcx, "next");
@@ -109,7 +127,27 @@ pub fn trans_if(bcx: block,
109127
then_bcx_in.to_str(), else_bcx_in.to_str());
110128

111129
CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb);
112-
next_bcx
130+
return next_bcx;
131+
132+
// trans `else [ if { .. } ... | { .. } ]`
133+
fn trans_if_else(bcx: block, elexpr: @ast::expr,
134+
dest: expr::Dest, scope_name: &str) -> (block, block) {
135+
let else_bcx_in = scope_block(bcx, elexpr.info(), scope_name);
136+
let else_bcx_out = match elexpr.node {
137+
ast::expr_if(_, _, _) => {
138+
let elseif_blk = ast_util::block_from_expr(elexpr);
139+
trans_block(else_bcx_in, &elseif_blk, dest)
140+
}
141+
ast::expr_block(ref blk) => {
142+
trans_block(else_bcx_in, blk, dest)
143+
}
144+
// would be nice to have a constraint on ifs
145+
_ => bcx.tcx().sess.bug("strange alternative in if")
146+
};
147+
let else_bcx_out = trans_block_cleanups(else_bcx_out,
148+
block_cleanups(else_bcx_in));
149+
(else_bcx_in, else_bcx_out)
150+
}
113151
}
114152

115153
pub fn join_blocks(parent_bcx: block, in_cxs: &[block]) -> block {

0 commit comments

Comments
 (0)