Skip to content

Commit 8d0feb5

Browse files
committed
auto merge of #7763 : dotdash/rust/empty_blocks, r=pcwalton
These commits remove a bunch of empty or otherwise unnecessary blocks, reducing the size of the pre-optimization IR and improving its readability. `librustc.ll` created with `--passes ""` shrinks by about 120k lines which equals about 5% of the total size.
2 parents 48bfb90 + 1d2e1a9 commit 8d0feb5

File tree

7 files changed

+163
-98
lines changed

7 files changed

+163
-98
lines changed

src/librustc/middle/trans/base.rs

+89-37
Original file line numberDiff line numberDiff line change
@@ -1102,11 +1102,6 @@ pub fn trans_trace(bcx: block, sp_opt: Option<span>, trace_str: @str) {
11021102
Call(bcx, ccx.upcalls.trace, args);
11031103
}
11041104

1105-
pub fn build_return(bcx: block) {
1106-
let _icx = push_ctxt("build_return");
1107-
Br(bcx, bcx.fcx.llreturn);
1108-
}
1109-
11101105
pub fn ignore_lhs(_bcx: block, local: &ast::local) -> bool {
11111106
match local.node.pat.node {
11121107
ast::pat_wild => true, _ => false
@@ -1364,6 +1359,42 @@ pub fn cleanup_and_leave(bcx: block,
13641359
}
13651360
}
13661361

1362+
pub fn cleanup_block(bcx: block, upto: Option<BasicBlockRef>) -> block{
1363+
let _icx = push_ctxt("cleanup_block");
1364+
let mut cur = bcx;
1365+
let mut bcx = bcx;
1366+
loop {
1367+
debug!("cleanup_block: %s", cur.to_str());
1368+
1369+
if bcx.sess().trace() {
1370+
trans_trace(
1371+
bcx, None,
1372+
(fmt!("cleanup_block(%s)", cur.to_str())).to_managed());
1373+
}
1374+
1375+
let mut cur_scope = cur.scope;
1376+
loop {
1377+
cur_scope = match cur_scope {
1378+
Some (inf) => {
1379+
bcx = trans_block_cleanups_(bcx, inf.cleanups.to_owned(), false);
1380+
inf.parent
1381+
}
1382+
None => break
1383+
}
1384+
}
1385+
1386+
match upto {
1387+
Some(bb) => { if cur.llbb == bb { break; } }
1388+
_ => ()
1389+
}
1390+
cur = match cur.parent {
1391+
Some(next) => next,
1392+
None => { assert!(upto.is_none()); break; }
1393+
};
1394+
}
1395+
bcx
1396+
}
1397+
13671398
pub fn cleanup_and_Br(bcx: block, upto: block, target: BasicBlockRef) {
13681399
let _icx = push_ctxt("cleanup_and_Br");
13691400
cleanup_and_leave(bcx, Some(upto.llbb), Some(target));
@@ -1526,7 +1557,7 @@ pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> Value
15261557
return llvm::LLVMGetUndef(ty.to_ref());
15271558
}
15281559
}
1529-
let initcx = base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas);
1560+
let initcx = base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas());
15301561
let p = Alloca(initcx, ty, name);
15311562
if zero { memzero(initcx, p, ty); }
15321563
p
@@ -1539,24 +1570,26 @@ pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
15391570
return llvm::LLVMGetUndef(ty.to_ref());
15401571
}
15411572
}
1542-
return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas), ty, v);
1573+
return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas()), ty, v);
15431574
}
15441575

15451576
pub struct BasicBlocks {
15461577
sa: BasicBlockRef,
1547-
rt: BasicBlockRef
15481578
}
15491579

1550-
// Creates the standard set of basic blocks for a function
1551-
pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
1580+
pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
15521581
unsafe {
15531582
let cx = task_llcx();
1554-
BasicBlocks {
1555-
sa: str::as_c_str("static_allocas",
1556-
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)),
1557-
rt: str::as_c_str("return",
1558-
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
1559-
}
1583+
str::as_c_str("static_allocas",
1584+
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
1585+
}
1586+
}
1587+
1588+
pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
1589+
unsafe {
1590+
let cx = task_llcx();
1591+
str::as_c_str("return",
1592+
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
15601593
}
15611594
}
15621595

@@ -1568,7 +1601,7 @@ pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
15681601
llvm::LLVMGetParam(fcx.llfn, 0)
15691602
} else {
15701603
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
1571-
alloca(raw_block(fcx, false, fcx.llstaticallocas), lloutputtype,
1604+
alloca(raw_block(fcx, false, fcx.get_llstaticallocas()), lloutputtype,
15721605
"__make_return_pointer")
15731606
}
15741607
}
@@ -1596,8 +1629,6 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
15961629
id,
15971630
param_substs.repr(ccx.tcx));
15981631

