Skip to content

Commit 48cab67

Browse files
committed
Auto merge of #77257 - ecstatic-morse:optimize-int-range-from-pat, r=Mark-Simulacrum
Optimize `IntRange::from_pat`, then shrink `ParamEnv` Resolves #77058. r? `@Mark-Simulacrum` cc `@vandenheuvel` Looking at the output of `perf report` for #76244, the hot instructions seemed to be around the call to `pat_constructor` in `IntRange::from_pat`. I carried out an obvious optimization, but it actually made the instruction count higher (see #77075). However, it seems to have mitigated whatever was causing the pipeline stalls, so when combined with #76244, it's a net win. As you can see below, the regression in #76244 seems to have originated from something measured by `stalled-cycles-backend`. I'll try to collect some finer-grained stats to see if I can isolate it. I wish I had a better idea of what was going on here. I'd like to prevent the regression from reappearing in the future due to small changes in unrelated code. <details> <summary>Current `master`:</summary> ``` Performance counter stats for 'cargo +baseline-stage1 check': 2,275.67 msec task-clock:u # 0.998 CPUs utilized 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 49,826 page-faults:u # 0.022 M/sec 5,117,221,678 cycles:u # 2.249 GHz 299,655,943 stalled-cycles-frontend:u # 5.86% frontend cycles idle 2,284,213,395 stalled-cycles-backend:u # 44.64% backend cycles idle 8,051,871,959 instructions:u # 1.57 insn per cycle # 0.28 stalled cycles per insn 1,359,589,402 branches:u # 597.447 M/sec 7,359,347 branch-misses:u # 0.54% of all branches 2.281030026 seconds time elapsed 2.108197000 seconds user 0.164183000 seconds sys ``` </details> <details> <summary>Shrink `ParamEnv` without changing `IntRange::from_pat`:</summary> ``` Performance counter stats for 'cargo +perf-stage1 check': 2,751.79 msec task-clock:u # 0.996 CPUs utilized 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 50,103 page-faults:u # 0.018 M/sec 6,260,590,019 cycles:u # 2.275 GHz 317,355,920 stalled-cycles-frontend:u # 5.07% frontend cycles idle 3,397,743,582 stalled-cycles-backend:u # 54.27% backend cycles idle 8,276,224,367 instructions:u # 1.32 insn per cycle # 0.41 stalled cycles per insn 1,370,453,386 branches:u # 498.023 M/sec 7,281,031 branch-misses:u # 0.53% of all branches 2.763265838 seconds time elapsed 2.544578000 seconds user 0.204548000 seconds sys ``` </details> <details> <summary>Shrink `ParamEnv` and change `IntRange::from_pat`: </summary> ``` Performance counter stats for 'cargo +perf-stage1 check': 2,295.57 msec task-clock:u # 0.996 CPUs utilized 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 49,959 page-faults:u # 0.022 M/sec 5,151,407,066 cycles:u # 2.244 GHz 324,517,829 stalled-cycles-frontend:u # 6.30% frontend cycles idle 2,301,671,001 stalled-cycles-backend:u # 44.68% backend cycles idle 8,130,868,329 instructions:u # 1.58 insn per cycle # 0.28 stalled cycles per insn 1,356,618,512 branches:u # 590.972 M/sec 7,323,800 branch-misses:u # 0.54% of all branches 2.304509653 seconds time elapsed 2.128090000 seconds user 0.163909000 seconds sys ``` </details>
2 parents fc2daaa + c4d8089 commit 48cab67

File tree

4 files changed

+30
-9
lines changed

4 files changed

+30
-9
lines changed

compiler/rustc_infer/src/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
5757

5858
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
5959
#[cfg(target_arch = "x86_64")]
60-
static_assert_size!(PredicateObligation<'_>, 40);
60+
static_assert_size!(PredicateObligation<'_>, 32);
6161

6262
pub type Obligations<'tcx, O> = Vec<Obligation<'tcx, O>>;
6363
pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;

compiler/rustc_middle/src/ty/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1751,9 +1751,6 @@ pub struct ParamEnv<'tcx> {
17511751
///
17521752
/// Note: This is packed, use the reveal() method to access it.
17531753
packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, traits::Reveal, true>,
1754-
1755-
/// FIXME: This field is not used, but removing it causes a performance degradation. See #76913.
1756-
unused_field: Option<DefId>,
17571754
}
17581755

17591756
unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal {
@@ -1834,7 +1831,7 @@ impl<'tcx> ParamEnv<'tcx> {
18341831
/// Construct a trait environment with the given set of predicates.
18351832
#[inline]
18361833
pub fn new(caller_bounds: &'tcx List<Predicate<'tcx>>, reveal: Reveal) -> Self {
1837-
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal), unused_field: None }
1834+
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal) }
18381835
}
18391836

18401837
pub fn with_user_facing(mut self) -> Self {

compiler/rustc_mir_build/src/thir/pattern/_match.rs

+27-3
Original file line numberDiff line numberDiff line change
@@ -1787,9 +1787,32 @@ impl<'tcx> IntRange<'tcx> {
17871787
param_env: ty::ParamEnv<'tcx>,
17881788
pat: &Pat<'tcx>,
17891789
) -> Option<IntRange<'tcx>> {
1790-
match pat_constructor(tcx, param_env, pat)? {
1791-
IntRange(range) => Some(range),
1792-
_ => None,
1790+
// This MUST be kept in sync with `pat_constructor`.
1791+
match *pat.kind {
1792+
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
1793+
PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."),
1794+
1795+
PatKind::Binding { .. }
1796+
| PatKind::Wild
1797+
| PatKind::Leaf { .. }
1798+
| PatKind::Deref { .. }
1799+
| PatKind::Variant { .. }
1800+
| PatKind::Array { .. }
1801+
| PatKind::Slice { .. } => None,
1802+
1803+
PatKind::Constant { value } => Self::from_const(tcx, param_env, value, pat.span),
1804+
1805+
PatKind::Range(PatRange { lo, hi, end }) => {
1806+
let ty = lo.ty;
1807+
Self::from_range(
1808+
tcx,
1809+
lo.eval_bits(tcx, param_env, lo.ty),
1810+
hi.eval_bits(tcx, param_env, hi.ty),
1811+
ty,
1812+
&end,
1813+
pat.span,
1814+
)
1815+
}
17931816
}
17941817
}
17951818

@@ -2196,6 +2219,7 @@ fn pat_constructor<'tcx>(
21962219
param_env: ty::ParamEnv<'tcx>,
21972220
pat: &Pat<'tcx>,
21982221
) -> Option<Constructor<'tcx>> {
2222+
// This MUST be kept in sync with `IntRange::from_pat`.
21992223
match *pat.kind {
22002224
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
22012225
PatKind::Binding { .. } | PatKind::Wild => None,

compiler/rustc_trait_selection/src/traits/fulfill.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub struct PendingPredicateObligation<'tcx> {
8787

8888
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
8989
#[cfg(target_arch = "x86_64")]
90-
static_assert_size!(PendingPredicateObligation<'_>, 64);
90+
static_assert_size!(PendingPredicateObligation<'_>, 56);
9191

9292
impl<'a, 'tcx> FulfillmentContext<'tcx> {
9393
/// Creates a new fulfillment context.

0 commit comments

Comments
 (0)