Auto merge of #86266 - LeSeulArtichaut:box-thir-adt, r=davidtwco

Box `thir::ExprKind::Adt` for performance

`Adt` is the biggest variant in the enum and probably isn't used very often compared to the other expr kinds, so boxing it should be beneficial for performance. We need a perf test to be sure.
This commit is contained in:
bors 2021-06-16 20:00:17 +00:00
commit a85f584aeb
5 changed files with 43 additions and 26 deletions

View File

@ -97,6 +97,20 @@ pub struct Block {
pub safety_mode: BlockSafety, pub safety_mode: BlockSafety,
} }
#[derive(Debug, HashStable)]
pub struct Adt<'tcx> {
pub adt_def: &'tcx AdtDef,
pub variant_index: VariantIdx,
pub substs: SubstsRef<'tcx>,
/// Optional user-given substs: for something like `let x =
/// Bar::<T> { ... }`.
pub user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
pub fields: Box<[FieldExpr]>,
pub base: Option<FruInfo<'tcx>>,
}
#[derive(Copy, Clone, Debug, HashStable)] #[derive(Copy, Clone, Debug, HashStable)]
pub enum BlockSafety { pub enum BlockSafety {
Safe, Safe,
@ -145,7 +159,7 @@ pub enum StmtKind<'tcx> {
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Expr<'_>, 144); rustc_data_structures::static_assert_size!(Expr<'_>, 104);
/// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`) /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
/// into instances of this `Expr` enum. This lowering can be done /// into instances of this `Expr` enum. This lowering can be done
@ -304,18 +318,7 @@ pub enum ExprKind<'tcx> {
Tuple { Tuple {
fields: Box<[ExprId]>, fields: Box<[ExprId]>,
}, },
Adt { Adt(Box<Adt<'tcx>>),
adt_def: &'tcx AdtDef,
variant_index: VariantIdx,
substs: SubstsRef<'tcx>,
/// Optional user-given substs: for something like `let x =
/// Bar::<T> { ... }`.
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
fields: Box<[FieldExpr]>,
base: Option<FruInfo<'tcx>>,
},
PlaceTypeAscription { PlaceTypeAscription {
source: ExprId, source: ExprId,
/// Type that the user gave to this expression /// Type that the user gave to this expression

View File

@ -264,7 +264,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.cfg.push_assign(block, source_info, destination, address_of); this.cfg.push_assign(block, source_info, destination, address_of);
block.unit() block.unit()
} }
ExprKind::Adt { adt_def, variant_index, substs, user_ty, ref fields, ref base } => { ExprKind::Adt(box Adt {
adt_def,
variant_index,
substs,
user_ty,
ref fields,
ref base,
}) => {
// See the notes for `ExprKind::Array` in `as_rvalue` and for // See the notes for `ExprKind::Array` in `as_rvalue` and for
// `ExprKind::Borrow` above. // `ExprKind::Borrow` above.
let is_union = adt_def.is_union(); let is_union = adt_def.is_union();

View File

@ -195,14 +195,14 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => { ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => {
self.requires_unsafe(expr.span, UseOfInlineAssembly); self.requires_unsafe(expr.span, UseOfInlineAssembly);
} }
ExprKind::Adt { ExprKind::Adt(box Adt {
adt_def, adt_def,
variant_index: _, variant_index: _,
substs: _, substs: _,
user_ty: _, user_ty: _,
fields: _, fields: _,
base: _, base: _,
} => match self.tcx.layout_scalar_valid_range(adt_def.did) { }) => match self.tcx.layout_scalar_valid_range(adt_def.did) {
(Bound::Unbounded, Bound::Unbounded) => {} (Bound::Unbounded, Bound::Unbounded) => {}
_ => self.requires_unsafe(expr.span, InitializingTypeWith), _ => self.requires_unsafe(expr.span, InitializingTypeWith),
}, },

View File

@ -228,14 +228,14 @@ impl<'tcx> Cx<'tcx> {
expr: self.mirror_expr(e), expr: self.mirror_expr(e),
}) })
.collect(); .collect();
ExprKind::Adt { ExprKind::Adt(Box::new(Adt {
adt_def, adt_def,
substs, substs,
variant_index: index, variant_index: index,
fields: field_refs, fields: field_refs,
user_ty, user_ty,
base: None, base: None,
} }))
} else { } else {
ExprKind::Call { ExprKind::Call {
ty: self.typeck_results().node_type(fun.hir_id), ty: self.typeck_results().node_type(fun.hir_id),
@ -362,7 +362,7 @@ impl<'tcx> Cx<'tcx> {
let user_provided_types = self.typeck_results().user_provided_types(); let user_provided_types = self.typeck_results().user_provided_types();
let user_ty = user_provided_types.get(expr.hir_id).copied(); let user_ty = user_provided_types.get(expr.hir_id).copied();
debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty); debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
ExprKind::Adt { ExprKind::Adt(Box::new(Adt {
adt_def: adt, adt_def: adt,
variant_index: VariantIdx::new(0), variant_index: VariantIdx::new(0),
substs, substs,
@ -375,7 +375,7 @@ impl<'tcx> Cx<'tcx> {
.copied() .copied()
.collect(), .collect(),
}), }),
} }))
} }
AdtKind::Enum => { AdtKind::Enum => {
let res = self.typeck_results().qpath_res(qpath, expr.hir_id); let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
@ -388,14 +388,14 @@ impl<'tcx> Cx<'tcx> {
self.typeck_results().user_provided_types(); self.typeck_results().user_provided_types();
let user_ty = user_provided_types.get(expr.hir_id).copied(); let user_ty = user_provided_types.get(expr.hir_id).copied();
debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty); debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
ExprKind::Adt { ExprKind::Adt(Box::new(Adt {
adt_def: adt, adt_def: adt,
variant_index: index, variant_index: index,
substs, substs,
user_ty, user_ty,
fields: self.field_refs(fields), fields: self.field_refs(fields),
base: None, base: None,
} }))
} }
_ => { _ => {
span_bug!(expr.span, "unexpected res: {:?}", res); span_bug!(expr.span, "unexpected res: {:?}", res);
@ -906,14 +906,14 @@ impl<'tcx> Cx<'tcx> {
match ty.kind() { match ty.kind() {
// A unit struct/variant which is used as a value. // A unit struct/variant which is used as a value.
// We return a completely different ExprKind here to account for this special case. // We return a completely different ExprKind here to account for this special case.
ty::Adt(adt_def, substs) => ExprKind::Adt { ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(Adt {
adt_def, adt_def,
variant_index: adt_def.variant_index_with_ctor_id(def_id), variant_index: adt_def.variant_index_with_ctor_id(def_id),
substs, substs,
user_ty: user_provided_type, user_ty: user_provided_type,
fields: box [], fields: box [],
base: None, base: None,
}, })),
_ => bug!("unexpected ty: {:?}", ty), _ => bug!("unexpected ty: {:?}", ty),
} }
} }

View File

@ -1,4 +1,4 @@
use rustc_middle::thir::*; use rustc_middle::thir::{self, *};
use rustc_middle::ty::Const; use rustc_middle::ty::Const;
pub trait Visitor<'a, 'tcx: 'a>: Sized { pub trait Visitor<'a, 'tcx: 'a>: Sized {
@ -94,7 +94,14 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
visitor.visit_expr(&visitor.thir()[field]); visitor.visit_expr(&visitor.thir()[field]);
} }
} }
Adt { ref fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => { Adt(box thir::Adt {
ref fields,
ref base,
adt_def: _,
variant_index: _,
substs: _,
user_ty: _,
}) => {
for field in &**fields { for field in &**fields {
visitor.visit_expr(&visitor.thir()[field.expr]); visitor.visit_expr(&visitor.thir()[field.expr]);
} }