]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #65089 - nnethercote:optimize-integral-pattern-matching, r=Mark-Simulacrum
authorbors <bors@rust-lang.org>
Sun, 6 Oct 2019 12:50:47 +0000 (12:50 +0000)
committerbors <bors@rust-lang.org>
Sun, 6 Oct 2019 12:50:47 +0000 (12:50 +0000)
Optimize integral pattern matching

Various improvements to integral pattern matching. Together they reduce instruction counts for `unicode_normalization-check-clean` by about 16%.

r? @Mark-Simulacrum

1  2 
src/librustc/ty/sty.rs

diff --combined src/librustc/ty/sty.rs
index e27236b47e07f8501557f344457077532ea503c5,d5bb18a2e3e2aadb81f01c009029930764cd01a2..41224ba40f33c771fb5a37e2eab08b440c0d2cc1
@@@ -13,7 -13,7 +13,7 @@@ use rustc_macros::HashStable
  use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, GenericArg, GenericArgKind};
  use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable};
  use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
- use crate::ty::layout::{Size, Integer, IntegerExt, VariantIdx};
+ use crate::ty::layout::VariantIdx;
  use crate::util::captures::Captures;
  use crate::mir::interpret::{Scalar, GlobalId};
  
@@@ -24,7 -24,6 +24,6 @@@ use std::marker::PhantomData
  use std::ops::Range;
  use rustc_target::spec::abi;
  use syntax::ast::{self, Ident};
- use syntax::attr::{SignedInt, UnsignedInt};
  use syntax::symbol::{kw, InternedString};
  
  use self::InferTy::*;
@@@ -159,11 -158,11 +158,11 @@@ pub enum TyKind<'tcx> 
  
      /// The anonymous type of a closure. Used to represent the type of
      /// `|a| a`.
 -    Closure(DefId, ClosureSubsts<'tcx>),
 +    Closure(DefId, SubstsRef<'tcx>),
  
      /// The anonymous type of a generator. Used to represent the type of
      /// `|a| yield a`.
 -    Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
 +    Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability),
  
      /// A type representin the types stored inside a generator.
      /// This should only appear in GeneratorInteriors.
@@@ -305,8 -304,8 +304,8 @@@ static_assert_size!(TyKind<'_>, 24)
  /// type parameters is similar, but the role of CK and CS are
  /// different. CK represents the "yield type" and CS represents the
  /// "return type" of the generator.
 -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
 -         Debug, RustcEncodable, RustcDecodable, HashStable)]
 +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug,
 +         RustcEncodable, RustcDecodable, HashStable)]
  pub struct ClosureSubsts<'tcx> {
      /// Lifetime and type parameters from the enclosing function,
      /// concatenated with the types of the upvars.