1599-
let llbbs = mk_standard_basic_blocks(llfndecl);
1600-
16011632
let substd_output_type = match param_substs {
16021633
None => output_type,
16031634
Some(substs) => {
@@ -1611,9 +1642,9 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
16111642
llvm::LLVMGetUndef(Type::i8p().to_ref())
16121643
},
16131644
llretptr: None,
1614-
llstaticallocas: llbbs.sa,
1645+
llstaticallocas: None,
16151646
llloadenv: None,
1616-
llreturn: llbbs.rt,
1647+
llreturn: None,
16171648
llself: None,
16181649
personality: None,
16191650
loop_ret: None,
@@ -1757,16 +1788,24 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
17571788

17581789
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
17591790
// and builds the return block.
1760-
pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef) {
1791+
pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef, last_bcx: block) {
17611792
let _icx = push_ctxt("finish_fn");
17621793
tie_up_header_blocks(fcx, lltop);
1763-
build_return_block(fcx);
1794+
1795+
let ret_cx = match fcx.llreturn {
1796+
Some(llreturn) => {
1797+
if !last_bcx.terminated {
1798+
Br(last_bcx, llreturn);
1799+
}
1800+
raw_block(fcx, false, llreturn)
1801+
}
1802+
None => last_bcx
1803+
};
1804+
build_return_block(fcx, ret_cx);
17641805
}
17651806

17661807
// Builds the return block for a function.
1767-
pub fn build_return_block(fcx: fn_ctxt) {
1768-
let ret_cx = raw_block(fcx, false, fcx.llreturn);
1769-
1808+
pub fn build_return_block(fcx: fn_ctxt, ret_cx: block) {
17701809
// Return the value if this function immediate; otherwise, return void.
17711810
if fcx.llretptr.is_some() && fcx.has_immediate_return_value {
17721811
Ret(ret_cx, Load(ret_cx, fcx.llretptr.get()))
@@ -1777,14 +1816,24 @@ pub fn build_return_block(fcx: fn_ctxt) {
17771816

17781817
pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
17791818
let _icx = push_ctxt("tie_up_header_blocks");
1780-
match fcx.llloadenv {
1819+
let llnext = match fcx.llloadenv {
17811820
Some(ll) => {
1782-
Br(raw_block(fcx, false, fcx.llstaticallocas), ll);
1821+
unsafe {
1822+
llvm::LLVMMoveBasicBlockBefore(ll, lltop);
1823+
}
17831824
Br(raw_block(fcx, false, ll), lltop);
1825+
ll
17841826
}
1785-
None => {
1786-
Br(raw_block(fcx, false, fcx.llstaticallocas), lltop);
1827+
None => lltop
1828+
};
1829+
match fcx.llstaticallocas {
1830+
Some(ll) => {
1831+
unsafe {
1832+
llvm::LLVMMoveBasicBlockBefore(ll, llnext);
1833+
}
1834+
Br(raw_block(fcx, false, ll), llnext);
17871835
}
1836+
None => ()
17881837
}
17891838
}
17901839

@@ -1854,16 +1903,21 @@ pub fn trans_closure(ccx: @mut CrateContext,
18541903
}
18551904

18561905
finish(bcx);
1857-
cleanup_and_Br(bcx, bcx_top, fcx.llreturn);
1906+
match fcx.llreturn {
1907+
Some(llreturn) => cleanup_and_Br(bcx, bcx_top, llreturn),
1908+
None => bcx = cleanup_block(bcx, Some(bcx_top.llbb))
1909+
};
18581910

18591911
// Put return block after all other blocks.
18601912
// This somewhat improves single-stepping experience in debugger.
18611913
unsafe {
1862-
llvm::LLVMMoveBasicBlockAfter(fcx.llreturn, bcx.llbb);
1914+
for fcx.llreturn.iter().advance |&llreturn| {
1915+
llvm::LLVMMoveBasicBlockAfter(llreturn, bcx.llbb);
1916+
}
18631917
}
18641918

18651919
// Insert the mandatory first few basic blocks before lltop.
1866-
finish_fn(fcx, lltop);
1920+
finish_fn(fcx, lltop, bcx);
18671921
}
18681922

18691923
// trans_fn: creates an LLVM function corresponding to a source language
@@ -2046,8 +2100,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
20462100
let arg_ty = arg_tys[i];
20472101
memcpy_ty(bcx, lldestptr, llarg, arg_ty);
20482102
}
2049-
build_return(bcx);
2050-
finish_fn(fcx, lltop);
2103+
finish_fn(fcx, lltop, bcx);
20512104
}
20522105

20532106
pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
@@ -2288,8 +2341,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
22882341
let args = ~[llenvarg];
22892342
Call(bcx, main_llfn, args);
22902343

2291-
build_return(bcx);
2292-
finish_fn(fcx, lltop);
2344+
finish_fn(fcx, lltop, bcx);
22932345
return llfdecl;
22942346
}
22952347

src/librustc/middle/trans/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ pub fn trans_call_inner(in_cx: block,
704704
Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
705705
}
706706
}
707-
base::cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
707+
base::cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn()));
708708
Unreachable(bcx);
709709
bcx
710710
}

