1139823Simp//===- llvm/Analysis/LegacyDivergenceAnalysis.h - KernelDivergence Analysis -*- C++ -*-===//
234649Swollman//
334649Swollman// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
434649Swollman// See https://llvm.org/LICENSE.txt for license information.
534649Swollman// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
634649Swollman//
734649Swollman//===----------------------------------------------------------------------===//
834649Swollman//
934649Swollman// The kernel divergence analysis is an LLVM pass which can be used to find out
1034649Swollman// if a branch instruction in a GPU program (kernel) is divergent or not. It can help
1134649Swollman// branch optimizations such as jump threading and loop unswitching to make
1234649Swollman// better decisions.
1334649Swollman//
1434649Swollman//===----------------------------------------------------------------------===//
1534649Swollman#ifndef LLVM_ANALYSIS_LEGACYDIVERGENCEANALYSIS_H
1634649Swollman#define LLVM_ANALYSIS_LEGACYDIVERGENCEANALYSIS_H
1734649Swollman
1834649Swollman#include "llvm/ADT/DenseSet.h"
1934649Swollman#include "llvm/Pass.h"
2034649Swollman#include <memory>
2134649Swollman
2234649Swollmannamespace llvm {
2334649Swollmanclass DivergenceInfo;
2434649Swollmanclass Function;
2534649Swollmanclass Module;
2634649Swollmanclass raw_ostream;
2734649Swollmanclass TargetTransformInfo;
2834649Swollmanclass Use;
2950477Speterclass Value;
3034649Swollman
3134649Swollmanclass LegacyDivergenceAnalysis : public FunctionPass {
3234649Swollmanpublic:
3334649Swollman  static char ID;
3434649Swollman
3534649Swollman  LegacyDivergenceAnalysis();
3634649Swollman
3734649Swollman  void getAnalysisUsage(AnalysisUsage &AU) const override;
3834649Swollman
3934649Swollman  bool runOnFunction(Function &F) override;
4034649Swollman
4134649Swollman  // Print all divergent branches in the function.
4234649Swollman  void print(raw_ostream &OS, const Module *) const override;
43167126Sbms
44167126Sbms  // Returns true if V is divergent at its definition.
45167126Sbms  bool isDivergent(const Value *V) const;
46167126Sbms
47167126Sbms  // Returns true if U is divergent. Uses of a uniform value can be divergent.
48167126Sbms  bool isDivergentUse(const Use *U) const;
49167126Sbms
5034649Swollman  // Returns true if V is uniform/non-divergent.
51167126Sbms  bool isUniform(const Value *V) const { return !isDivergent(V); }
52167126Sbms
53167126Sbms  // Returns true if U is uniform/non-divergent. Uses of a uniform value can be
54167126Sbms  // divergent.
55167126Sbms  bool isUniformUse(const Use *U) const { return !isDivergentUse(U); }
56167126Sbms
57167126Sbms  // Keep the analysis results uptodate by removing an erased value.
58167126Sbms  void removeValue(const Value *V) { DivergentValues.erase(V); }
59167126Sbms
60167126Sbmsprivate:
61167126Sbms  // Whether analysis should be performed by GPUDivergenceAnalysis.
62167126Sbms  bool shouldUseGPUDivergenceAnalysis(const Function &F,
63167126Sbms                                      const TargetTransformInfo &TTI) const;
64167126Sbms
65167126Sbms  // (optional) handle to new DivergenceAnalysis
66167126Sbms  std::unique_ptr<DivergenceInfo> gpuDA;
67167126Sbms
68167126Sbms  // Stores all divergent values.
69167126Sbms  DenseSet<const Value *> DivergentValues;
70167126Sbms
71167126Sbms  // Stores divergent uses of possibly uniform values.
72167126Sbms  DenseSet<const Use *> DivergentUses;
73167126Sbms};
74167126Sbms} // End llvm namespace
75167126Sbms
76167126Sbms#endif // LLVM_ANALYSIS_LEGACYDIVERGENCEANALYSIS_H
77167126Sbms