Skip to content

Commit daa77e6

Browse files
committed
Don't treat asserts as a call in cross-crate inlining
1 parent 29a6971 commit daa77e6

File tree

4 files changed

+43
-7
lines changed

4 files changed

+43
-7
lines changed

compiler/rustc_mir_transform/src/cross_crate_inline.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_hir::attrs::InlineAttr;
22
use rustc_hir::def::DefKind;
33
use rustc_hir::def_id::LocalDefId;
4+
use rustc_middle::bug;
45
use rustc_middle::mir::visit::Visitor;
56
use rustc_middle::mir::*;
67
use rustc_middle::query::Providers;
@@ -102,6 +103,15 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
102103
&& checker.statements <= threshold
103104
}
104105

106+
// The threshold that CostChecker computes is balancing the desire to make more things
107+
// inlinable cross crates against the growth in incremental CGU size that happens when too many
108+
// things in the sysroot are made inlinable.
109+
// Permitting calls causes the size of some incremental CGUs to grow, because more functions are
110+
// made inlinable out of the sysroot or dependencies.
111+
// Assert terminators are similar to calls, but do not have the same impact on compile time, so
112+
// those are just treated as statements.
113+
// A threshold exists at all because we don't want to blindly mark a huge function as inlinable.
114+
105115
struct CostChecker<'b, 'tcx> {
106116
tcx: TyCtxt<'tcx>,
107117
callee_body: &'b Body<'tcx>,
@@ -121,9 +131,10 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
121131
}
122132

123133
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, _: Location) {
134+
self.statements += 1;
124135
let tcx = self.tcx;
125-
match terminator.kind {
126-
TerminatorKind::Drop { ref place, unwind, .. } => {
136+
match &terminator.kind {
137+
TerminatorKind::Drop { place, unwind, .. } => {
127138
let ty = place.ty(self.callee_body, tcx).ty;
128139
if !ty.is_trivially_pure_clone_copy() {
129140
self.calls += 1;
@@ -132,7 +143,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
132143
}
133144
}
134145
}
135-
TerminatorKind::Call { ref func, unwind, .. } => {
146+
TerminatorKind::Call { func, unwind, .. } => {
136147
// We track calls because they make our function not a leaf (and in theory, the
137148
// number of calls indicates how likely this function is to perturb other CGUs).
138149
// But intrinsics don't have a body that gets assigned to a CGU, so they are
@@ -147,21 +158,31 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
147158
self.landing_pads += 1;
148159
}
149160
}
150-
TerminatorKind::Assert { unwind, .. } => {
161+
TerminatorKind::TailCall { .. } => {
151162
self.calls += 1;
163+
}
164+
TerminatorKind::Assert { unwind, .. } => {
152165
if let UnwindAction::Cleanup(_) = unwind {
153166
self.landing_pads += 1;
154167
}
155168
}
156169
TerminatorKind::UnwindResume => self.resumes += 1,
157170
TerminatorKind::InlineAsm { unwind, .. } => {
158-
self.statements += 1;
159171
if let UnwindAction::Cleanup(_) = unwind {
160172
self.landing_pads += 1;
161173
}
162174
}
163-
TerminatorKind::Return => {}
164-
_ => self.statements += 1,
175+
TerminatorKind::Return
176+
| TerminatorKind::Goto { .. }
177+
| TerminatorKind::SwitchInt { .. }
178+
| TerminatorKind::Unreachable
179+
| TerminatorKind::UnwindTerminate(_) => {}
180+
kind @ (TerminatorKind::FalseUnwind { .. }
181+
| TerminatorKind::FalseEdge { .. }
182+
| TerminatorKind::Yield { .. }
183+
| TerminatorKind::CoroutineDrop) => {
184+
bug!("{kind:?} should not be in runtime MIR");
185+
}
165186
}
166187
}
167188
}

tests/codegen-llvm/cross-crate-inlining/auxiliary/leaf.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,8 @@ fn inner() -> String {
2323
pub fn leaf_with_intrinsic(a: &[u64; 2], b: &[u64; 2]) -> bool {
2424
a == b
2525
}
26+
27+
// This function's optimized MIR contains assert terminators, not calls.
28+
pub fn leaf_with_assert(a: i32, b: i32) -> i32 {
29+
a / b
30+
}

tests/codegen-llvm/cross-crate-inlining/leaf-inlining.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,12 @@ pub fn leaf_with_intrinsic_outer(a: &[u64; 2], b: &[u64; 2]) -> bool {
2525
// CHECK-NOT: call {{.*}}leaf_with_intrinsic
2626
leaf::leaf_with_intrinsic(a, b)
2727
}
28+
29+
// Check that we inline functions with assert terminators
30+
#[no_mangle]
31+
pub fn leaf_with_assert(a: i32, b: i32) -> i32 {
32+
// CHECK-NOT: call {{.*}}leaf_with_assert
33+
// CHECK: sdiv i32 %a, %b
34+
// CHECK-NOT: call {{.*}}leaf_with_assert
35+
leaf::leaf_with_assert(a, b)
36+
}

tests/codegen-units/item-collection/implicit-panic-call.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// rust-lang/rust#90405
22
// Ensure implicit panic calls are collected
3+
//@ compile-flags: -Zcross-crate-inline-threshold=never
34

45
#![feature(lang_items)]
56
#![feature(no_core)]

0 commit comments

Comments
 (0)