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->getValueUniformity(&Arg) == ValueUniformity::NeverUniform)
75 DivergentArgs.push_back(&Arg);
76 else
77 UniformValues.insert(&Arg);
78 }
79 for (auto &I : instructions(F)) {
80 ValueUniformity IU = TTI->getValueUniformity(&I);
81 switch (IU) {
83 UniformValues.insert(&I);
85 continue;
87 // Skip inserting -- divergent by definition. Add to Worklist directly
88 // so compute() propagates divergence to users.
89 if (I.isTerminator())
90 DivergentTermBlocks.insert(I.getParent());
91 Worklist.push_back(&I);
92 continue;
94 UniformValues.insert(&I);
96 continue;
98 UniformValues.insert(&I);
99 break;
100 }
101 }
102 // Arguments are not instructions and cannot go on the Worklist, so we
103 // propagate their divergence to users explicitly here. This must happen
104 // after all instructions are in UniformValues so markDivergent (called
105 // inside pushUsers) can successfully erase user instructions from the set.
106 for (const Value *Arg : DivergentArgs)
107 pushUsers(Arg);
108}
109
110template <>
111bool llvm::GenericUniformityAnalysisImpl<SSAContext>::usesValueFromCycle(
112 const Instruction &I, const Cycle &DefCycle) const {
113 assert(!isAlwaysUniform(I));
114 for (const Use &U : I.operands()) {
115 if (auto *I = dyn_cast<Instruction>(&U)) {
116 if (DefCycle.contains(I->getParent()))
117 return true;
118 }
119 }
120 return false;
121}
122
123template <>
125 SSAContext>::propagateTemporalDivergence(const Instruction &I,
126 const Cycle &DefCycle) {
127 for (auto *User : I.users()) {
128 auto *UserInstr = cast<Instruction>(User);
129 if (DefCycle.contains(UserInstr->getParent()))
130 continue;
131 markDivergent(*UserInstr);
132 recordTemporalDivergence(&I, UserInstr, &DefCycle);
133 }
134}
135
136template <>
138 const Use &U) const {
139 const auto *V = U.get();
140 if (isDivergent(V))
141 return true;
142 if (const auto *DefInstr = dyn_cast<Instruction>(V)) {
143 const auto *UseInstr = cast<Instruction>(U.getUser());
144 return isTemporalDivergent(*UseInstr->getParent(), *DefInstr);
145 }
146 return false;
147}
148
149template <>
151 const Instruction &I) const {
152 SmallBitVector UniformArgs(I.getNumOperands());
153 for (auto [Idx, Use] : enumerate(I.operands()))
154 UniformArgs[Idx] = !isDivergentUse(Use);
155 return TTI->isUniform(&I, UniformArgs);
156}
157
158// This ensures explicit instantiation of
159// GenericUniformityAnalysisImpl::ImplDeleter::operator()
163
164//===----------------------------------------------------------------------===//
165// UniformityInfoAnalysis and related pass implementations
166//===----------------------------------------------------------------------===//
167
171 if (!TTI.hasBranchDivergence(&F))
172 return UniformityInfo{};
173 DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
174 CycleInfo &CI = FAM.getResult<CycleAnalysis>(F);
175 UniformityInfo UI{DT, CI, &TTI};
176 UI.compute();
177 return UI;
178}
179
180AnalysisKey UniformityInfoAnalysis::Key;
181
184
187 OS << "UniformityInfo for function '" << F.getName() << "':\n";
189
190 return PreservedAnalyses::all();
191}
192
193//===----------------------------------------------------------------------===//
194// UniformityInfoWrapperPass Implementation
195//===----------------------------------------------------------------------===//
196
198
200
202 "Uniformity Analysis", false, true)
207 "Uniformity Analysis", false, true)
208
210 AU.setPreservesAll();
211 AU.addRequired<DominatorTreeWrapperPass>();
212 AU.addRequiredTransitive<CycleInfoWrapperPass>();
213 AU.addRequired<TargetTransformInfoWrapperPass>();
214}
215
219
220 Fn = &F;
221
222 if (!TTI.hasBranchDivergence(Fn)) {
223 UI = UniformityInfo{};
224 return false;
225 }
226
229 UI = UniformityInfo{DT, CI, &TTI};
230 UI.compute();
231 return false;
232}
233
235 OS << "UniformityInfo for function '" << Fn->getName() << "':\n";
236 UI.print(OS);
237}
238
240 UI = UniformityInfo{};
241 Fn = 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
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:159
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.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
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:426
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.
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
Definition Uniformity.h:18
@ AlwaysUniform
The result value is always uniform.
Definition Uniformity.h:23
@ NeverUniform
The result value can never be assumed to be uniform.
Definition Uniformity.h:26
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
@ Custom
The result value requires 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