-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[DomTree] Avoid duplicate hash lookups in runDFS() (NFCI) #96460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
runDFS() currently performs three hash table lookups. One in the main loop, one when checking whether a successor has already been visited and another when adding parent and reverse children to the successor. We can avoid the two additional lookups by making the parent number part of the stack, and then making the parent / reverse children update part of the main loop. The main loop already has a check for already visited nodes, so we don't have to check this in advance -- we can simply push the node to the worklist and skip it later.
@llvm/pr-subscribers-llvm-support Author: Nikita Popov (nikic) ChangesrunDFS() currently performs three hash table lookups. One in the main loop, one when checking whether a successor has already been visited and another when adding parent and reverse children to the successor. We can avoid the two additional lookups by making the parent number part of the stack, and then making the parent / reverse children update part of the main loop. The main loop already has a check for already visited nodes, so we don't have to check this in advance -- we can simply push the node to the worklist and skip it later. This results in a minor compile-time improvement: http://llvm-compile-time-tracker.com/compare.php?from=c43d5f540fd43409e7997c9fec97a1d415855b7c&to=1844fc47329a2905bf73b7b86964e8a31fa3b758&stat=instructions:u Full diff: https://github.com/llvm/llvm-project/pull/96460.diff 1 Files Affected:
diff --git a/llvm/include/llvm/Support/GenericDomTreeConstruction.h b/llvm/include/llvm/Support/GenericDomTreeConstruction.h
index 401cc4eb0ec1b..57cbe993d8739 100644
--- a/llvm/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/llvm/include/llvm/Support/GenericDomTreeConstruction.h
@@ -180,15 +180,17 @@ struct SemiNCAInfo {
unsigned AttachToNum,
const NodeOrderMap *SuccOrder = nullptr) {
assert(V);
- SmallVector<NodePtr, 64> WorkList = {V};
+ SmallVector<std::pair<NodePtr, unsigned>, 64> WorkList = {{V, AttachToNum}};
NodeToInfo[V].Parent = AttachToNum;
while (!WorkList.empty()) {
- const NodePtr BB = WorkList.pop_back_val();
+ const auto [BB, ParentNum] = WorkList.pop_back_val();
auto &BBInfo = NodeToInfo[BB];
+ BBInfo.ReverseChildren.push_back(ParentNum);
// Visited nodes always have positive DFS numbers.
if (BBInfo.DFSNum != 0) continue;
+ BBInfo.Parent = ParentNum;
BBInfo.DFSNum = BBInfo.Semi = BBInfo.Label = ++LastNum;
NumToNode.push_back(BB);
@@ -201,22 +203,9 @@ struct SemiNCAInfo {
});
for (const NodePtr Succ : Successors) {
- const auto SIT = NodeToInfo.find(Succ);
- // Don't visit nodes more than once but remember to collect
- // ReverseChildren.
- if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 0) {
- if (Succ != BB) SIT->second.ReverseChildren.push_back(LastNum);
- continue;
- }
-
if (!Condition(BB, Succ)) continue;
- // It's fine to add Succ to the map, because we know that it will be
- // visited later.
- auto &SuccInfo = NodeToInfo[Succ];
- WorkList.push_back(Succ);
- SuccInfo.Parent = LastNum;
- SuccInfo.ReverseChildren.push_back(LastNum);
+ WorkList.push_back({Succ, LastNum});
}
}
|
@@ -180,15 +180,17 @@ struct SemiNCAInfo { | |||
unsigned AttachToNum, | |||
const NodeOrderMap *SuccOrder = nullptr) { | |||
assert(V); | |||
SmallVector<NodePtr, 64> WorkList = {V}; | |||
SmallVector<std::pair<NodePtr, unsigned>, 64> WorkList = {{V, AttachToNum}}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a pretty large stack allocation (16B * 64 => 1kB?). Is this what we want?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's on the bigger side, but as runDFS is essentially a leaf function, I don't think it's a problem.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/101/builds/644 Here is the relevant piece of the build log for the reference:
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/139/builds/441 Here is the relevant piece of the build log for the reference:
|
runDFS() currently performs three hash table lookups. One in the main loop, one when checking whether a successor has already been visited and another when adding parent and reverse children to the successor. We can avoid the two additional lookups by making the parent number part of the stack, and then making the parent / reverse children update part of the main loop. The main loop already has a check for already visited nodes, so we don't have to check this in advance -- we can simply push the node to the worklist and skip it later.
runDFS() currently performs three hash table lookups. One in the main loop, one when checking whether a successor has already been visited and another when adding parent and reverse children to the successor.
We can avoid the two additional lookups by making the parent number part of the stack, and then making the parent / reverse children update part of the main loop.
The main loop already has a check for already visited nodes, so we don't have to check this in advance -- we can simply push the node to the worklist and skip it later.
This results in a minor compile-time improvement: http://llvm-compile-time-tracker.com/compare.php?from=c43d5f540fd43409e7997c9fec97a1d415855b7c&to=1844fc47329a2905bf73b7b86964e8a31fa3b758&stat=instructions:u