mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[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
This commit is contained in:
parent
f9714f9d78
commit
610300535f
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
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 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);
|
||||
|
Loading…
Reference in New Issue
Block a user