Skip to content

Commit e58d794

Browse files
committed
Do not compute actual aggregate type.
1 parent 405bed9 commit e58d794

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

+47-11
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;
@@ -129,6 +131,16 @@ newtype_index! {
129131
struct VnIndex {}
130132
}
131133

134+
/// Computing the aggregate's type can be quite slow, so we only keep the minimal amount of
135+
/// information to reconstruct it when needed.
136+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
137+
enum AggregateTy<'tcx> {
138+
/// Invariant: this must not be used for an empty array.
139+
Array,
140+
Tuple,
141+
Def(DefId, ty::GenericArgsRef<'tcx>),
142+
}
143+
132144
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
133145
enum AddressKind {
134146
Ref(BorrowKind),
@@ -145,7 +157,7 @@ enum Value<'tcx> {
145157
Constant(Const<'tcx>),
146158
/// An aggregate value, either tuple/closure/struct/enum.
147159
/// This does not contain unions, as we cannot reason with the value.
148-
Aggregate(Ty<'tcx>, VariantIdx, Vec<VnIndex>),
160+
Aggregate(AggregateTy<'tcx>, VariantIdx, Vec<VnIndex>),
149161
/// This corresponds to a `[value; count]` expression.
150162
Repeat(VnIndex, ty::Const<'tcx>),
151163
/// The address of a place.
@@ -282,11 +294,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
282294
Repeat(..) => return None,
283295

284296
Constant(ref constant) => self.ecx.eval_mir_constant(constant, None, None).ok()?,
285-
Aggregate(ty, variant, ref fields) => {
297+
Aggregate(kind, variant, ref fields) => {
286298
let fields = fields
287299
.iter()
288300
.map(|&f| self.evaluated[f].as_ref())
289301
.collect::<Option<Vec<_>>>()?;
302+
let ty = match kind {
303+
AggregateTy::Array => {
304+
assert!(fields.len() > 0);
305+
Ty::new_array(self.tcx, fields[0].layout.ty, fields.len() as u64)
306+
}
307+
AggregateTy::Tuple => {
308+
Ty::new_tup_from_iter(self.tcx, fields.iter().map(|f| f.layout.ty))
309+
}
310+
AggregateTy::Def(def_id, args) => {
311+
self.tcx.type_of(def_id).instantiate(self.tcx, args)
312+
}
313+
};
290314
let variant = if ty.is_enum() { Some(variant) } else { None };
291315
let ty = self.ecx.layout_of(ty).ok()?;
292316
if ty.is_zst() {
@@ -502,7 +526,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
502526
Value::Repeat(inner, _) => {
503527
return Some(*inner);
504528
}
505-
Value::Aggregate(ty, _, operands) if ty.is_array() => {
529+
Value::Aggregate(AggregateTy::Array, _, operands) => {
506530
let offset = if from_end {
507531
operands.len() - offset as usize
508532
} else {
@@ -650,20 +674,30 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
650674
}
651675
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
652676
Rvalue::Aggregate(box ref kind, ref mut fields) => {
653-
let variant_index = match *kind {
654-
AggregateKind::Array(..)
655-
| AggregateKind::Tuple
656-
| AggregateKind::Closure(..)
657-
| AggregateKind::Generator(..) => FIRST_VARIANT,
658-
AggregateKind::Adt(_, variant_index, _, _, None) => variant_index,
677+
let (ty, variant_index) = match *kind {
678+
// For empty arrays, we have not mean to recover the type. They are ZSTs
679+
// anyway, so return them as such.
680+
AggregateKind::Array(..) | AggregateKind::Tuple if fields.is_empty() => {
681+
return Some(self.insert(Value::Constant(Const::zero_sized(
682+
rvalue.ty(self.local_decls, self.tcx),
683+
))));
684+
}
685+
AggregateKind::Array(..) => (AggregateTy::Array, FIRST_VARIANT),
686+
AggregateKind::Tuple => (AggregateTy::Tuple, FIRST_VARIANT),
687+
AggregateKind::Closure(did, substs)
688+
| AggregateKind::Generator(did, substs, _) => {
689+
(AggregateTy::Def(did, substs), FIRST_VARIANT)
690+
}
691+
AggregateKind::Adt(did, variant_index, substs, _, None) => {
692+
(AggregateTy::Def(did, substs), variant_index)
693+
}
659694
// Do not track unions.
660695
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
661696
};
662697
let fields: Option<Vec<_>> = fields
663698
.iter_mut()
664699
.map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
665700
.collect();
666-
let ty = rvalue.ty(self.local_decls, self.tcx);
667701
Value::Aggregate(ty, variant_index, fields?)
668702
}
669703
Rvalue::Ref(_, borrow_kind, ref mut place) => {
@@ -716,8 +750,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
716750

717751
fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> {
718752
if let Value::Aggregate(enum_ty, variant, _) = *self.get(place)
719-
&& enum_ty.is_enum()
753+
&& let AggregateTy::Def(enum_did, enum_substs) = enum_ty
754+
&& let DefKind::Enum = self.tcx.def_kind(enum_did)
720755
{
756+
let enum_ty = self.tcx.type_of(enum_did).instantiate(self.tcx, enum_substs);
721757
let discr = self.ecx.discriminant_for_variant(enum_ty, variant).ok()?;
722758
return Some(self.insert_scalar(discr.to_scalar(), discr.layout.ty));
723759
}

0 commit comments

Comments
 (0)