src/librustc/middle/trans/common.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,13 @@ pub struct fn_ctxt_ {
178178
// the function, due to LLVM's quirks.
179179
// A block for all the function's static allocas, so that LLVM
180180
// will coalesce them into a single alloca call.
181-
llstaticallocas: BasicBlockRef,
181+
llstaticallocas: Option<BasicBlockRef>,
182182
// A block containing code that copies incoming arguments to space
183183
// already allocated by code in one of the llallocas blocks.
184184
// (LLVM requires that arguments be copied to local allocas before
185185
// allowing most any operation to be performed on them.)
186186
llloadenv: Option<BasicBlockRef>,
187-
llreturn: BasicBlockRef,
187+
llreturn: Option<BasicBlockRef>,
188188
// The 'self' value currently in use in this function, if there
189189
// is one.
190190
//
@@ -251,6 +251,21 @@ impl fn_ctxt_ {
251251
}
252252
}
253253

254+
pub fn get_llstaticallocas(&mut self) -> BasicBlockRef {
255+
if self.llstaticallocas.is_none() {
256+
self.llstaticallocas = Some(base::mk_staticallocas_basic_block(self.llfn));
257+
}
258+
259+
self.llstaticallocas.get()
260+
}
261+
262+
pub fn get_llreturn(&mut self) -> BasicBlockRef {
263+
if self.llreturn.is_none() {
264+
self.llreturn = Some(base::mk_return_basic_block(self.llfn));
265+
}
266+
267+
self.llreturn.get()
268+
}
254269
}
255270

256271
pub type fn_ctxt = @mut fn_ctxt_;

src/librustc/middle/trans/controlflow.rs

+21-14
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,8 @@ pub fn trans_if(bcx: block,
6767
expr::trans_to_datum(bcx, cond).to_result();
6868

6969
let then_bcx_in = scope_block(bcx, thn.info(), "then");
70-
let else_bcx_in = scope_block(bcx, els.info(), "else");
7170

7271
let cond_val = bool_to_i1(bcx, cond_val);
73-
CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb);
74-
75-
debug!("then_bcx_in=%s, else_bcx_in=%s",
76-
then_bcx_in.to_str(), else_bcx_in.to_str());
7772

7873
let then_bcx_out = trans_block(then_bcx_in, thn, dest);
7974
let then_bcx_out = trans_block_cleanups(then_bcx_out,
@@ -83,9 +78,10 @@ pub fn trans_if(bcx: block,
8378
// because trans_expr will create another scope block
8479
// context for the block, but we've already got the
8580
// 'else' context
86-
let else_bcx_out = match els {
81+
let (else_bcx_in, next_bcx) = match els {
8782
Some(elexpr) => {
88-
match elexpr.node {
83+
let else_bcx_in = scope_block(bcx, els.info(), "else");
84+
let else_bcx_out = match elexpr.node {
8985
ast::expr_if(_, _, _) => {
9086
let elseif_blk = ast_util::block_from_expr(elexpr);
9187
trans_block(else_bcx_in, &elseif_blk, dest)
@@ -95,14 +91,25 @@ pub fn trans_if(bcx: block,
9591
}
9692
// would be nice to have a constraint on ifs
9793
_ => bcx.tcx().sess.bug("strange alternative in if")
98-
}
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]))
99+
}
100+
_ => {
101+
let next_bcx = sub_block(bcx, "next");
102+
Br(then_bcx_out, next_bcx.llbb);
103+
104+
(next_bcx, next_bcx)
99105
}
100-
_ => else_bcx_in
101106
};
102-
let else_bcx_out = trans_block_cleanups(else_bcx_out,
103-
block_cleanups(else_bcx_in));
104-
return join_blocks(bcx, [then_bcx_out, else_bcx_out]);
105107

108+
debug!("then_bcx_in=%s, else_bcx_in=%s",
109+
then_bcx_in.to_str(), else_bcx_in.to_str());
110+
111+
CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb);
112+
next_bcx
106113
}
107114

108115
pub fn join_blocks(parent_bcx: block, in_cxs: &[block]) -> block {
@@ -279,7 +286,7 @@ pub fn trans_break_cont(bcx: block,
279286
// This is a return from a loop body block
280287
None => {
281288
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get());
282-
cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
289+
cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn()));
283290
Unreachable(bcx);
284291
return bcx;
285292
}
@@ -328,7 +335,7 @@ pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
328335
}
329336
_ => ()
330337
}
331-
cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
338+
cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn()));
332339
Unreachable(bcx);
333340
return bcx;
334341
}

0 commit comments

Comments
 (0)