@@@ -357,7 -356,7 +356,7 @@@ impl<'tcx> ClosureSubsts<'tcx> 
      /// Returns the closure kind for this closure; may return a type
      /// variable during inference. To get the closure kind during
      /// inference, use `infcx.closure_kind(def_id, substs)`.
 -    pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
 +    pub fn kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
          self.split(def_id, tcx).closure_kind_ty
      }
  
      /// closure; may contain type variables during inference. To get
      /// the closure signature during inference, use
      /// `infcx.fn_sig(def_id)`.
 -    pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
 +    pub fn sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
          self.split(def_id, tcx).closure_sig_ty
      }
  
      /// there are no type variables.
      ///
      /// If you have an inference context, use `infcx.closure_kind()`.
 -    pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
 +    pub fn kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
          self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
      }
  
      /// there are no type variables.
      ///
      /// If you have an inference context, use `infcx.closure_sig()`.
 -    pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
 -        let ty = self.closure_sig_ty(def_id, tcx);
 +    pub fn sig(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
 +        let ty = self.sig_ty(def_id, tcx);
          match ty.kind {
              ty::FnPtr(sig) => sig,
              _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind),
@@@ -512,7 -511,7 +511,7 @@@ impl<'tcx> GeneratorSubsts<'tcx> 
      /// variant indices.
      #[inline]
      pub fn discriminants(
 -        &'tcx self,
 +        self,
          def_id: DefId,
          tcx: TyCtxt<'tcx>,
      ) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx> {
      /// Calls `f` with a reference to the name of the enumerator for the given
      /// variant `v`.
      #[inline]
 -    pub fn variant_name(&self, v: VariantIdx) -> Cow<'static, str> {
 +    pub fn variant_name(self, v: VariantIdx) -> Cow<'static, str> {
          match v.as_usize() {
              Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME),
              Self::RETURNED => Cow::from(Self::RETURNED_NAME),
  
  #[derive(Debug, Copy, Clone)]
  pub enum UpvarSubsts<'tcx> {
 -    Closure(ClosureSubsts<'tcx>),
 -    Generator(GeneratorSubsts<'tcx>),
 +    Closure(SubstsRef<'tcx>),
 +    Generator(SubstsRef<'tcx>),
  }
  
  impl<'tcx> UpvarSubsts<'tcx> {
      pub fn upvar_tys(
          self,
          def_id: DefId,
 -        tcx: TyCtxt<'_>,
 +        tcx: TyCtxt<'tcx>,
      ) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
          let upvar_kinds = match self {
 -            UpvarSubsts::Closure(substs) => substs.split(def_id, tcx).upvar_kinds,
 -            UpvarSubsts::Generator(substs) => substs.split(def_id, tcx).upvar_kinds,
 +            UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds,
 +            UpvarSubsts::Generator(substs) => substs.as_generator().split(def_id, tcx).upvar_kinds,
          };
          upvar_kinds.iter().map(|t| {
              if let GenericArgKind::Type(ty) = t.unpack() {
@@@ -2109,8 -2108,7 +2108,8 @@@ impl<'tcx> TyS<'tcx> 
      pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
          match self.kind {
              TyKind::Adt(adt, _) => Some(adt.variant_range()),
 -            TyKind::Generator(def_id, substs, _) => Some(substs.variant_range(def_id, tcx)),
 +            TyKind::Generator(def_id, substs, _) =>
 +                Some(substs.as_generator().variant_range(def_id, tcx)),
              _ => None,
          }
      }
          match self.kind {
              TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)),
              TyKind::Generator(def_id, substs, _) =>
 -                Some(substs.discriminant_for_variant(def_id, tcx, variant_index)),
 +                Some(substs.as_generator().discriminant_for_variant(def_id, tcx, variant_index)),
              _ => None,
          }
      }
              Adt(_, substs) | Opaque(_, substs) => {
                  out.extend(substs.regions())
              }
 -            Closure(_, ClosureSubsts { ref substs }) |
 -            Generator(_, GeneratorSubsts { ref substs }, _) => {
 +            Closure(_, ref substs ) |
 +            Generator(_, ref substs, _) => {
                  out.extend(substs.regions())
              }
              Projection(ref data) | UnnormalizedProjection(ref data) => {
@@@ -2300,20 -2298,7 +2299,7 @@@ impl<'tcx> Const<'tcx> 
          ty: Ty<'tcx>,
      ) -> Option<u128> {
          assert_eq!(self.ty, ty);
-         // This is purely an optimization -- layout_of is a pretty expensive operation,
-         // but if we can determine the size without calling it, we don't need all that complexity
-         // (hashing, caching, etc.). As such, try to skip it.
-         let size = match ty.kind {
-             ty::Bool => Size::from_bytes(1),
-             ty::Char => Size::from_bytes(4),
-             ty::Int(ity) => {
-                 Integer::from_attr(&tcx, SignedInt(ity)).size()
-             }
-             ty::Uint(uty) => {
-                 Integer::from_attr(&tcx, UnsignedInt(uty)).size()
-             }
-             _ => tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size,
-         };
+         let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
          // if `ty` does not depend on generic parameters, use an empty param_env
          self.eval(tcx, param_env).val.try_to_bits(size)
      }