diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Analysis/DivergenceAnalysis.cpp | 33 | ||||
| -rw-r--r-- | llvm/lib/Analysis/LegacyDivergenceAnalysis.cpp | 101 | 
2 files changed, 108 insertions, 26 deletions
diff --git a/llvm/lib/Analysis/DivergenceAnalysis.cpp b/llvm/lib/Analysis/DivergenceAnalysis.cpp index de47445c5e0..7ba23854a3c 100644 --- a/llvm/lib/Analysis/DivergenceAnalysis.cpp +++ b/llvm/lib/Analysis/DivergenceAnalysis.cpp @@ -422,3 +422,36 @@ void DivergenceAnalysis::print(raw_ostream &OS, const Module *) const {        OS << "DIVERGENT:" << I << '\n';    }  } + +// class GPUDivergenceAnalysis +GPUDivergenceAnalysis::GPUDivergenceAnalysis(Function &F, +                                             const DominatorTree &DT, +                                             const PostDominatorTree &PDT, +                                             const LoopInfo &LI, +                                             const TargetTransformInfo &TTI) +    : SDA(DT, PDT, LI), DA(F, nullptr, DT, LI, SDA, false) { +  for (auto &I : instructions(F)) { +    if (TTI.isSourceOfDivergence(&I)) { +      DA.markDivergent(I); +    } else if (TTI.isAlwaysUniform(&I)) { +      DA.addUniformOverride(I); +    } +  } +  for (auto &Arg : F.args()) { +    if (TTI.isSourceOfDivergence(&Arg)) { +      DA.markDivergent(Arg); +    } +  } + +  DA.compute(); +} + +bool GPUDivergenceAnalysis::isDivergent(const Value &val) const { +  return DA.isDivergent(val); +} + +void GPUDivergenceAnalysis::print(raw_ostream &OS, const Module *mod) const { +  OS << "Divergence of kernel " << DA.getFunction().getName() << " {\n"; +  DA.print(OS, mod); +  OS << "}\n"; +} diff --git a/llvm/lib/Analysis/LegacyDivergenceAnalysis.cpp b/llvm/lib/Analysis/LegacyDivergenceAnalysis.cpp index 2089d1c53d0..bb8e9176826 100644 --- a/llvm/lib/Analysis/LegacyDivergenceAnalysis.cpp +++ b/llvm/lib/Analysis/LegacyDivergenceAnalysis.cpp @@ -1,4 +1,5 @@ -//===- LegacyDivergenceAnalysis.cpp --------- Legacy Divergence Analysis Implementation -==// +//===- LegacyDivergenceAnalysis.cpp --------- Legacy Divergence Analysis +//Implementation -==//  //  //                     The LLVM Compiler Infrastructure  // @@ -64,6 +65,9 @@  //  //===----------------------------------------------------------------------===// +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/Analysis/CFG.h" +#include "llvm/Analysis/DivergenceAnalysis.h"  #include "llvm/Analysis/LegacyDivergenceAnalysis.h"  #include "llvm/Analysis/Passes.h"  #include "llvm/Analysis/PostDominators.h" @@ -79,6 +83,12 @@ using namespace llvm;  #define DEBUG_TYPE "divergence" +// transparently use the GPUDivergenceAnalysis +static cl::opt<bool> UseGPUDA("use-gpu-divergence-analysis", cl::init(false), +                              cl::Hidden, +                              cl::desc("turn the LegacyDivergenceAnalysis into " +                                       "a wrapper for GPUDivergenceAnalysis")); +  namespace {  class DivergencePropagator { @@ -262,16 +272,17 @@ void DivergencePropagator::propagate() {    }  } -} /// end namespace anonymous +} // namespace  // Register this pass.  char LegacyDivergenceAnalysis::ID = 0; -INITIALIZE_PASS_BEGIN(LegacyDivergenceAnalysis, "divergence", "Legacy Divergence Analysis", -                      false, true) +INITIALIZE_PASS_BEGIN(LegacyDivergenceAnalysis, "divergence", +                      "Legacy Divergence Analysis", false, true)  INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)  INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) -INITIALIZE_PASS_END(LegacyDivergenceAnalysis, "divergence", "Legacy Divergence Analysis", -                    false, true) +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) +INITIALIZE_PASS_END(LegacyDivergenceAnalysis, "divergence", +                    "Legacy Divergence Analysis", false, true)  FunctionPass *llvm::createLegacyDivergenceAnalysisPass() {    return new LegacyDivergenceAnalysis(); @@ -280,9 +291,24 @@ FunctionPass *llvm::createLegacyDivergenceAnalysisPass() {  void LegacyDivergenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {    AU.addRequired<DominatorTreeWrapperPass>();    AU.addRequired<PostDominatorTreeWrapperPass>(); +  if (UseGPUDA) +    AU.addRequired<LoopInfoWrapperPass>();    AU.setPreservesAll();  } +bool LegacyDivergenceAnalysis::shouldUseGPUDivergenceAnalysis( +    const Function &F) const { +  if (!UseGPUDA) +    return false; + +  // GPUDivergenceAnalysis requires a reducible CFG. +  auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); +  using RPOTraversal = ReversePostOrderTraversal<const Function *>; +  RPOTraversal FuncRPOT(&F); +  return !containsIrreducibleCFG<const BasicBlock *, const RPOTraversal, +                                 const LoopInfo>(FuncRPOT, LI); +} +  bool LegacyDivergenceAnalysis::runOnFunction(Function &F) {    auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();    if (TTIWP == nullptr) @@ -295,36 +321,59 @@ bool LegacyDivergenceAnalysis::runOnFunction(Function &F) {      return false;    DivergentValues.clear(); +  gpuDA = nullptr; + +  auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();    auto &PDT = getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree(); -  DivergencePropagator DP(F, TTI, -                          getAnalysis<DominatorTreeWrapperPass>().getDomTree(), -                          PDT, DivergentValues); -  DP.populateWithSourcesOfDivergence(); -  DP.propagate(); -  LLVM_DEBUG( -    dbgs() << "\nAfter divergence analysis on " << F.getName() << ":\n"; -    print(dbgs(), F.getParent()) -  ); + +  if (shouldUseGPUDivergenceAnalysis(F)) { +    // run the new GPU divergence analysis +    auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); +    gpuDA = llvm::make_unique<GPUDivergenceAnalysis>(F, DT, PDT, LI, TTI); + +  } else { +    // run LLVM's existing DivergenceAnalysis +    DivergencePropagator DP(F, TTI, DT, PDT, DivergentValues); +    DP.populateWithSourcesOfDivergence(); +    DP.propagate(); +  } + +  LLVM_DEBUG(dbgs() << "\nAfter divergence analysis on " << F.getName() +                    << ":\n"; +             print(dbgs(), F.getParent())); +    return false;  } +bool LegacyDivergenceAnalysis::isDivergent(const Value *V) const { +  if (gpuDA) { +    return gpuDA->isDivergent(*V); +  } +  return DivergentValues.count(V); +} +  void LegacyDivergenceAnalysis::print(raw_ostream &OS, const Module *) const { -  if (DivergentValues.empty()) +  if ((!gpuDA || !gpuDA->hasDivergence()) && DivergentValues.empty())      return; -  const Value *FirstDivergentValue = *DivergentValues.begin(); +    const Function *F; -  if (const Argument *Arg = dyn_cast<Argument>(FirstDivergentValue)) { -    F = Arg->getParent(); -  } else if (const Instruction *I = -                 dyn_cast<Instruction>(FirstDivergentValue)) { -    F = I->getParent()->getParent(); -  } else { -    llvm_unreachable("Only arguments and instructions can be divergent"); +  if (!DivergentValues.empty()) { +    const Value *FirstDivergentValue = *DivergentValues.begin(); +    if (const Argument *Arg = dyn_cast<Argument>(FirstDivergentValue)) { +      F = Arg->getParent(); +    } else if (const Instruction *I = +                   dyn_cast<Instruction>(FirstDivergentValue)) { +      F = I->getParent()->getParent(); +    } else { +      llvm_unreachable("Only arguments and instructions can be divergent"); +    } +  } else if (gpuDA) { +    F = &gpuDA->getFunction();    }    // Dumps all divergent values in F, arguments and then instructions.    for (auto &Arg : F->args()) { -    OS << (DivergentValues.count(&Arg) ? "DIVERGENT: " : "           "); +    OS << (isDivergent(&Arg) ? "DIVERGENT: " : "           ");      OS << Arg << "\n";    }    // Iterate instructions using instructions() to ensure a deterministic order. @@ -332,7 +381,7 @@ void LegacyDivergenceAnalysis::print(raw_ostream &OS, const Module *) const {      auto &BB = *BI;      OS << "\n           " << BB.getName() << ":\n";      for (auto &I : BB.instructionsWithoutDebug()) { -      OS << (DivergentValues.count(&I) ? "DIVERGENT:     " : "               "); +      OS << (isDivergent(&I) ? "DIVERGENT:     " : "               ");        OS << I << "\n";      }    }  | 

