LLVM 23.0.0git
UniformityAnalysis.cpp
Go to the documentation of this file.
1//===- UniformityAnalysis.cpp ---------------------------------------------===//
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
14#include "llvm/IR/Dominators.h"
18
19using namespace llvm;
20
21template <>
26
27template <>
32
33template <>
34void llvm::GenericUniformityAnalysisImpl<SSAContext>::pushUsers(
35 const Value *V) {
36 for (const auto *User : V->users()) {
37 if (const auto *UserInstr = dyn_cast<const Instruction>(User)) {
38 markDivergent(*UserInstr);
39 }
40 }
41}
42
43template <>
44void llvm::GenericUniformityAnalysisImpl<SSAContext>::pushUsers(
45 const Instruction &Instr) {
46 assert(!isAlwaysUniform(Instr));
47 if (Instr.isTerminator())
48 return;
49 pushUsers(cast<Value>(&Instr));
50}
51
52template <>
54 raw_ostream &OS) const {
55 bool haveDivergentArgs = false;
56 for (const auto &Arg : F.args()) {
57 if (isDivergent(&Arg)) {
58 if (!haveDivergentArgs) {
59 OS << "DIVERGENT ARGUMENTS:\n";
60 haveDivergentArgs = true;
61 }
62 OS << " DIVERGENT: " << Context.print(&Arg) << '\n';
63 }
64 }
65 return haveDivergentArgs;
66}
67
69 // Pre-populate UniformValues with uniform values, then seed divergence.
70 // NeverUniform values are not inserted -- they are divergent by definition
71 // and will be reported as such by isDivergent() (not in UniformValues).
73 for (auto &Arg : F.args()) {
74 if (TTI->getInstructionUniformity(&Arg) ==
76 DivergentArgs.push_back(&Arg);
77 else
78 UniformValues.insert(&Arg);
79 }
80 for (auto &I : instructions(F)) {
81 InstructionUniformity IU = TTI->getInstructionUniformity(&I);
82 switch (IU) {
84 UniformValues.insert(&I);
86 continue;
88 // Skip inserting -- divergent by definition. Add to Worklist directly
89 // so compute() propagates divergence to users.
90 if (I.isTerminator())
91 DivergentTermBlocks.insert(I.getParent());
92 Worklist.push_back(&I);
93 continue;
95 UniformValues.insert(&I);
97 continue;
99 UniformValues.insert(&I);
100 break;
101 }
102 }
103 // Arguments are not instructions and cannot go on the Worklist, so we
104 // propagate their divergence to users explicitly here. This must happen
105 // after all instructions are in UniformValues so markDivergent (called
106 // inside pushUsers) can successfully erase user instructions from the set.
107 for (const Value *Arg : DivergentArgs)
108 pushUsers(Arg);
109}
110
111template <>
112bool llvm::GenericUniformityAnalysisImpl<SSAContext>::usesValueFromCycle(
113 const Instruction &I, const Cycle &DefCycle) const {
114 assert(!isAlwaysUniform(I));
115 for (const Use &U : I.operands()) {
116 if (auto *I = dyn_cast<Instruction>(&U)) {
117 if (DefCycle.contains(I->getParent()))
118 return true;
119 }
120 }
121 return false;
122}
123
124template <>
126 SSAContext>::propagateTemporalDivergence(const Instruction &I,
127 const Cycle &DefCycle) {
128 for (auto *User : I.users()) {
129 auto *UserInstr = cast<Instruction>(User);
130 if (DefCycle.contains(UserInstr->getParent()))
131 continue;
132 markDivergent(*UserInstr);
133 recordTemporalDivergence(&I, UserInstr, &DefCycle);
134 }
135}
136
137template <>
139 const Use &U) const {
140 const auto *V = U.get();
141 if (isDivergent(V))
142 return true;
143 if (const auto *DefInstr = dyn_cast<Instruction>(V)) {
144 const auto *UseInstr = cast<Instruction>(U.getUser());
145 return isTemporalDivergent(*UseInstr->getParent(), *DefInstr);
146 }
147 return false;
148}
149
150template <>
152 const Instruction &I) const {
153 SmallBitVector UniformArgs(I.getNumOperands());
154 for (auto [Idx, Use] : enumerate(I.operands()))
155 UniformArgs[Idx] = !isDivergentUse(Use);
156 return TTI->isUniform(&I, UniformArgs);
157}
158
159// This ensures explicit instantiation of
160// GenericUniformityAnalysisImpl::ImplDeleter::operator()
164
165//===----------------------------------------------------------------------===//
166// UniformityInfoAnalysis and related pass implementations
167//===----------------------------------------------------------------------===//
168
171 auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
172 auto &TTI = FAM.getResult<TargetIRAnalysis>(F);
173 auto &CI = FAM.getResult<CycleAnalysis>(F);
174 UniformityInfo UI{DT, CI, &TTI};
175 // Skip computation if we can assume everything is uniform.
176 if (TTI.hasBranchDivergence(&F))
177 UI.compute();
178
179 return UI;
180}
181
182AnalysisKey UniformityInfoAnalysis::Key;
183
186
189 OS << "UniformityInfo for function '" << F.getName() << "':\n";
191
192 return PreservedAnalyses::all();
193}
194
195//===----------------------------------------------------------------------===//
196// UniformityInfoWrapperPass Implementation
197//===----------------------------------------------------------------------===//
198
200
202
204 "Uniformity Analysis", false, true)
209 "Uniformity Analysis", false, true)
210
212 AU.setPreservesAll();
213 AU.addRequired<DominatorTreeWrapperPass>();
214 AU.addRequiredTransitive<CycleInfoWrapperPass>();
215 AU.addRequired<TargetTransformInfoWrapperPass>();
216}
217
219 auto &cycleInfo = getAnalysis<CycleInfoWrapperPass>().getResult();
220 auto &domTree = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
221 auto &targetTransformInfo =
223
224 m_function = &F;
225 m_uniformityInfo = UniformityInfo{domTree, cycleInfo, &targetTransformInfo};
226
227 // Skip computation if we can assume everything is uniform.
228 if (targetTransformInfo.hasBranchDivergence(m_function))
229 m_uniformityInfo.compute();
230
231 return false;
232}
233
235 OS << "UniformityInfo for function '" << m_function->getName() << "':\n";
236 m_uniformityInfo.print(OS);
237}
238
240 m_uniformityInfo = UniformityInfo{};
241 m_function = nullptr;
242}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
This file declares an analysis pass that computes CycleInfo for LLVM IR, specialized from GenericCycl...
Implementation of uniformity analysis.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file implements the SmallBitVector class.
This pass exposes codegen information to IR-level passes.
LLVM IR instance of the generic uniformity analysis.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
Analysis pass which computes a CycleInfo.
Legacy analysis pass which computes a CycleInfo.
Analysis pass which computes a DominatorTree.
Definition Dominators.h:278
Legacy analysis pass which computes a DominatorTree.
Definition Dominators.h:316
FunctionPass(char &pid)
Definition Pass.h:316
bool contains(const BlockT *Block) const
Return whether Block is contained in the cycle.
Analysis that identifies uniform values in a data-parallel execution.
bool isCustomUniform(const InstructionT &I) const
Check if an instruction with Custom uniformity can be proven uniform based on its operands.
void addCustomUniformityCandidate(const InstructionT *I)
Add an instruction that requires custom uniformity analysis.
bool isDivergentUse(const UseT &U) const
bool hasDivergentDefs(const InstructionT &I) const
bool printDivergentArgs(raw_ostream &out) const
Print divergent arguments and return true if any were found.
bool markDefsDivergent(const InstructionT &Instr)
Mark outputs of Instr as divergent.
bool isDivergent(const InstructionT &I) const
std::vector< const InstructionT * > Worklist
void markDivergent(const InstructionT &I)
Examine I for divergent outputs and add to the worklist.
SmallPtrSet< const BlockT *, 32 > DivergentTermBlocks
void addUniformOverride(const InstructionT &Instr)
Mark UniVal as a value that is always uniform.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetTransformInfo.
Wrapper pass for TargetTransformInfo.
Analysis pass which computes UniformityInfo.
UniformityInfo run(Function &F, FunctionAnalysisManager &)
Run the analysis pass over a function and produce a dominator tree.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Legacy analysis pass which computes a CycleInfo.
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void print(raw_ostream &OS, const Module *M=nullptr) const override
print - Print out the internal state of the pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
iterator_range< user_iterator > users()
Definition Value.h:427
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
NodeAddr< InstrNode * > Instr
Definition RDFGraph.h:389
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
GenericSSAContext< Function > SSAContext
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
CycleInfo::CycleT Cycle
Definition CycleInfo.h:26
TargetTransformInfo TTI
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
InstructionUniformity
Enum describing how instructions behave with respect to uniformity and divergence,...
Definition Uniformity.h:18
@ AlwaysUniform
The result values are always uniform.
Definition Uniformity.h:23
@ NeverUniform
The result values can never be assumed to be uniform.
Definition Uniformity.h:26
@ Default
The result values are uniform if and only if all operands are uniform.
Definition Uniformity.h:20
@ Custom
The result values require a custom uniformity check.
Definition Uniformity.h:31
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29