Skip to content

Commit b50e910

Browse files
committed
Auto merge of rust-lang#136593 - lukas-code:ty-value-perf, r=<try>
[perf] try to mitigate regression in fast reject for `ty::Value` rust-lang#136318 (comment) r? ghost
2 parents 64e06c0 + cd733ad commit b50e910

File tree

14 files changed

+143
-94
lines changed

14 files changed

+143
-94
lines changed

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+11-13
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_abi::{BackendRepr, VariantIdx};
22
use rustc_data_structures::stack::ensure_sufficient_stack;
33
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ReportedErrorInfo};
44
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
5-
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
5+
use rustc_middle::ty::{self, Ty, TyCtxt};
66
use rustc_middle::{bug, mir};
77
use rustc_span::DUMMY_SP;
88
use tracing::{debug, instrument, trace};
@@ -25,11 +25,13 @@ fn branches<'tcx>(
2525
variant: Option<VariantIdx>,
2626
num_nodes: &mut usize,
2727
) -> ValTreeCreationResult<'tcx> {
28+
let tcx = *ecx.tcx;
2829
let place = match variant {
2930
Some(variant) => ecx.project_downcast(place, variant).unwrap(),
3031
None => place.clone(),
3132
};
32-
let variant = variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
33+
let variant =
34+
variant.map(|variant| Some(ty::ValTree::from_scalar_int(tcx, variant.as_u32().into())));
3335
debug!(?place, ?variant);
3436

3537
let mut fields = Vec::with_capacity(n);
@@ -52,7 +54,7 @@ fn branches<'tcx>(
5254
*num_nodes += 1;
5355
}
5456

55-
Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches)))
57+
Ok(ty::ValTree::from_branches(tcx, branches))
5658
}
5759

5860
#[instrument(skip(ecx), level = "debug")]
@@ -70,7 +72,7 @@ fn slice_branches<'tcx>(
7072
elems.push(valtree);
7173
}
7274

73-
Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(elems)))
75+
Ok(ty::ValTree::from_branches(*ecx.tcx, elems))
7476
}
7577

7678
#[instrument(skip(ecx), level = "debug")]
@@ -79,6 +81,7 @@ fn const_to_valtree_inner<'tcx>(
7981
place: &MPlaceTy<'tcx>,
8082
num_nodes: &mut usize,
8183
) -> ValTreeCreationResult<'tcx> {
84+
let tcx = *ecx.tcx;
8285
let ty = place.layout.ty;
8386
debug!("ty kind: {:?}", ty.kind());
8487

@@ -89,14 +92,14 @@ fn const_to_valtree_inner<'tcx>(
8992
match ty.kind() {
9093
ty::FnDef(..) => {
9194
*num_nodes += 1;
92-
Ok(ty::ValTree::zst())
95+
Ok(ty::ValTree::zst(tcx))
9396
}
9497
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
9598
let val = ecx.read_immediate(place).unwrap();
9699
let val = val.to_scalar_int().unwrap();
97100
*num_nodes += 1;
98101

99-
Ok(ty::ValTree::Leaf(val))
102+
Ok(ty::ValTree::from_scalar_int(tcx, val))
100103
}
101104

102105
ty::Pat(base, ..) => {
@@ -127,7 +130,7 @@ fn const_to_valtree_inner<'tcx>(
127130
return Err(ValTreeCreationError::NonSupportedType(ty));
128131
};
129132
// It's just a ScalarInt!
130-
Ok(ty::ValTree::Leaf(val))
133+
Ok(ty::ValTree::from_scalar_int(tcx, val))
131134
}
132135

