Skip to content

Commit 06c6e75

Browse files
Optimize try_eval_bits to avoid layout queries
This specifically targets match checking, but is possibly more widely useful as well. In code with large, single-value match statements, we were previously spending a lot of time running layout_of for the primitive types (integers, chars) -- which is essentially useless. This optimizes the code to avoid those query calls by directly obtaining the size for these types, when possible. It may be worth considering adding a `size_of` query in the future which might be far faster, especially if specialized for "const" cases -- match arms being the most obvious example. It's possibly such a function would benefit from *not* being a query as well, since it's trivially evaluatable from the sty for many cases whereas a query needs to hash the input and such.
1 parent 06c6894 commit 06c6e75

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

src/librustc/ty/sty.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_macros::HashStable;
1313
use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, GenericArg, GenericArgKind};
1414
use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable};
1515
use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
16-
use crate::ty::layout::VariantIdx;
16+
use crate::ty::layout::{Size, Integer, IntegerExt, VariantIdx};
1717
use crate::util::captures::Captures;
1818
use crate::mir::interpret::{Scalar, GlobalId};
1919

@@ -24,6 +24,7 @@ use std::marker::PhantomData;
2424
use std::ops::Range;
2525
use rustc_target::spec::abi;
2626
use syntax::ast::{self, Ident};
27+
use syntax::attr::{SignedInt, UnsignedInt};
2728
use syntax::symbol::{kw, InternedString};
2829

2930
use self::InferTy::*;
@@ -2298,8 +2299,21 @@ impl<'tcx> Const<'tcx> {
22982299
ty: Ty<'tcx>,
22992300
) -> Option<u128> {
23002301
assert_eq!(self.ty, ty);
2302+
// This is purely an optimization -- layout_of is a pretty expensive operation,
2303+
// but if we can determine the size without calling it, we don't need all that complexity
2304+
// (hashing, caching, etc.). As such, try to skip it.
2305+
let size = match ty.kind {
2306+
ty::Bool => Size::from_bytes(1),
2307+
ty::Char => Size::from_bytes(4),
2308+
ty::Int(ity) => {
2309+
Integer::from_attr(&tcx, SignedInt(ity)).size()
2310+
}
2311+
ty::Uint(uty) => {
2312+
Integer::from_attr(&tcx, UnsignedInt(uty)).size()
2313+
}
2314+
_ => tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size,
2315+
};
23012316
// if `ty` does not depend on generic parameters, use an empty param_env
2302-
let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
23032317
self.eval(tcx, param_env).val.try_to_bits(size)
23042318
}
23052319

0 commit comments

Comments
 (0)