Reduce the size of hir::Expr.

From 104 bytes to 72 bytes on x86-64. This slightly reduces instruction
counts.

Also add an assertion about the size.
This commit is contained in:
Nicholas Nethercote 2019-02-07 16:03:57 +11:00
parent e544947278
commit 5d65e8cc7a
4 changed files with 23 additions and 10 deletions

View File

@ -3859,7 +3859,7 @@ impl<'a> LoweringContext<'a> {
hir::ExprKind::Call(f, args.iter().map(|x| self.lower_expr(x)).collect()) hir::ExprKind::Call(f, args.iter().map(|x| self.lower_expr(x)).collect())
} }
ExprKind::MethodCall(ref seg, ref args) => { ExprKind::MethodCall(ref seg, ref args) => {
let hir_seg = self.lower_path_segment( let hir_seg = P(self.lower_path_segment(
e.span, e.span,
seg, seg,
ParamMode::Optional, ParamMode::Optional,
@ -3867,7 +3867,7 @@ impl<'a> LoweringContext<'a> {
ParenthesizedGenericArgs::Err, ParenthesizedGenericArgs::Err,
ImplTraitContext::disallowed(), ImplTraitContext::disallowed(),
None, None,
); ));
let args = args.iter().map(|x| self.lower_expr(x)).collect(); let args = args.iter().map(|x| self.lower_expr(x)).collect();
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args) hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args)
} }
@ -4148,7 +4148,7 @@ impl<'a> LoweringContext<'a> {
node: if is_unit { node: if is_unit {
hir::ExprKind::Path(struct_path) hir::ExprKind::Path(struct_path)
} else { } else {
hir::ExprKind::Struct(struct_path, fields, None) hir::ExprKind::Struct(P(struct_path), fields, None)
}, },
span: e.span, span: e.span,
attrs: e.attrs.clone(), attrs: e.attrs.clone(),
@ -4220,13 +4220,13 @@ impl<'a> LoweringContext<'a> {
hir::ExprKind::InlineAsm(P(hir_asm), outputs, inputs) hir::ExprKind::InlineAsm(P(hir_asm), outputs, inputs)
} }
ExprKind::Struct(ref path, ref fields, ref maybe_expr) => hir::ExprKind::Struct( ExprKind::Struct(ref path, ref fields, ref maybe_expr) => hir::ExprKind::Struct(
self.lower_qpath( P(self.lower_qpath(
e.id, e.id,
&None, &None,
path, path,
ParamMode::Optional, ParamMode::Optional,
ImplTraitContext::disallowed(), ImplTraitContext::disallowed(),
), )),
fields.iter().map(|x| self.lower_field(x)).collect(), fields.iter().map(|x| self.lower_field(x)).collect(),
maybe_expr.as_ref().map(|x| P(self.lower_expr(x))), maybe_expr.as_ref().map(|x| P(self.lower_expr(x))),
), ),

View File

@ -1319,6 +1319,10 @@ pub struct Expr {
pub hir_id: HirId, pub hir_id: HirId,
} }
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::<Expr>() == 72);
impl Expr { impl Expr {
pub fn precedence(&self) -> ExprPrecedence { pub fn precedence(&self) -> ExprPrecedence {
match self.node { match self.node {
@ -1438,7 +1442,7 @@ pub enum ExprKind {
/// and the remaining elements are the rest of the arguments. /// and the remaining elements are the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
MethodCall(PathSegment, Span, HirVec<Expr>), MethodCall(P<PathSegment>, Span, HirVec<Expr>),
/// A tuple (e.g., `(a, b, c ,d)`). /// A tuple (e.g., `(a, b, c ,d)`).
Tup(HirVec<Expr>), Tup(HirVec<Expr>),
/// A binary operation (e.g., `a + b`, `a * b`). /// A binary operation (e.g., `a + b`, `a * b`).
@ -1506,7 +1510,7 @@ pub enum ExprKind {
/// ///
/// For example, `Foo {x: 1, y: 2}`, or /// For example, `Foo {x: 1, y: 2}`, or
/// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`. /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
Struct(QPath, HirVec<Field>, Option<P<Expr>>), Struct(P<QPath>, HirVec<Field>, Option<P<Expr>>),
/// An array literal constructed from one repeated element. /// An array literal constructed from one repeated element.
/// ///

View File

@ -614,11 +614,16 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
Some(def) if def != HirDef::Err => def, Some(def) if def != HirDef::Err => def,
_ => self.get_path_def(self.tcx.hir().get_parent_node(id)), _ => self.get_path_def(self.tcx.hir().get_parent_node(id)),
} }
}, }
Node::Expr(&hir::Expr { Node::Expr(&hir::Expr {
node: hir::ExprKind::Struct(ref qpath, ..), node: hir::ExprKind::Struct(ref qpath, ..),
.. ..
}) | }) => {
let hir_id = self.tcx.hir().node_to_hir_id(id);
self.tables.qpath_def(qpath, hir_id)
}
Node::Expr(&hir::Expr { Node::Expr(&hir::Expr {
node: hir::ExprKind::Path(ref qpath), node: hir::ExprKind::Path(ref qpath),
.. ..

View File

@ -430,7 +430,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match expr.node { match expr.node {
// All built-in range literals but `..=` and `..` desugar to Structs // All built-in range literals but `..=` and `..` desugar to Structs
ExprKind::Struct(QPath::Resolved(None, ref path), _, _) | ExprKind::Struct(ref qpath, _, _) => {
if let QPath::Resolved(None, ref path) = **qpath {
return is_range_path(&path) && span_is_range_literal(&expr.span);
}
}
// `..` desugars to its struct path // `..` desugars to its struct path
ExprKind::Path(QPath::Resolved(None, ref path)) => { ExprKind::Path(QPath::Resolved(None, ref path)) => {
return is_range_path(&path) && span_is_range_literal(&expr.span); return is_range_path(&path) && span_is_range_literal(&expr.span);