133136
// Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
@@ -291,12 +294,7 @@ pub fn valtree_to_const_value<'tcx>(
291294
mir::ConstValue::ZeroSized
292295
}
293296
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char | ty::RawPtr(_, _) => {
294-
match cv.valtree {
295-
ty::ValTree::Leaf(scalar_int) => mir::ConstValue::Scalar(Scalar::Int(scalar_int)),
296-
ty::ValTree::Branch(_) => bug!(
297-
"ValTrees for Bool, Int, Uint, Float, Char or RawPtr should have the form ValTree::Leaf"
298-
),
299-
}
297+
mir::ConstValue::Scalar(Scalar::Int(cv.valtree.unwrap_leaf()))
300298
}
301299
ty::Pat(ty, _) => {
302300
let cv = ty::Value { valtree: cv.valtree, ty };

compiler/rustc_middle/src/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ macro_rules! arena_types {
9090
[] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem,
9191
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::Symbol>,
9292
[] pats: rustc_middle::ty::PatternKind<'tcx>,
93+
[] valtree: rustc_middle::ty::ValTreeData<'tcx>,
9394

9495
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
9596
// since we need to allocate this type on both the `rustc_hir` arena

compiler/rustc_middle/src/ty/codec.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Pattern<'tcx> {
147147
}
148148
}
149149

150+
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::ValTree<'tcx> {
151+
fn encode(&self, e: &mut E) {
152+
self.0.0.encode(e);
153+
}
154+
}
155+
150156
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ConstAllocation<'tcx> {
151157
fn encode(&self, e: &mut E) {
152158
self.inner().encode(e)
@@ -356,12 +362,9 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Pattern<'tcx> {
356362
}
357363
}
358364

359-
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] {
360-
fn decode(decoder: &mut D) -> &'tcx Self {
361-
decoder
362-
.interner()
363-
.arena
364-
.alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
365+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::ValTree<'tcx> {
366+
fn decode(decoder: &mut D) -> Self {
367+
decoder.interner().mk_valtree(Decodable::decode(decoder))
365368
}
366369
}
367370

compiler/rustc_middle/src/ty/consts.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
2020
pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
2121

2222
#[cfg(target_pointer_width = "64")]
23-
rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
23+
rustc_data_structures::static_assert_size!(ConstKind<'_>, 24);
2424

2525
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
2626
#[rustc_pass_by_value]
@@ -190,15 +190,15 @@ impl<'tcx> Const<'tcx> {
190190
.size;
191191
ty::Const::new_value(
192192
tcx,
193-
ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()),
193+
ty::ValTree::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap()),
194194
ty,
195195
)
196196
}
197197

198198
#[inline]
199199
/// Creates an interned zst constant.
200200
pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
201-
ty::Const::new_value(tcx, ty::ValTree::zst(), ty)
201+
ty::Const::new_value(tcx, ty::ValTree::zst(tcx), ty)
202202
}
203203

204204
#[inline]

compiler/rustc_middle/src/ty/consts/valtree.rs

+60-25
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use std::ops::Deref;
2+
3+
use rustc_data_structures::intern::Interned;
14
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
25

