1 | //===- GenericUniformityInfo.h ---------------------------*- C++ -*--------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_ADT_GENERICUNIFORMITYINFO_H |
10 | #define LLVM_ADT_GENERICUNIFORMITYINFO_H |
11 | |
12 | #include "llvm/ADT/GenericCycleInfo.h" |
13 | #include "llvm/Support/raw_ostream.h" |
14 | |
15 | namespace llvm { |
16 | |
17 | class TargetTransformInfo; |
18 | |
19 | template <typename ContextT> class GenericUniformityAnalysisImpl; |
20 | template <typename ImplT> struct GenericUniformityAnalysisImplDeleter { |
21 | // Ugly hack around the fact that recent (> 15.0) clang will run into an |
22 | // is_invocable() check in some GNU libc++'s unique_ptr implementation |
23 | // and reject this deleter if you just make it callable with an ImplT *, |
24 | // whether or not the type of ImplT is spelled out. |
25 | using pointer = ImplT *; |
26 | void operator()(ImplT *Impl); |
27 | }; |
28 | |
29 | template <typename ContextT> class GenericUniformityInfo { |
30 | public: |
31 | using BlockT = typename ContextT::BlockT; |
32 | using FunctionT = typename ContextT::FunctionT; |
33 | using ValueRefT = typename ContextT::ValueRefT; |
34 | using ConstValueRefT = typename ContextT::ConstValueRefT; |
35 | using UseT = typename ContextT::UseT; |
36 | using InstructionT = typename ContextT::InstructionT; |
37 | using DominatorTreeT = typename ContextT::DominatorTreeT; |
38 | using ThisT = GenericUniformityInfo<ContextT>; |
39 | |
40 | using CycleInfoT = GenericCycleInfo<ContextT>; |
41 | using CycleT = typename CycleInfoT::CycleT; |
42 | |
43 | GenericUniformityInfo(const DominatorTreeT &DT, const CycleInfoT &CI, |
44 | const TargetTransformInfo *TTI = nullptr); |
45 | GenericUniformityInfo() = default; |
46 | GenericUniformityInfo(GenericUniformityInfo &&) = default; |
47 | GenericUniformityInfo &operator=(GenericUniformityInfo &&) = default; |
48 | |
49 | void compute() { |
50 | DA->initialize(); |
51 | DA->compute(); |
52 | } |
53 | |
54 | /// Whether any divergence was detected. |
55 | bool hasDivergence() const; |
56 | |
57 | /// The GPU kernel this analysis result is for |
58 | const FunctionT &getFunction() const; |
59 | |
60 | /// Whether \p V is divergent at its definition. |
61 | bool isDivergent(ConstValueRefT V) const; |
62 | |
63 | /// Whether \p V is uniform/non-divergent. |
64 | bool isUniform(ConstValueRefT V) const { return !isDivergent(V); } |
65 | |
66 | // Similar queries for InstructionT. These accept a pointer argument so that |
67 | // in LLVM IR, they overload the equivalent queries for Value*. For example, |
68 | // if querying whether a BranchInst is divergent, it should not be treated as |
69 | // a Value in LLVM IR. |
70 | bool isUniform(const InstructionT *I) const { return !isDivergent(I); }; |
71 | bool isDivergent(const InstructionT *I) const; |
72 | |
73 | /// \brief Whether \p U is divergent. Uses of a uniform value can be |
74 | /// divergent. |
75 | bool isDivergentUse(const UseT &U) const; |
76 | |
77 | bool hasDivergentTerminator(const BlockT &B); |
78 | |
79 | void print(raw_ostream &Out) const; |
80 | |
81 | private: |
82 | using ImplT = GenericUniformityAnalysisImpl<ContextT>; |
83 | |
84 | std::unique_ptr<ImplT, GenericUniformityAnalysisImplDeleter<ImplT>> DA; |
85 | |
86 | GenericUniformityInfo(const GenericUniformityInfo &) = delete; |
87 | GenericUniformityInfo &operator=(const GenericUniformityInfo &) = delete; |
88 | }; |
89 | |
90 | } // namespace llvm |
91 | |
92 | #endif // LLVM_ADT_GENERICUNIFORMITYINFO_H |
93 | |