From: Fangrui Song Date: Thu, 28 Feb 2019 05:16:01 +0000 (+0000) Subject: [Dominators] Avoid potentially quadratic std::is_permutation X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc5e3d536259f6842d204bfcb2000c6881de7c5f;p=llvm [Dominators] Avoid potentially quadratic std::is_permutation Summary: If the two sequences are not equal, std::is_permutation may be O(N^2) and indeed the case in libstdc++ and libc++. Use SmallPtrSet to prevent pessimizing cases. On my machine, SmallPtrSet starts to outperform std::is_permutation when there are 16 elements. Reviewers: kuhar Reviewed By: kuhar Subscribers: kristina, jdoerfert, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58373 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355070 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h index 19c3a8e2d80..53f3f997a00 100644 --- a/include/llvm/Support/GenericDomTreeConstruction.h +++ b/include/llvm/Support/GenericDomTreeConstruction.h @@ -698,6 +698,17 @@ struct SemiNCAInfo { return true; } + static bool isPermutation(const SmallVectorImpl &A, + const SmallVectorImpl &B) { + if (A.size() != B.size()) + return false; + SmallPtrSet Set(A.begin(), A.end()); + for (NodePtr N : B) + if (Set.count(N) == 0) + return false; + return true; + } + // Updates the set of roots after insertion or deletion. This ensures that // roots are the same when after a series of updates and when the tree would // be built from scratch. @@ -711,9 +722,8 @@ struct SemiNCAInfo { return; // Recalculate the set of roots. - auto Roots = FindRoots(DT, BUI); - if (DT.Roots.size() != Roots.size() || - !std::is_permutation(DT.Roots.begin(), DT.Roots.end(), Roots.begin())) { + RootsT Roots = FindRoots(DT, BUI); + if (!isPermutation(DT.Roots, Roots)) { // The roots chosen in the CFG have changed. This is because the // incremental algorithm does not really know or use the set of roots and // can make a different (implicit) decision about which node within an @@ -724,7 +734,6 @@ struct SemiNCAInfo { // It may be possible to update the tree without recalculating it, but // we do not know yet how to do it, and it happens rarely in practise. CalculateFromScratch(DT, BUI); - return; } } @@ -1264,9 +1273,7 @@ struct SemiNCAInfo { } RootsT ComputedRoots = FindRoots(DT, nullptr); - if (DT.Roots.size() != ComputedRoots.size() || - !std::is_permutation(DT.Roots.begin(), DT.Roots.end(), - ComputedRoots.begin())) { + if (!isPermutation(DT.Roots, ComputedRoots)) { errs() << "Tree has different roots than freshly computed ones!\n"; errs() << "\tPDT roots: "; for (const NodePtr N : DT.Roots) errs() << BlockNamePrinter(N) << ", ";