Skip to content

Commit 553e7c4

Browse files
committed
Give inlining bonuses to things that optimize out
1 parent 916e0d2 commit 553e7c4

File tree

1 file changed

+48
-8
lines changed

1 file changed

+48
-8
lines changed

Diff for: compiler/rustc_mir_transform/src/cost_checker.rs

+48-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const INSTR_COST: usize = 5;
66
const CALL_PENALTY: usize = 25;
77
const LANDINGPAD_PENALTY: usize = 50;
88
const RESUME_PENALTY: usize = 45;
9+
const LARGE_SWITCH_PENALTY: usize = 20;
10+
const CONST_SWITCH_BONUS: usize = 30;
911

1012
/// Verify that the callee body is compatible with the caller.
1113
#[derive(Clone)]
@@ -42,13 +44,34 @@ impl<'b, 'tcx> CostChecker<'b, 'tcx> {
4244
}
4345

4446
impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
45-
fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
46-
// Don't count StorageLive/StorageDead in the inlining cost.
47+
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
48+
// Most costs are in rvalues and terminators, not in statements.
4749
match statement.kind {
48-
StatementKind::StorageLive(_)
49-
| StatementKind::StorageDead(_)
50-
| StatementKind::Deinit(_)
51-
| StatementKind::Nop => {}
50+
StatementKind::Intrinsic(ref ndi) => {
51+
self.penalty += match **ndi {
52+
NonDivergingIntrinsic::Assume(..) => INSTR_COST,
53+
NonDivergingIntrinsic::CopyNonOverlapping(..) => CALL_PENALTY,
54+
};
55+
}
56+
_ => self.super_statement(statement, location),
57+
}
58+
}
59+
60+
fn visit_rvalue(
61+
&mut self,
62+
rvalue: &Rvalue<'tcx>,
63+
_location: Location,
64+
) {
65+
match rvalue {
66+
Rvalue::NullaryOp(NullOp::UbChecks, ..) if !self.tcx.sess.ub_checks() => {
67+
// If this is in optimized MIR it's because it's used later,
68+
// so if we don't need UB checks this session, give a bonus
69+
// here to offset the cost of the call later.
70+
self.bonus += CALL_PENALTY;
71+
}
72+
// These are essentially constants that didn't end up in an Operand,
73+
// so treat them as also being free.
74+
Rvalue::NullaryOp(..) => {}
5275
_ => self.penalty += INSTR_COST,
5376
}
5477
}
@@ -82,8 +105,25 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
82105
self.penalty += LANDINGPAD_PENALTY;
83106
}
84107
}
85-
TerminatorKind::Assert { unwind, .. } => {
86-
self.penalty += CALL_PENALTY;
108+
TerminatorKind::SwitchInt { ref discr, ref targets } => {
109+
if discr.constant().is_some() {
110+
// Not only will this become a `Goto`, but likely other
111+
// things will be removable as unreachable.
112+
self.bonus += CONST_SWITCH_BONUS;
113+
} else if targets.all_targets().len() > 3 {
114+
// More than false/true/unreachable gets extra cost.
115+
self.penalty += LARGE_SWITCH_PENALTY;
116+
} else {
117+
self.penalty += INSTR_COST;
118+
}
119+
}
120+
TerminatorKind::Assert { unwind, ref msg, .. } => {
121+
self.penalty +=
122+
if msg.is_optional_overflow_check() && !self.tcx.sess.overflow_checks() {
123+
INSTR_COST
124+
} else {
125+
CALL_PENALTY
126+
};
87127
if let UnwindAction::Cleanup(_) = unwind {
88128
self.penalty += LANDINGPAD_PENALTY;
89129
}

0 commit comments

Comments
 (0)