Skip to content

Commit 94fe18f

Browse files
committed
Use a specialized varint + bitpacking scheme for DepGraph encoding
1 parent bf1e3f3 commit 94fe18f

File tree

8 files changed

+358
-46
lines changed

8 files changed

+358
-46
lines changed

compiler/rustc_middle/src/dep_graph/dep_node.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ macro_rules! define_dep_nodes {
9797
// discriminants of the variants have been assigned consecutively from 0
9898
// so that just the one comparison suffices to check that the u16 can be
9999
// transmuted to a DepKind.
100-
const VARIANTS: u16 = {
100+
pub const VARIANTS: u16 = {
101101
let deps: &[DepKind] = &[$(DepKind::$variant,)*];
102102
let mut i = 0;
103103
while i < deps.len() {

compiler/rustc_middle/src/dep_graph/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub type DepKindStruct<'tcx> = rustc_query_system::dep_graph::DepKindStruct<TyCt
2626
impl rustc_query_system::dep_graph::DepKind for DepKind {
2727
const NULL: Self = DepKind::Null;
2828
const RED: Self = DepKind::Red;
29+
const MAX: u16 = DepKind::VARIANTS - 1;
2930

3031
fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3132
write!(f, "{:?}(", node.kind)?;
@@ -68,6 +69,21 @@ impl rustc_query_system::dep_graph::DepKind for DepKind {
6869
op(icx.task_deps)
6970
})
7071
}
72+
73+
#[track_caller]
74+
#[inline]
75+
fn from_u16(u: u16) -> Self {
76+
if u > Self::MAX {
77+
panic!("Invalid DepKind {u}");
78+
}
79+
// SAFETY: See comment on DepKind::VARIANTS
80+
unsafe { std::mem::transmute(u) }
81+
}
82+
83+
#[inline]
84+
fn to_u16(self) -> u16 {
85+
self as u16
86+
}
7187
}
7288

7389
impl<'tcx> DepContext for TyCtxt<'tcx> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use crate::dep_graph::DepNodeIndex;
2+
use smallvec::SmallVec;
3+
use std::hash::{Hash, Hasher};
4+
use std::ops::Deref;
5+
6+
#[derive(Default, Debug)]
7+
pub struct EdgesVec {
8+
max: u32,
9+
edges: SmallVec<[DepNodeIndex; EdgesVec::INLINE_CAPACITY]>,
10+
}
11+
12+
impl Hash for EdgesVec {
13+
#[inline]
14+
fn hash<H: Hasher>(&self, hasher: &mut H) {
15+
Hash::hash(&self.edges, hasher)
16+
}
17+
}
18+
19+
impl EdgesVec {
20+
pub const INLINE_CAPACITY: usize = 8;
21+
22+
#[inline]
23+
pub fn new() -> Self {
24+
Self::default()
25+
}
26+
27+
#[inline]
28+
pub fn push(&mut self, edge: DepNodeIndex) {
29+
self.max = self.max.max(edge.as_u32());
30+
self.edges.push(edge);
31+
}
32+
33+
#[inline]
34+
pub fn max_index(&self) -> u32 {
35+
self.max
36+
}
37+
}
38+
39+
impl Deref for EdgesVec {
40+
type Target = [DepNodeIndex];
41+
42+
#[inline]
43+
fn deref(&self) -> &Self::Target {
44+
self.edges.as_slice()
45+
}
46+
}
47+
48+
impl FromIterator<DepNodeIndex> for EdgesVec {
49+
#[inline]
50+
fn from_iter<T>(iter: T) -> Self
51+
where
52+
T: IntoIterator<Item = DepNodeIndex>,
53+
{
54+
let mut vec = EdgesVec::new();
55+
for index in iter {
56+
vec.push(index)
57+
}
58+
vec
59+
}
60+
}

compiler/rustc_query_system/src/dep_graph/graph.rs

+15-16
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
88
use rustc_data_structures::unord::UnordMap;
99
use rustc_index::IndexVec;
1010
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
11-
use smallvec::{smallvec, SmallVec};
1211
use std::assert_matches::assert_matches;
1312
use std::collections::hash_map::Entry;
1413
use std::fmt::Debug;
@@ -19,6 +18,7 @@ use std::sync::atomic::Ordering::Relaxed;
1918
use super::query::DepGraphQuery;
2019
use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex};
2120
use super::{DepContext, DepKind, DepNode, HasDepContext, WorkProductId};
21+
use crate::dep_graph::EdgesVec;
2222
use crate::ich::StableHashingContext;
2323
use crate::query::{QueryContext, QuerySideEffects};
2424

@@ -137,7 +137,7 @@ impl<K: DepKind> DepGraph<K> {
137137
let _green_node_index = current.intern_new_node(
138138
profiler,
139139
DepNode { kind: DepKind::NULL, hash: current.anon_id_seed.into() },
140-
smallvec![],
140+
EdgesVec::new(),
141141
Fingerprint::ZERO,
142142
);
143143
assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
@@ -147,7 +147,7 @@ impl<K: DepKind> DepGraph<K> {
147147
profiler,
148148
&prev_graph,
149149
DepNode { kind: DepKind::RED, hash: Fingerprint::ZERO.into() },
150-
smallvec![],
150+
EdgesVec::new(),
151151
None,
152152
false,
153153
);
@@ -356,12 +356,12 @@ impl<K: DepKind> DepGraphData<K> {
356356

357357
let with_deps = |task_deps| K::with_deps(task_deps, || task(cx, arg));
358358
let (result, edges) = if cx.dep_context().is_eval_always(key.kind) {
359-
(with_deps(TaskDepsRef::EvalAlways), smallvec![])
359+
(with_deps(TaskDepsRef::EvalAlways), EdgesVec::new())
360360
} else {
361361
let task_deps = Lock::new(TaskDeps {
362362
#[cfg(debug_assertions)]
363363
node: Some(key),
364-
reads: SmallVec::new(),
364+
reads: EdgesVec::new(),
365365
read_set: Default::default(),
366366
phantom_data: PhantomData,
367367
});
@@ -486,14 +486,14 @@ impl<K: DepKind> DepGraph<K> {
486486

487487
// As long as we only have a low number of reads we can avoid doing a hash
488488
// insert and potentially allocating/reallocating the hashmap
489-
let new_read = if task_deps.reads.len() < TASK_DEPS_READS_CAP {
489+
let new_read = if task_deps.reads.len() < EdgesVec::INLINE_CAPACITY {
490490
task_deps.reads.iter().all(|other| *other != dep_node_index)
491491
} else {
492492
task_deps.read_set.insert(dep_node_index)
493493
};
494494
if new_read {
495495
task_deps.reads.push(dep_node_index);
496-
if task_deps.reads.len() == TASK_DEPS_READS_CAP {
496+
if task_deps.reads.len() == EdgesVec::INLINE_CAPACITY {
497497
// Fill `read_set` with what we have so far so we can use the hashset
498498
// next time
499499
task_deps.read_set.extend(task_deps.reads.iter().copied());
@@ -572,9 +572,13 @@ impl<K: DepKind> DepGraph<K> {
572572
}
573573
}
574574

575-
let mut edges = SmallVec::new();
575+
let mut edges = EdgesVec::new();
576576
K::read_deps(|task_deps| match task_deps {
577-
TaskDepsRef::Allow(deps) => edges.extend(deps.lock().reads.iter().copied()),
577+
TaskDepsRef::Allow(deps) => {
578+
for index in deps.lock().reads.iter().copied() {
579+
edges.push(index);
580+
}
581+
}
578582
TaskDepsRef::EvalAlways => {
579583
edges.push(DepNodeIndex::FOREVER_RED_NODE);
580584
}
@@ -872,7 +876,7 @@ impl<K: DepKind> DepGraphData<K> {
872876

873877
let prev_deps = self.previous.edge_targets_from(prev_dep_node_index);
874878

875-
for &dep_dep_node_index in prev_deps {
879+
for dep_dep_node_index in prev_deps {
876880
self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node, Some(&frame))?;
877881
}
878882

@@ -1308,8 +1312,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
13081312
let key = prev_graph.index_to_node(prev_index);
13091313
let edges = prev_graph
13101314
.edge_targets_from(prev_index)
1311-
.iter()
1312-
.map(|i| prev_index_to_index[*i].unwrap())
1315+
.map(|i| prev_index_to_index[i].unwrap())
13131316
.collect();
13141317
let fingerprint = prev_graph.fingerprint_by_index(prev_index);
13151318
let dep_node_index = self.encoder.borrow().send(profiler, key, fingerprint, edges);
@@ -1335,10 +1338,6 @@ impl<K: DepKind> CurrentDepGraph<K> {
13351338
}
13361339
}
13371340

1338-
/// The capacity of the `reads` field `SmallVec`
1339-
const TASK_DEPS_READS_CAP: usize = 8;
1340-
type EdgesVec = SmallVec<[DepNodeIndex; TASK_DEPS_READS_CAP]>;
1341-
13421341
#[derive(Debug, Clone, Copy)]
13431342
pub enum TaskDepsRef<'a, K: DepKind> {
13441343
/// New dependencies can be added to the

compiler/rustc_query_system/src/dep_graph/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
pub mod debug;
22
mod dep_node;
3+
mod edges;
34
mod graph;
45
mod query;
56
mod serialized;
67

78
pub use dep_node::{DepKindStruct, DepNode, DepNodeParams, WorkProductId};
9+
pub use edges::EdgesVec;
810
pub use graph::{
911
hash_result, DepGraph, DepGraphData, DepNodeColor, DepNodeIndex, TaskDeps, TaskDepsRef,
1012
WorkProduct, WorkProductMap,
@@ -157,4 +159,10 @@ pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable<FileEncoder>
157159
fn read_deps<OP>(op: OP)
158160
where
159161
OP: for<'a> FnOnce(TaskDepsRef<'a, Self>);
162+
163+
fn from_u16(u: u16) -> Self;
164+
165+
fn to_u16(self) -> u16;
166+
167+
const MAX: u16;
160168
}

0 commit comments

Comments
 (0)