From c4cd04480bdfca84274dcbe80dae710bdbe0bd59 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 8 Jun 2022 17:02:06 +1000 Subject: [PATCH] sort_candidates: avoid the second comparison if possible. This is a performance win for `unicode-normalization`. The commit also removes the closure, which isn't necessary. And reformulates the comparison into a form I find easier to read. --- .../rustc_mir_build/src/build/matches/test.rs | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 62ee73993b8..d98837ad7df 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -632,39 +632,33 @@ pub(super) fn sort_candidate<'pat>( } (&TestKind::Range(test), &PatKind::Range(pat)) => { + use std::cmp::Ordering::*; + if test == pat { self.candidate_without_match_pair(match_pair_index, candidate); return Some(0); } - let no_overlap = (|| { - use rustc_hir::RangeEnd::*; - use std::cmp::Ordering::*; + let tcx = self.tcx; + let test_ty = test.lo.ty(); - let tcx = self.tcx; - - let test_ty = test.lo.ty(); - let lo = compare_const_vals(tcx, test.lo, pat.hi, self.param_env, test_ty)?; - let hi = compare_const_vals(tcx, test.hi, pat.lo, self.param_env, test_ty)?; - - match (test.end, pat.end, lo, hi) { - // pat < test - (_, _, Greater, _) | - (_, Excluded, Equal, _) | - // pat > test - (_, _, _, Less) | - (Excluded, _, _, Equal) => Some(true), - _ => Some(false), - } - })(); - - if let Some(true) = no_overlap { - // Testing range does not overlap with pattern range, - // so the pattern can be matched only if this test fails. + // For performance, it's important to only do the second + // `compare_const_vals` if necessary. + let no_overlap = if matches!( + (compare_const_vals(tcx, test.hi, pat.lo, self.param_env, test_ty)?, test.end), + (Less, _) | (Equal, RangeEnd::Excluded) // test < pat + ) || matches!( + (compare_const_vals(tcx, test.lo, pat.hi, self.param_env, test_ty)?, pat.end), + (Greater, _) | (Equal, RangeEnd::Excluded) // test > pat + ) { Some(1) } else { None - } + }; + + // If the testing range does not overlap with pattern range, + // the pattern can be matched only if this test fails. + no_overlap } (&TestKind::Range(range), &PatKind::Constant { value }) => {