36
use super::ScalarInt;
@@ -16,9 +19,9 @@ use crate::ty::{self, Ty, TyCtxt};
1619
///
1720
/// `ValTree` does not have this problem with representation, as it only contains integers or
1821
/// lists of (nested) `ValTree`.
19-
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
22+
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
2023
#[derive(HashStable, TyEncodable, TyDecodable)]
21-
pub enum ValTree<'tcx> {
24+
pub enum ValTreeData<'tcx> {
2225
/// integers, `bool`, `char` are represented as scalars.
2326
/// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values
2427
/// of these types have the same representation.
@@ -33,50 +36,82 @@ pub enum ValTree<'tcx> {
3336
/// the fields of the variant.
3437
///
3538
/// ZST types are represented as an empty slice.
36-
Branch(&'tcx [ValTree<'tcx>]),
39+
Branch(Box<[ValTree<'tcx>]>),
3740
}
3841

39-
impl<'tcx> ValTree<'tcx> {
40-
pub fn zst() -> Self {
41-
Self::Branch(&[])
42-
}
43-
42+
impl<'tcx> ValTreeData<'tcx> {
4443
#[inline]
45-
pub fn unwrap_leaf(self) -> ScalarInt {
44+
pub fn unwrap_leaf(&self) -> ScalarInt {
4645
match self {
47-
Self::Leaf(s) => s,
46+
Self::Leaf(s) => *s,
4847
_ => bug!("expected leaf, got {:?}", self),
4948
}
5049
}
5150

5251
#[inline]
53-
pub fn unwrap_branch(self) -> &'tcx [Self] {
52+
pub fn unwrap_branch(&self) -> &[ValTree<'tcx>] {
5453
match self {
55-
Self::Branch(branch) => branch,
54+
Self::Branch(branch) => &**branch,
5655
_ => bug!("expected branch, got {:?}", self),
5756
}
5857
}
5958

60-
pub fn from_raw_bytes<'a>(tcx: TyCtxt<'tcx>, bytes: &'a [u8]) -> Self {
61-
let branches = bytes.iter().map(|b| Self::Leaf(ScalarInt::from(*b)));
62-
let interned = tcx.arena.alloc_from_iter(branches);
59+
pub fn try_to_scalar(&self) -> Option<Scalar> {
60+
self.try_to_scalar_int().map(Scalar::Int)
61+
}
6362

64-
Self::Branch(interned)
63+
pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
64+
match self {
65+
Self::Leaf(s) => Some(*s),
66+
Self::Branch(_) => None,
67+
}
6568
}
6669

67-
pub fn from_scalar_int(i: ScalarInt) -> Self {
68-
Self::Leaf(i)
70+
pub fn try_to_branch(&self) -> Option<&[ValTree<'tcx>]> {
71+
match self {
72+
Self::Branch(branch) => Some(&**branch),
73+
Self::Leaf(_) => None,
74+
}
6975
}
76+
}
7077

71-
pub fn try_to_scalar(self) -> Option<Scalar> {
72-
self.try_to_scalar_int().map(Scalar::Int)
78+
/// An interned valtree. Use this rather than `ValTreeData`, whenever possible.
79+
///
80+
/// See the docs of [`ValTreeData`] or the [dev guide] for an explanation of this type.
81+
///
82+
/// [dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html#valtrees
83+
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
84+
#[derive(HashStable)]
85+
pub struct ValTree<'tcx>(pub(crate) Interned<'tcx, ValTreeData<'tcx>>);
86+
87+
impl<'tcx> ValTree<'tcx> {
88+
pub fn zst(tcx: TyCtxt<'tcx>) -> Self {
89+
tcx.consts.valtree_zst
7390
}
7491

75-
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
76-
match self {
77-
Self::Leaf(s) => Some(s),
78-
Self::Branch(_) => None,
79-
}
92+
pub fn is_zst(self) -> bool {
93+
matches!(*self, ValTreeData::Branch(box []))
94+
}
95+
96+
pub fn from_raw_bytes(tcx: TyCtxt<'tcx>, bytes: &[u8]) -> Self {
97+
let branches = bytes.iter().map(|b| tcx.mk_valtree(ValTreeData::Leaf(ScalarInt::from(*b))));
98+
Self::from_branches(tcx, branches)
99+
}
100+
101+
pub fn from_branches(tcx: TyCtxt<'tcx>, branches: impl IntoIterator<Item = Self>) -> Self {
102+
tcx.mk_valtree(ValTreeData::Branch(branches.into_iter().collect()))
103+
}
104+
105+
pub fn from_scalar_int(tcx: TyCtxt<'tcx>, i: ScalarInt) -> Self {
106+
tcx.mk_valtree(ValTreeData::Leaf(i))
107+
}
108+
}
109+
110+
impl<'tcx> Deref for ValTree<'tcx> {
111+
type Target = &'tcx ValTreeData<'tcx>;
112+
113+
fn deref(&self) -> &&'tcx ValTreeData<'tcx> {
114+
&self.0.0
80115
}
81116
}
82117

compiler/rustc_middle/src/ty/context.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ use crate::ty::{
8080
GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, ParamTy,
8181
Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind,
8282
PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
83-
Visibility,
83+
ValTree, ValTreeData, Visibility,
8484
};
8585

8686
#[allow(rustc::usage_of_ty_tykind)]
@@ -798,6 +798,7 @@ pub struct CtxtInterners<'tcx> {
798798
local_def_ids: InternedSet<'tcx, List<LocalDefId>>,
799799
captures: InternedSet<'tcx, List<&'tcx ty::CapturedPlace<'tcx>>>,
800800
offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>,
801+
valtree: InternedSet<'tcx, ty::ValTreeData<'tcx>>,
801802
}
802803

803804
impl<'tcx> CtxtInterners<'tcx> {
@@ -827,6 +828,7 @@ impl<'tcx> CtxtInterners<'tcx> {
827828
local_def_ids: Default::default(),
828829
captures: Default::default(),
829830
offset_of: Default::default(),
831+
valtree: Default::default(),
830832
}
831833
}
832834

@@ -1018,6 +1020,8 @@ pub struct CommonConsts<'tcx> {
10181020
pub unit: Const<'tcx>,
10191021
pub true_: Const<'tcx>,
10201022
pub false_: Const<'tcx>,
1023+
/// Use [`ty::ValTree::zst`] instead.
1024+
pub(crate) valtree_zst: ValTree<'tcx>,
10211025
}
10221026

10231027
impl<'tcx> CommonTypes<'tcx> {
@@ -1118,19 +1122,30 @@ impl<'tcx> CommonConsts<'tcx> {
11181122
)
11191123
};
11201124

1125+
let mk_valtree = |v| {
1126+
ty::ValTree(Interned::new_unchecked(
1127+
interners.valtree.intern(v, |v| InternedInSet(interners.arena.alloc(v))).0,
1128+
))
1129+
};
1130+
1131+
let valtree_zst = mk_valtree(ty::ValTreeData::Branch(Box::default()));
1132+
let valtree_true = mk_valtree(ty::ValTreeData::Leaf(ty::ScalarInt::TRUE));
1133+
let valtree_false = mk_valtree(ty::ValTreeData::Leaf(ty::ScalarInt::FALSE));
1134+
11211135
CommonConsts {
11221136
unit: mk_const(ty::ConstKind::Value(ty::Value {
11231137
ty: types.unit,
1124-
valtree: ty::ValTree::zst(),
1138+
valtree: valtree_zst,
11251139
})),
11261140
true_: mk_const(ty::ConstKind::Value(ty::Value {
11271141
ty: types.bool,
1128-
valtree: ty::ValTree::Leaf(ty::ScalarInt::TRUE),
1142+
valtree: valtree_true,
11291143
})),
11301144
false_: mk_const(ty::ConstKind::Value(ty::Value {
11311145
ty: types.bool,
1132-
valtree: ty::ValTree::Leaf(ty::ScalarInt::FALSE),
1146+
valtree: valtree_false,
11331147
})),
1148+
valtree_zst,
11341149
}
11351150
}
11361151
}
@@ -2533,6 +2548,7 @@ direct_interners! {
25332548
ExternalConstraints -> ExternalConstraints<'tcx>,
25342549
predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData<TyCtxt<'tcx>>):
25352550
PredefinedOpaques -> PredefinedOpaques<'tcx>,
2551+
valtree: pub mk_valtree(ValTreeData<'tcx>): ValTree -> ValTree<'tcx>,
25362552
}
25372553

25382554
macro_rules! slice_interners {

compiler/rustc_middle/src/ty/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ pub use self::closure::{
6060
place_to_string_for_capture,
6161
};
6262
pub use self::consts::{
63-
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, Value,
63+
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeData,
64+
Value,
6465
};
6566
pub use self::context::{
6667
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,

0 commit comments

Comments
 (0)