Skip to content

Commit 4ff2c5c

Browse files
committed
Don't treat asserts as a call in cross-crate inlining
1 parent fcf67da commit 4ff2c5c

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;
@@ -110,6 +111,15 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
110111
&& checker.statements <= threshold
111112
}
112113

114+
// The threshold that CostChecker computes is balancing the desire to make more things
115+
// inlinable cross crates against the growth in incremental CGU size that happens when too many
116+
// things in the sysroot are made inlinable.
117+
// Permitting calls causes the size of some incremental CGUs to grow, because more functions are
118+
// made inlinable out of the sysroot or dependencies.
119+
// Assert terminators are similar to calls, but do not have the same impact on compile time, so
120+
// those are just treated as statements.
121+
// A threshold exists at all because we don't want to blindly mark a huge function as inlinable.
122+
113123
struct CostChecker<'b, 'tcx> {
114124
tcx: TyCtxt<'tcx>,
115125
callee_body: &'b Body<'tcx>,
@@ -129,9 +139,10 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
129139
}
130140

131141
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, _: Location) {
142+
self.statements += 1;
132143
let tcx = self.tcx;
133-
match terminator.kind {
134-
TerminatorKind::Drop { ref place, unwind, .. } => {
144+
match &terminator.kind {
145+
TerminatorKind::Drop { place, unwind, .. } => {
135146
let ty = place.ty(self.callee_body, tcx).ty;
136147
if !ty.is_trivially_pure_clone_copy() {
137148
self.calls += 1;
@@ -140,7 +151,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
140151
}
141152
}
142153
}
143-
TerminatorKind::Call { ref func, unwind, .. } => {
154+
TerminatorKind::Call { func, unwind, .. } => {
144155
// We track calls because they make our function not a leaf (and in theory, the
145156
// number of calls indicates how likely this function is to perturb other CGUs).
146157
// But intrinsics don't have a body that gets assigned to a CGU, so they are
@@ -155,21 +166,31 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
155166
self.landing_pads += 1;
156167
}
157168
}
158-
TerminatorKind::Assert { unwind, .. } => {
169+
TerminatorKind::TailCall { .. } => {
159170
self.calls += 1;
171+
}
172+
TerminatorKind::Assert { unwind, .. } => {
160173
if let UnwindAction::Cleanup(_) = unwind {
161174
self.landing_pads += 1;
162175
}
163176
}
164177
TerminatorKind::UnwindResume => self.resumes += 1,
165178
TerminatorKind::InlineAsm { unwind, .. } => {
166-
self.statements += 1;
167179
if let UnwindAction::Cleanup(_) = unwind {
168180
self.landing_pads += 1;
169181
}
170182
}
171-
TerminatorKind::Return => {}
172-
_ => self.statements += 1,
183+
TerminatorKind::Return
184+
| TerminatorKind::Goto { .. }
185+
| TerminatorKind::SwitchInt { .. }
186+
| TerminatorKind::Unreachable
187+
| TerminatorKind::UnwindTerminate(_) => {}
188+
kind @ (TerminatorKind::FalseUnwind { .. }
189+
| TerminatorKind::FalseEdge { .. }
190+
| TerminatorKind::Yield { .. }
191+
| TerminatorKind::CoroutineDrop) => {
192+
bug!("{kind:?} should not be in runtime MIR");
193+
}
173194
}
174195
}
175196
}

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)