Skip to content

Commit e1204fe

Browse files
committed
Slightly faster version of find_state
This version shaves off ca 2% of the cycles in my experiments and makes the control flow easier to follow for me and hopefully others, including the compiler. Someone gave me a working profiler and by God I'm using it.
1 parent 46d3568 commit e1204fe

File tree

1 file changed

+27
-24
lines changed
  • compiler/rustc_data_structures/src/graph/scc

1 file changed

+27
-24
lines changed

compiler/rustc_data_structures/src/graph/scc/mod.rs

+27-24
Original file line numberDiff line numberDiff line change
@@ -402,13 +402,25 @@ where
402402
// Ultimately propagated to all the transitive parents when following
403403
// `InCycleWith` upwards.
404404
// This loop performs the downward link encoding mentioned above. Details below!
405-
let node_state = {
405+
// Note that there are two different states being assigned: the root state, and
406+
// a potentially derived version of the root state for non-root nodes in the chain.
407+
let (root_state, assigned_state) = {
406408
loop {
407409
debug!("find_state(r = {node:?} in state {:?})", self.node_states[node]);
408410
match self.node_states[node] {
409-
s @ (NodeState::NotVisited
410-
| NodeState::BeingVisited { .. }
411-
| NodeState::InCycle { .. }) => break s,
411+
// This must have been the first and only state since it is unexplored*;
412+
// no update needed! * Unless there is a bug :')
413+
s @ NodeState::NotVisited => return s,
414+
// We are in a completely discovered SCC; every node on our path is in that SCC:
415+
s @ NodeState::InCycle { .. } => break (s, s),
416+
// The Interesting Third Base Case: we are a path back to a root node
417+
// still being explored. Now we need that node to keep its state and
418+
// every other node to be recorded as being in whatever component that
419+
// ends up in.
420+
s @ NodeState::BeingVisited { depth, .. } => {
421+
break (s, NodeState::InCycleWith { parent: self.node_stack[depth] });
422+
}
423+
// We are not at the head of a path; keep compressing it!
412424
NodeState::InCycleWith { parent } => {
413425
// We test this, to be extremely sure that we never
414426
// ever break our termination condition for the
@@ -462,11 +474,13 @@ where
462474
// Move backwards until we found the node where we started. We
463475
// will know when we hit the state where previous_node == node.
464476
loop {
465-
// Back at the beginning, we can return.
477+
// Back at the beginning, we can return. Note that we return the root state.
478+
// This is becuse for components being explored, we would otherwise get a
479+
// `node_state[n] = InCycleWith{ parent: n }` and that's wrong.
466480
if previous_node == node {
467-
return node_state;
481+
return root_state;
468482
}
469-
debug!("Compressing {node:?} down to {previous_node:?} with state {node_state:?}");
483+
debug!("Compressing {node:?} down to {previous_node:?} with state {assigned_state:?}");
470484

471485
// Update to previous node in the link.
472486
match self.node_states[previous_node] {
@@ -475,25 +489,14 @@ where
475489
previous_node = previous;
476490
}
477491
// Only InCycleWith nodes were added to the reverse linked list.
478-
other => panic!("Invalid previous link while compressing cycle: {other:?}"),
492+
other => unreachable!("Invalid previous link while compressing cycle: {other:?}"),
479493
}
480494

481-
debug!("find_state: parent_state = {:?}", node_state);
482-
483-
let new_state = match node_state {
484-
// Still visiting nodes, compress the cycle to the root node
485-
// at that depth.
486-
NodeState::BeingVisited { depth, .. } => {
487-
let parent = self.node_stack[depth];
488-
NodeState::InCycleWith { parent }
489-
}
490-
// Already fully visited; we just transfer the state of the parent.
491-
s @ NodeState::InCycle { .. } => s,
492-
// These cannot be the root nodes of a path being compressed
493-
NodeState::NotVisited | NodeState::InCycleWith { .. } => unreachable!(),
494-
};
495-
496-
self.node_states[node] = new_state;
495+
// Update the node state to the (potentially derived) state.
496+
// If the root is still being explored, this is
497+
// `InCycleWith{ parent: <root node>}`, otherwise
498+
// `assigned_state == root_state`.
499+
self.node_states[node] = assigned_state;
497500
}
498501
}
499502

0 commit comments

Comments
 (0)