Skip to content

Commit 2f601ef

Browse files
committed
Auto merge of #85337 - cjgillot:less-anon, r=michaelwoerister
Avoid creating anonymous nodes with zero or one dependency. Anonymous nodes are only useful to encode dependencies, and cannot be replayed from one compilation session to another. As such, anonymous nodes without dependency are always green. Anonymous nodes with only one dependency are equivalent to this dependency. cc #45408 cc `@michaelwoerister`
2 parents 1e13a9b + b51f24f commit 2f601ef

File tree

2 files changed

+54
-27
lines changed
  • compiler
    • rustc_incremental/src/persist
    • rustc_query_system/src/dep_graph

2 files changed

+54
-27
lines changed

compiler/rustc_incremental/src/persist/save.rs

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ pub fn build_dep_graph(
229229
}
230230

231231
Some(DepGraph::new(
232+
&sess.prof,
232233
prev_graph,
233234
prev_work_products,
234235
encoder,

compiler/rustc_query_system/src/dep_graph/graph.rs

+53-27
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ rustc_index::newtype_index! {
4444

4545
impl DepNodeIndex {
4646
pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
47+
pub const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::from_u32(0);
4748
}
4849

4950
impl std::convert::From<DepNodeIndex> for QueryInvocationId {
@@ -108,6 +109,7 @@ where
108109

109110
impl<K: DepKind> DepGraph<K> {
110111
pub fn new(
112+
profiler: &SelfProfilerRef,
111113
prev_graph: SerializedDepGraph<K>,
112114
prev_work_products: FxHashMap<WorkProductId, WorkProduct>,
113115
encoder: FileEncoder,
@@ -116,16 +118,23 @@ impl<K: DepKind> DepGraph<K> {
116118
) -> DepGraph<K> {
117119
let prev_graph_node_count = prev_graph.node_count();
118120

121+
let current =
122+
CurrentDepGraph::new(prev_graph_node_count, encoder, record_graph, record_stats);
123+
124+
// Instantiate a dependy-less node only once for anonymous queries.
125+
let _green_node_index = current.intern_new_node(
126+
profiler,
127+
DepNode { kind: DepKind::NULL, hash: current.anon_id_seed.into() },
128+
smallvec![],
129+
Fingerprint::ZERO,
130+
);
131+
debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
132+
119133
DepGraph {
120134
data: Some(Lrc::new(DepGraphData {
121135
previous_work_products: prev_work_products,
122136
dep_node_debug: Default::default(),
123-
current: CurrentDepGraph::new(
124-
prev_graph_node_count,
125-
encoder,
126-
record_graph,
127-
record_stats,
128-
),
137+
current,
129138
emitting_diagnostics: Default::default(),
130139
emitting_diagnostics_cond_var: Condvar::new(),
131140
previous: prev_graph,
@@ -287,30 +296,47 @@ impl<K: DepKind> DepGraph<K> {
287296
let task_deps = Lock::new(TaskDeps::default());
288297
let result = K::with_deps(Some(&task_deps), op);
289298
let task_deps = task_deps.into_inner();
299+
let task_deps = task_deps.reads;
300+
301+
let dep_node_index = match task_deps.len() {
302+
0 => {
303+
// Because the dep-node id of anon nodes is computed from the sets of its
304+
// dependencies we already know what the ID of this dependency-less node is
305+
// going to be (i.e. equal to the precomputed
306+
// `SINGLETON_DEPENDENCYLESS_ANON_NODE`). As a consequence we can skip creating
307+
// a `StableHasher` and sending the node through interning.
308+
DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE
309+
}
310+
1 => {
311+
// When there is only one dependency, don't bother creating a node.
312+
task_deps[0]
313+
}
314+
_ => {
315+
// The dep node indices are hashed here instead of hashing the dep nodes of the
316+
// dependencies. These indices may refer to different nodes per session, but this isn't
317+
// a problem here because we that ensure the final dep node hash is per session only by
318+
// combining it with the per session random number `anon_id_seed`. This hash only need
319+
// to map the dependencies to a single value on a per session basis.
320+
let mut hasher = StableHasher::new();
321+
task_deps.hash(&mut hasher);
322+
323+
let target_dep_node = DepNode {
324+
kind: dep_kind,
325+
// Fingerprint::combine() is faster than sending Fingerprint
326+
// through the StableHasher (at least as long as StableHasher
327+
// is so slow).
328+
hash: data.current.anon_id_seed.combine(hasher.finish()).into(),
329+
};
290330

291-
// The dep node indices are hashed here instead of hashing the dep nodes of the
292-
// dependencies. These indices may refer to different nodes per session, but this isn't
293-
// a problem here because we that ensure the final dep node hash is per session only by
294-
// combining it with the per session random number `anon_id_seed`. This hash only need
295-
// to map the dependencies to a single value on a per session basis.
296-
let mut hasher = StableHasher::new();
297-
task_deps.reads.hash(&mut hasher);
298-
299-
let target_dep_node = DepNode {
300-
kind: dep_kind,
301-
// Fingerprint::combine() is faster than sending Fingerprint
302-
// through the StableHasher (at least as long as StableHasher
303-
// is so slow).
304-
hash: data.current.anon_id_seed.combine(hasher.finish()).into(),
331+
data.current.intern_new_node(
332+
cx.profiler(),
333+
target_dep_node,
334+
task_deps,
335+
Fingerprint::ZERO,
336+
)
337+
}
305338
};
306339

307-
let dep_node_index = data.current.intern_new_node(
308-
cx.profiler(),
309-
target_dep_node,
310-
task_deps.reads,
311-
Fingerprint::ZERO,
312-
);
313-
314340
(result, dep_node_index)
315341
} else {
316342
(op(), self.next_virtual_depnode_index())

0 commit comments

Comments
 (0)