[llvm] 351d234 - [OpenMPOpt] Most SCC's are uninteresting, don't waste time on them (up to 16x faster)
Roman Lebedev via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 27 13:37:38 PDT 2020
Author: Roman Lebedev
Date: 2020-07-27T23:36:34+03:00
New Revision: 351d234d866ea441d8f8ad1e9b483a98fd51da19
URL: https://github.com/llvm/llvm-project/commit/351d234d866ea441d8f8ad1e9b483a98fd51da19
DIFF: https://github.com/llvm/llvm-project/commit/351d234d866ea441d8f8ad1e9b483a98fd51da19.diff
LOG: [OpenMPOpt] Most SCC's are uninteresting, don't waste time on them (up to 16x faster)
Summary:
This seems obvious in hindsight, but the result is surprising.
I've measured compile-time of `-openmpopt` pass standalone
on RawSpeed unity build, and while there is some OpenMP stuff,
most is not OpenMP. But nonetheless the pass does a lot of costly
preparations before ever trying to look for OpenMP stuff in SCC.
Numbers (n=25): 0.094624s -> 0.005976s, an -93.68% improvement, or ~16x
Reviewers: jdoerfert
Reviewed By: jdoerfert
Subscribers: yaxunl, hiraditya, guansong, llvm-commits, sstefan1
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D84689
Added:
Modified:
llvm/include/llvm/Transforms/IPO/OpenMPOpt.h
llvm/lib/Transforms/IPO/OpenMPOpt.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Transforms/IPO/OpenMPOpt.h b/llvm/include/llvm/Transforms/IPO/OpenMPOpt.h
index d96187b73f9b..9b72ee0afd28 100644
--- a/llvm/include/llvm/Transforms/IPO/OpenMPOpt.h
+++ b/llvm/include/llvm/Transforms/IPO/OpenMPOpt.h
@@ -33,6 +33,11 @@ struct OpenMPInModule {
bool isKnown() { return Value != OpenMP::UNKNOWN; }
operator bool() { return Value != OpenMP::NOT_FOUND; }
+ /// Does this function \p F contain any OpenMP runtime calls?
+ bool containsOMPRuntimeCalls(Function *F) const {
+ return FuncsWithOMPRuntimeCalls.contains(F);
+ }
+
/// Return the known kernels (=GPU entry points) in the module.
SmallPtrSetImpl<Kernel> &getKernels() { return Kernels; }
@@ -42,6 +47,11 @@ struct OpenMPInModule {
private:
enum class OpenMP { FOUND, NOT_FOUND, UNKNOWN } Value = OpenMP::UNKNOWN;
+ friend bool containsOpenMP(Module &M, OpenMPInModule &OMPInModule);
+
+ /// In which functions are OpenMP runtime calls present?
+ SmallPtrSet<Function *, 32> FuncsWithOMPRuntimeCalls;
+
/// Collection of known kernels (=GPU entry points) in the module.
SmallPtrSet<Kernel, 8> Kernels;
};
diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
index f664a2417374..93f1e5392eb2 100644
--- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
+++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
@@ -1339,10 +1339,21 @@ PreservedAnalyses OpenMPOptPass::run(LazyCallGraph::SCC &C,
return PreservedAnalyses::all();
SmallVector<Function *, 16> SCC;
- for (LazyCallGraph::Node &N : C)
- SCC.push_back(&N.getFunction());
+ // If there are kernels in the module, we have to run on all SCC's.
+ bool SCCIsInteresting = !OMPInModule.getKernels().empty();
+ for (LazyCallGraph::Node &N : C) {
+ Function *Fn = &N.getFunction();
+ SCC.push_back(Fn);
+
+ // Do we already know that the SCC contains kernels,
+ // or that OpenMP functions are called from this SCC?
+ if (SCCIsInteresting)
+ continue;
+ // If not, let's check that.
+ SCCIsInteresting |= OMPInModule.containsOMPRuntimeCalls(Fn);
+ }
- if (SCC.empty())
+ if (!SCCIsInteresting || SCC.empty())
return PreservedAnalyses::all();
FunctionAnalysisManager &FAM =
@@ -1401,12 +1412,23 @@ struct OpenMPOptLegacyPass : public CallGraphSCCPass {
return false;
SmallVector<Function *, 16> SCC;
- for (CallGraphNode *CGN : CGSCC)
- if (Function *Fn = CGN->getFunction())
- if (!Fn->isDeclaration())
- SCC.push_back(Fn);
+ // If there are kernels in the module, we have to run on all SCC's.
+ bool SCCIsInteresting = !OMPInModule.getKernels().empty();
+ for (CallGraphNode *CGN : CGSCC) {
+ Function *Fn = CGN->getFunction();
+ if (!Fn || Fn->isDeclaration())
+ continue;
+ SCC.push_back(Fn);
- if (SCC.empty())
+ // Do we already know that the SCC contains kernels,
+ // or that OpenMP functions are called from this SCC?
+ if (SCCIsInteresting)
+ continue;
+ // If not, let's check that.
+ SCCIsInteresting |= OMPInModule.containsOMPRuntimeCalls(Fn);
+ }
+
+ if (!SCCIsInteresting || SCC.empty())
return false;
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
@@ -1468,13 +1490,19 @@ bool llvm::omp::containsOpenMP(Module &M, OpenMPInModule &OMPInModule) {
if (OMPInModule.isKnown())
return OMPInModule;
+ auto RecordFunctionsContainingUsesOf = [&](Function *F) {
+ for (User *U : F->users())
+ if (auto *I = dyn_cast<Instruction>(U))
+ OMPInModule.FuncsWithOMPRuntimeCalls.insert(I->getFunction());
+ };
+
// MSVC doesn't like long if-else chains for some reason and instead just
// issues an error. Work around it..
do {
#define OMP_RTL(_Enum, _Name, ...) \
- if (M.getFunction(_Name)) { \
+ if (Function *F = M.getFunction(_Name)) { \
+ RecordFunctionsContainingUsesOf(F); \
OMPInModule = true; \
- break; \
}
#include "llvm/Frontend/OpenMP/OMPKinds.def"
} while (false);
More information about the llvm-commits
mailing list