Skip to content

Commit 55eefde

Browse files
committed
Enable MIR inlining of very small functions in debug builds
1 parent 2a7c2df commit 55eefde

25 files changed

+160
-44
lines changed

compiler/rustc_mir_transform/src/inline.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use rustc_middle::mir::visit::*;
1010
use rustc_middle::mir::*;
1111
use rustc_middle::ty::TypeVisitableExt;
1212
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
13-
use rustc_session::config::OptLevel;
1413
use rustc_target::abi::FieldIdx;
1514
use rustc_target::spec::abi::Abi;
1615

@@ -47,12 +46,8 @@ impl<'tcx> MirPass<'tcx> for Inline {
4746
}
4847

4948
match sess.mir_opt_level() {
50-
0 | 1 => false,
51-
2 => {
52-
(sess.opts.optimize == OptLevel::Default
53-
|| sess.opts.optimize == OptLevel::Aggressive)
54-
&& sess.opts.incremental == None
55-
}
49+
0 => false,
50+
1 | 2 => sess.opts.incremental.is_none(),
5651
_ => true,
5752
}
5853
}
@@ -471,7 +466,15 @@ impl<'tcx> Inliner<'tcx> {
471466
if callee_body.basic_blocks.len() <= 3 {
472467
threshold += threshold / 4;
473468
}
474-
debug!(" final inline threshold = {}", threshold);
469+
470+
if tcx.sess.mir_opt_level() == 1 {
471+
threshold = 2 * INSTR_COST;
472+
473+
if callee_body.basic_blocks.len() > 1 {
474+
return Err("cost above threshold");
475+
}
476+
}
477+
debug!("final inline threshold = {}", threshold);
475478

476479
// FIXME: Give a bonus to functions with only a single caller
477480

@@ -481,6 +484,7 @@ impl<'tcx> Inliner<'tcx> {
481484
instance: callsite.callee,
482485
callee_body,
483486
cost: 0,
487+
threshold,
484488
};
485489

486490
// Traverse the MIR manually so we can account for the effects of inlining on the CFG.
@@ -493,6 +497,10 @@ impl<'tcx> Inliner<'tcx> {
493497

494498
let blk = &callee_body.basic_blocks[bb];
495499
checker.visit_basic_block_data(bb, blk);
500+
if callee_attrs.inline != InlineAttr::Always && checker.cost > threshold {
501+
debug!("checker cost exceeded threshold partway through");
502+
return Err("cost above threshold");
503+
}
496504

497505
let term = blk.terminator();
498506
if let TerminatorKind::Drop { ref place, target, unwind, replace: _ } = term.kind {
@@ -805,12 +813,17 @@ struct CostChecker<'b, 'tcx> {
805813
tcx: TyCtxt<'tcx>,
806814
param_env: ParamEnv<'tcx>,
807815
cost: usize,
816+
threshold: usize,
808817
callee_body: &'b Body<'tcx>,
809818
instance: ty::Instance<'tcx>,
810819
}
811820

812821
impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
813822
fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
823+
if self.cost > self.threshold {
824+
return;
825+
}
826+
814827
// Don't count StorageLive/StorageDead in the inlining cost.
815828
match statement.kind {
816829
StatementKind::StorageLive(_)

tests/codegen-units/polymorphization/unused_type_parameters.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// compile-flags:-Zpolymorphize=on -Zprint-mono-items=lazy -Copt-level=1
1+
// compile-flags:-Zpolymorphize=on -Zprint-mono-items=lazy -Copt-level=1 -Zmir-opt-level=0
22

33
#![crate_type = "rlib"]
44

tests/debuginfo/function-names.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Function names are formatted differently in old versions of GDB
22
// min-gdb-version: 10.1
33

4-
// compile-flags:-g
4+
// compile-flags: -g -Zmir-opt-level=0
55

66
// === GDB TESTS ===================================================================================
77

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
2+
// compile-flags: -Copt-level=0 -Zmir-opt-level=1
3+
#![crate_type = "lib"]
4+
5+
// Test that we still inline trivial functions even in a debug build
6+
7+
pub struct Thing {
8+
inner: u8,
9+
}
10+
11+
impl Thing {
12+
#[inline]
13+
pub fn get(&self) -> u8 {
14+
self.inner
15+
}
16+
}
17+
18+
// EMIT_MIR trivial_fn_debug_build.wrapper.Inline.diff
19+
// EMIT_MIR trivial_fn_debug_build.wrapper.PreCodegen.after.mir
20+
pub fn wrapper(t: &Thing) -> u8 {
21+
t.get()
22+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
- // MIR for `wrapper` before Inline
2+
+ // MIR for `wrapper` after Inline
3+
4+
fn wrapper(_1: &Thing) -> u8 {
5+
debug t => _1;
6+
let mut _0: u8;
7+
let mut _2: &Thing;
8+
+ scope 1 (inlined Thing::get) {
9+
+ debug self => _2;
10+
+ }
11+
12+
bb0: {
13+
StorageLive(_2);
14+
_2 = &(*_1);
15+
- _0 = Thing::get(move _2) -> [return: bb1, unwind unreachable];
16+
- }
17+
-
18+
- bb1: {
19+
+ _0 = ((*_2).0: u8);
20+
StorageDead(_2);
21+
return;
22+
}
23+
}
24+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
- // MIR for `wrapper` before Inline
2+
+ // MIR for `wrapper` after Inline
3+
4+
fn wrapper(_1: &Thing) -> u8 {
5+
debug t => _1;
6+
let mut _0: u8;
7+
let mut _2: &Thing;
8+
+ scope 1 (inlined Thing::get) {
9+
+ debug self => _2;
10+
+ }
11+
12+
bb0: {
13+
StorageLive(_2);
14+
_2 = &(*_1);
15+
- _0 = Thing::get(move _2) -> [return: bb1, unwind continue];
16+
- }
17+
-
18+
- bb1: {
19+
+ _0 = ((*_2).0: u8);
20+
StorageDead(_2);
21+
return;
22+
}
23+
}
24+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// MIR for `wrapper` after PreCodegen
2+
3+
fn wrapper(_1: &Thing) -> u8 {
4+
debug t => _1;
5+
let mut _0: u8;
6+
scope 1 (inlined Thing::get) {
7+
debug self => _1;
8+
}
9+
10+
bb0: {
11+
_0 = ((*_1).0: u8);
12+
return;
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// MIR for `wrapper` after PreCodegen
2+
3+
fn wrapper(_1: &Thing) -> u8 {
4+
debug t => _1;
5+
let mut _0: u8;
6+
scope 1 (inlined Thing::get) {
7+
debug self => _1;
8+
}
9+
10+
bb0: {
11+
_0 = ((*_1).0: u8);
12+
return;
13+
}
14+
}

tests/run-make/sepcomp-cci-copies/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ include ../tools.mk
88
all:
99
$(RUSTC) cci_lib.rs
1010
$(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=6 \
11-
-Z inline-in-all-cgus
11+
-Z inline-in-all-cgus -Zmir-opt-level=0
1212
[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ .*cci_fn)" -eq "2" ]

tests/run-make/sepcomp-inlining/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ include ../tools.mk
88

99
all:
1010
$(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 \
11-
-Z inline-in-all-cgus
11+
-Z inline-in-all-cgus -Zmir-opt-level=0
1212
[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ i32\ .*inlined)" -eq "0" ]
1313
[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "2" ]
1414
[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ hidden\ i32\ .*normal)" -eq "1" ]

0 commit comments

Comments
 (0)