Skip to content

Commit c04c7e3

Browse files
committed
Do not compute actual aggregate type.
1 parent e224bd7 commit c04c7e3

File tree

1 file changed

+47
-11
lines changed
  • compiler/rustc_mir_transform/src

1 file changed

+47
-11
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
use rustc_const_eval::interpret::{ImmTy, InterpCx, MemPlaceMeta, OpTy, Projectable, Scalar};
5757
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
5858
use rustc_data_structures::graph::dominators::Dominators;
59+
use rustc_hir::def::DefKind;
5960
use rustc_index::bit_set::BitSet;
6061
use rustc_index::IndexVec;
6162
use rustc_macros::newtype_index;
@@ -64,6 +65,7 @@ use rustc_middle::mir::visit::*;
6465
use rustc_middle::mir::*;
6566
use rustc_middle::ty::layout::LayoutOf;
6667
use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut};
68+
use rustc_span::def_id::DefId;
6769
use rustc_span::DUMMY_SP;
6870
use rustc_target::abi::{self, Abi, Size, VariantIdx, FIRST_VARIANT};
6971
use std::borrow::Cow;
@@ -136,6 +138,16 @@ newtype_index! {
136138
struct VnIndex {}
137139
}
138140

141+
/// Computing the aggregate's type can be quite slow, so we only keep the minimal amount of
142+
/// information to reconstruct it when needed.
143+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
144+
enum AggregateTy<'tcx> {
145+
/// Invariant: this must not be used for an empty array.
146+
Array,
147+
Tuple,
148+
Def(DefId, ty::GenericArgsRef<'tcx>),
149+
}
150+
139151
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
140152
enum AddressKind {
141153
Ref(BorrowKind),
@@ -152,7 +164,7 @@ enum Value<'tcx> {
152164
Constant(Const<'tcx>),
153165
/// An aggregate value, either tuple/closure/struct/enum.
154166
/// This does not contain unions, as we cannot reason with the value.
155-
Aggregate(Ty<'tcx>, VariantIdx, Vec<VnIndex>),
167+
Aggregate(AggregateTy<'tcx>, VariantIdx, Vec<VnIndex>),
156168
/// This corresponds to a `[value; count]` expression.
157169
Repeat(VnIndex, ty::Const<'tcx>),
158170
/// The address of a place.
@@ -289,11 +301,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
289301
Repeat(..) => return None,
290302

291303
Constant(ref constant) => self.ecx.eval_mir_constant(constant, None, None).ok()?,
292-
Aggregate(ty, variant, ref fields) => {
304+
Aggregate(kind, variant, ref fields) => {
293305
let fields = fields
294306
.iter()
295307
.map(|&f| self.evaluated[f].as_ref())
296308
.collect::<Option<Vec<_>>>()?;
309+
let ty = match kind {
310+
AggregateTy::Array => {
311+
assert!(fields.len() > 0);
312+
Ty::new_array(self.tcx, fields[0].layout.ty, fields.len() as u64)
313+
}
314+
AggregateTy::Tuple => {
315+
Ty::new_tup_from_iter(self.tcx, fields.iter().map(|f| f.layout.ty))
316+
}
317+
AggregateTy::Def(def_id, args) => {
318+
self.tcx.type_of(def_id).instantiate(self.tcx, args)
319+
}
320+
};
297321
let variant = if ty.is_enum() { Some(variant) } else { None };
298322
let ty = self.ecx.layout_of(ty).ok()?;
299323
if ty.is_zst() {
@@ -510,7 +534,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
510534
Value::Repeat(inner, _) => {
511535
return Some(*inner);
512536
}
513-
Value::Aggregate(ty, _, operands) if ty.is_array() => {
537+
Value::Aggregate(AggregateTy::Array, _, operands) => {
514538
let offset = if from_end {
515539
operands.len() - offset as usize
516540
} else {
@@ -659,20 +683,30 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
659683
}
660684
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
661685
Rvalue::Aggregate(box ref kind, ref mut fields) => {
662-
let variant_index = match *kind {
663-
AggregateKind::Array(..)
664-
| AggregateKind::Tuple
665-
| AggregateKind::Closure(..)
666-
| AggregateKind::Generator(..) => FIRST_VARIANT,
667-
AggregateKind::Adt(_, variant_index, _, _, None) => variant_index,
686+
let (ty, variant_index) = match *kind {
687+
// For empty arrays, we have not mean to recover the type. They are ZSTs
688+
// anyway, so return them as such.
689+
AggregateKind::Array(..) | AggregateKind::Tuple if fields.is_empty() => {
690+
return Some(self.insert(Value::Constant(Const::zero_sized(
691+
rvalue.ty(self.local_decls, self.tcx),
692+
))));
693+
}
694+
AggregateKind::Array(..) => (AggregateTy::Array, FIRST_VARIANT),
695+
AggregateKind::Tuple => (AggregateTy::Tuple, FIRST_VARIANT),
696+
AggregateKind::Closure(did, substs)
697+
| AggregateKind::Generator(did, substs, _) => {
698+
(AggregateTy::Def(did, substs), FIRST_VARIANT)
699+
}
700+
AggregateKind::Adt(did, variant_index, substs, _, None) => {
701+
(AggregateTy::Def(did, substs), variant_index)
702+
}
668703
// Do not track unions.
669704
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
670705
};
671706
let fields: Option<Vec<_>> = fields
672707
.iter_mut()
673708
.map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
674709
.collect();
675-
let ty = rvalue.ty(self.local_decls, self.tcx);
676710
Value::Aggregate(ty, variant_index, fields?)
677711
}
678712
Rvalue::Ref(_, borrow_kind, ref mut place) => {
@@ -725,8 +759,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
725759

726760
fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> {
727761
if let Value::Aggregate(enum_ty, variant, _) = *self.get(place)
728-
&& enum_ty.is_enum()
762+
&& let AggregateTy::Def(enum_did, enum_substs) = enum_ty
763+
&& let DefKind::Enum = self.tcx.def_kind(enum_did)
729764
{
765+
let enum_ty = self.tcx.type_of(enum_did).instantiate(self.tcx, enum_substs);
730766
let discr = self.ecx.discriminant_for_variant(enum_ty, variant).ok()?;
731767
return Some(self.insert_scalar(discr.to_scalar(), discr.layout.ty));
732768
}

0 commit comments

Comments
 (0)