Skip to content

Commit 3c7ee98

Browse files
committed
Compute DepNode for incremental queries.
Prior to rust-lang#154122 it wasn't used on all paths, so we only computed it when necessary -- sometimes in `check_if_ensure_can_skip_execution`, sometimes in one of two places in `execute_job_incr` -- and pass around `Option<DepNode>` to allow this. But now it's always used, so this commit makes us compute it earlier, which simplifies things. - `check_if_ensure_can_skip_execution` can be made simpler, returning a bool and eliminating the need for `EnsureCanSkip`. - `execute_job_incr` no longer uses two slightly different methods to create a `DepNode` (`get_or_insert_with` vs `unwrap_or_else`).
1 parent 1e4b453 commit 3c7ee98

File tree

1 file changed

+37
-66
lines changed

1 file changed

+37
-66
lines changed

compiler/rustc_query_impl/src/execution.rs

Lines changed: 37 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,7 @@ fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(
261261
tcx: TyCtxt<'tcx>,
262262
span: Span,
263263
key: C::Key,
264-
// If present, some previous step has already created a `DepNode` for this
265-
// query+key, which we should reuse instead of creating a new one.
266-
dep_node: Option<DepNode>,
264+
dep_node: Option<DepNode>, // `None` for non-incremental, `Some` for incremental
267265
) -> (C::Value, Option<DepNodeIndex>) {
268266
let key_hash = sharded::make_hash(&key);
269267
let mut state_lock = query.state.active.lock_shard_by_hash(key_hash);
@@ -300,7 +298,7 @@ fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(
300298

301299
// Delegate to another function to actually execute the query job.
302300
let (value, dep_node_index) = if INCR {
303-
execute_job_incr(query, tcx, key, dep_node, id)
301+
execute_job_incr(query, tcx, key, dep_node.unwrap(), id)
304302
} else {
305303
execute_job_non_incr(query, tcx, key, id)
306304
};
@@ -416,27 +414,23 @@ fn execute_job_incr<'tcx, C: QueryCache>(
416414
query: &'tcx QueryVTable<'tcx, C>,
417415
tcx: TyCtxt<'tcx>,
418416
key: C::Key,
419-
mut dep_node_opt: Option<DepNode>,
417+
dep_node: DepNode,
420418
job_id: QueryJobId,
421419
) -> (C::Value, DepNodeIndex) {
422420
let dep_graph_data =
423421
tcx.dep_graph.data().expect("should always be present in incremental mode");
424422

425423
if !query.eval_always {
426-
// `to_dep_node` is expensive for some `DepKind`s.
427-
let dep_node =
428-
dep_node_opt.get_or_insert_with(|| DepNode::construct(tcx, query.dep_kind, &key));
429-
430424
// The diagnostics for this query will be promoted to the current session during
431425
// `try_mark_green()`, so we can ignore them here.
432426
if let Some(ret) = start_query(job_id, false, || try {
433-
let (prev_index, dep_node_index) = dep_graph_data.try_mark_green(tcx, dep_node)?;
427+
let (prev_index, dep_node_index) = dep_graph_data.try_mark_green(tcx, &dep_node)?;
434428
let value = load_from_disk_or_invoke_provider_green(
435429
tcx,
436430
dep_graph_data,
437431
query,
438432
key,
439-
dep_node,
433+
&dep_node,
440434
prev_index,
441435
dep_node_index,
442436
);
@@ -449,10 +443,6 @@ fn execute_job_incr<'tcx, C: QueryCache>(
449443
let prof_timer = tcx.prof.query_provider();
450444

451445
let (result, dep_node_index) = start_query(job_id, query.depth_limit, || {
452-
// `to_dep_node` is expensive for some `DepKind`s.
453-
let dep_node =
454-
dep_node_opt.unwrap_or_else(|| DepNode::construct(tcx, query.dep_kind, &key));
455-
456446
// Call the query provider.
457447
dep_graph_data.with_task(
458448
dep_node,
@@ -542,67 +532,54 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>(
542532
value
543533
}
544534

545-
/// Return value struct for [`check_if_ensure_can_skip_execution`].
546-
struct EnsureCanSkip {
547-
/// If true, the current `tcx.ensure_ok()` or `tcx.ensure_done()` query
548-
/// can return early without actually trying to execute.
549-
skip_execution: bool,
550-
/// A dep node that was prepared while checking whether execution can be
551-
/// skipped, to be reused by execution itself if _not_ skipped.
552-
dep_node: Option<DepNode>,
553-
}
554-
555535
/// Checks whether a `tcx.ensure_ok()` or `tcx.ensure_done()` query call can
556536
/// return early without actually trying to execute.
557537
///
558538
/// This only makes sense during incremental compilation, because it relies
559539
/// on having the dependency graph (and in some cases a disk-cached value)
560540
/// from the previous incr-comp session.
561541
#[inline(never)]
562-
fn check_if_ensure_can_skip_execution<'tcx, C: QueryCache>(
542+
fn ensure_can_skip_execution<'tcx, C: QueryCache>(
563543
query: &'tcx QueryVTable<'tcx, C>,
564544
tcx: TyCtxt<'tcx>,
565545
key: C::Key,
546+
dep_node: DepNode,
566547
ensure_mode: EnsureMode,
567-
) -> EnsureCanSkip {
548+
) -> bool {
568549
// Queries with `eval_always` should never skip execution.
569550
if query.eval_always {
570-
return EnsureCanSkip { skip_execution: false, dep_node: None };
551+
return false;
571552
}
572553

573-
let dep_node = DepNode::construct(tcx, query.dep_kind, &key);
574-
575-
let serialized_dep_node_index = match tcx.dep_graph.try_mark_green(tcx, &dep_node) {
554+
match tcx.dep_graph.try_mark_green(tcx, &dep_node) {
576555
None => {
577556
// A None return from `try_mark_green` means that this is either
578557
// a new dep node or that the dep node has already been marked red.
579558
// Either way, we can't call `dep_graph.read()` as we don't have the
580559
// DepNodeIndex. We must invoke the query itself. The performance cost
581560
// this introduces should be negligible as we'll immediately hit the
582561
// in-memory cache, or another query down the line will.
583-
return EnsureCanSkip { skip_execution: false, dep_node: Some(dep_node) };
562+
false
584563
}
585564
Some((serialized_dep_node_index, dep_node_index)) => {
586565
tcx.dep_graph.read_index(dep_node_index);
587566
tcx.prof.query_cache_hit(dep_node_index.into());
588-
serialized_dep_node_index
589-
}
590-
};
591-
592-
match ensure_mode {
593-
EnsureMode::Ok => {
594-
// In ensure-ok mode, we can skip execution for this key if the node
595-
// is green. It must have succeeded in the previous session, and
596-
// therefore would succeed in the current session if executed.
597-
EnsureCanSkip { skip_execution: true, dep_node: None }
598-
}
599-
EnsureMode::Done => {
600-
// In ensure-done mode, we can only skip execution for this key if
601-
// there's a disk-cached value available to load later if needed,
602-
// which guarantees the query provider will never run for this key.
603-
let is_loadable = (query.will_cache_on_disk_for_key_fn)(tcx, key)
604-
&& loadable_from_disk(tcx, serialized_dep_node_index);
605-
EnsureCanSkip { skip_execution: is_loadable, dep_node: Some(dep_node) }
567+
match ensure_mode {
568+
// In ensure-ok mode, we can skip execution for this key if the
569+
// node is green. It must have succeeded in the previous
570+
// session, and therefore would succeed in the current session
571+
// if executed.
572+
EnsureMode::Ok => true,
573+
574+
// In ensure-done mode, we can only skip execution for this key
575+
// if there's a disk-cached value available to load later if
576+
// needed, which guarantees the query provider will never run
577+
// for this key.
578+
EnsureMode::Done => {
579+
(query.will_cache_on_disk_for_key_fn)(tcx, key)
580+
&& loadable_from_disk(tcx, serialized_dep_node_index)
581+
}
582+
}
606583
}
607584
}
608585
}
@@ -629,24 +606,18 @@ pub(super) fn execute_query_incr_inner<'tcx, C: QueryCache>(
629606
key: C::Key,
630607
mode: QueryMode,
631608
) -> Option<C::Value> {
609+
let dep_node = DepNode::construct(tcx, query.dep_kind, &key);
610+
632611
// Check if query execution can be skipped, for `ensure_ok` or `ensure_done`.
633-
// This might have the side-effect of creating a suitable DepNode, which
634-
// we should reuse for execution instead of creating a new one.
635-
let dep_node: Option<DepNode> = match mode {
636-
QueryMode::Ensure { ensure_mode } => {
637-
let EnsureCanSkip { skip_execution, dep_node } =
638-
check_if_ensure_can_skip_execution(query, tcx, key, ensure_mode);
639-
if skip_execution {
640-
// Return early to skip execution.
641-
return None;
642-
}
643-
dep_node
644-
}
645-
QueryMode::Get => None,
646-
};
612+
if let QueryMode::Ensure { ensure_mode } = mode
613+
&& ensure_can_skip_execution(query, tcx, key, dep_node, ensure_mode)
614+
{
615+
return None;
616+
}
647617

648-
let (result, dep_node_index) =
649-
ensure_sufficient_stack(|| try_execute_query::<C, true>(query, tcx, span, key, dep_node));
618+
let (result, dep_node_index) = ensure_sufficient_stack(|| {
619+
try_execute_query::<C, true>(query, tcx, span, key, Some(dep_node))
620+
});
650621
if let Some(dep_node_index) = dep_node_index {
651622
tcx.dep_graph.read_index(dep_node_index)
652623
}

0 commit comments

Comments
 (0)