xref: /llvm-project/llvm/lib/Analysis/UniformityAnalysis.cpp (revision 236fda550d36d35a00785938c3e38b0f402aeda6)
1c76acb9dSJay Foad //===- UniformityAnalysis.cpp ---------------------------------------------===//
2475ce4c2SSameer Sahasrabuddhe //
3475ce4c2SSameer Sahasrabuddhe // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4475ce4c2SSameer Sahasrabuddhe // See https://llvm.org/LICENSE.txt for license information.
5475ce4c2SSameer Sahasrabuddhe // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6475ce4c2SSameer Sahasrabuddhe //
7475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===//
8475ce4c2SSameer Sahasrabuddhe 
9475ce4c2SSameer Sahasrabuddhe #include "llvm/Analysis/UniformityAnalysis.h"
10475ce4c2SSameer Sahasrabuddhe #include "llvm/ADT/GenericUniformityImpl.h"
11475ce4c2SSameer Sahasrabuddhe #include "llvm/Analysis/CycleAnalysis.h"
12475ce4c2SSameer Sahasrabuddhe #include "llvm/Analysis/TargetTransformInfo.h"
13475ce4c2SSameer Sahasrabuddhe #include "llvm/IR/Dominators.h"
14475ce4c2SSameer Sahasrabuddhe #include "llvm/IR/InstIterator.h"
15475ce4c2SSameer Sahasrabuddhe #include "llvm/IR/Instructions.h"
16475ce4c2SSameer Sahasrabuddhe #include "llvm/InitializePasses.h"
17475ce4c2SSameer Sahasrabuddhe 
18475ce4c2SSameer Sahasrabuddhe using namespace llvm;
19475ce4c2SSameer Sahasrabuddhe 
20475ce4c2SSameer Sahasrabuddhe template <>
21475ce4c2SSameer Sahasrabuddhe bool llvm::GenericUniformityAnalysisImpl<SSAContext>::hasDivergentDefs(
22475ce4c2SSameer Sahasrabuddhe     const Instruction &I) const {
23475ce4c2SSameer Sahasrabuddhe   return isDivergent((const Value *)&I);
24475ce4c2SSameer Sahasrabuddhe }
25475ce4c2SSameer Sahasrabuddhe 
26475ce4c2SSameer Sahasrabuddhe template <>
27475ce4c2SSameer Sahasrabuddhe bool llvm::GenericUniformityAnalysisImpl<SSAContext>::markDefsDivergent(
28fbe1c061SSameer Sahasrabuddhe     const Instruction &Instr) {
290a170eb7SSameer Sahasrabuddhe   return markDivergent(cast<Value>(&Instr));
30475ce4c2SSameer Sahasrabuddhe }
31475ce4c2SSameer Sahasrabuddhe 
32475ce4c2SSameer Sahasrabuddhe template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
33475ce4c2SSameer Sahasrabuddhe   for (auto &I : instructions(F)) {
34dbebebf6Spvanhout     if (TTI->isSourceOfDivergence(&I))
35475ce4c2SSameer Sahasrabuddhe       markDivergent(I);
36dbebebf6Spvanhout     else if (TTI->isAlwaysUniform(&I))
37475ce4c2SSameer Sahasrabuddhe       addUniformOverride(I);
38475ce4c2SSameer Sahasrabuddhe   }
39475ce4c2SSameer Sahasrabuddhe   for (auto &Arg : F.args()) {
40475ce4c2SSameer Sahasrabuddhe     if (TTI->isSourceOfDivergence(&Arg)) {
41475ce4c2SSameer Sahasrabuddhe       markDivergent(&Arg);
42475ce4c2SSameer Sahasrabuddhe     }
43475ce4c2SSameer Sahasrabuddhe   }
44475ce4c2SSameer Sahasrabuddhe }
45475ce4c2SSameer Sahasrabuddhe 
46475ce4c2SSameer Sahasrabuddhe template <>
47475ce4c2SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl<SSAContext>::pushUsers(
48475ce4c2SSameer Sahasrabuddhe     const Value *V) {
49475ce4c2SSameer Sahasrabuddhe   for (const auto *User : V->users()) {
50fd98416dSSameer Sahasrabuddhe     if (const auto *UserInstr = dyn_cast<const Instruction>(User)) {
510a170eb7SSameer Sahasrabuddhe       markDivergent(*UserInstr);
52475ce4c2SSameer Sahasrabuddhe     }
53475ce4c2SSameer Sahasrabuddhe   }
54fd98416dSSameer Sahasrabuddhe }
55475ce4c2SSameer Sahasrabuddhe 
56475ce4c2SSameer Sahasrabuddhe template <>
57475ce4c2SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl<SSAContext>::pushUsers(
58475ce4c2SSameer Sahasrabuddhe     const Instruction &Instr) {
59475ce4c2SSameer Sahasrabuddhe   assert(!isAlwaysUniform(Instr));
60475ce4c2SSameer Sahasrabuddhe   if (Instr.isTerminator())
61475ce4c2SSameer Sahasrabuddhe     return;
62475ce4c2SSameer Sahasrabuddhe   pushUsers(cast<Value>(&Instr));
63475ce4c2SSameer Sahasrabuddhe }
64475ce4c2SSameer Sahasrabuddhe 
65475ce4c2SSameer Sahasrabuddhe template <>
66475ce4c2SSameer Sahasrabuddhe bool llvm::GenericUniformityAnalysisImpl<SSAContext>::usesValueFromCycle(
67475ce4c2SSameer Sahasrabuddhe     const Instruction &I, const Cycle &DefCycle) const {
685230f6c1SYashwant Singh   assert(!isAlwaysUniform(I));
69475ce4c2SSameer Sahasrabuddhe   for (const Use &U : I.operands()) {
70475ce4c2SSameer Sahasrabuddhe     if (auto *I = dyn_cast<Instruction>(&U)) {
71475ce4c2SSameer Sahasrabuddhe       if (DefCycle.contains(I->getParent()))
72475ce4c2SSameer Sahasrabuddhe         return true;
73475ce4c2SSameer Sahasrabuddhe     }
74475ce4c2SSameer Sahasrabuddhe   }
75475ce4c2SSameer Sahasrabuddhe   return false;
76475ce4c2SSameer Sahasrabuddhe }
77475ce4c2SSameer Sahasrabuddhe 
78f90849dfSpvanhout template <>
79b0f0dd25SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl<
80b0f0dd25SSameer Sahasrabuddhe     SSAContext>::propagateTemporalDivergence(const Instruction &I,
81b0f0dd25SSameer Sahasrabuddhe                                              const Cycle &DefCycle) {
82b0f0dd25SSameer Sahasrabuddhe   if (isDivergent(I))
83b0f0dd25SSameer Sahasrabuddhe     return;
84b0f0dd25SSameer Sahasrabuddhe   for (auto *User : I.users()) {
85b0f0dd25SSameer Sahasrabuddhe     auto *UserInstr = cast<Instruction>(User);
86b0f0dd25SSameer Sahasrabuddhe     if (DefCycle.contains(UserInstr->getParent()))
87b0f0dd25SSameer Sahasrabuddhe       continue;
880a170eb7SSameer Sahasrabuddhe     markDivergent(*UserInstr);
89b0f0dd25SSameer Sahasrabuddhe   }
90b0f0dd25SSameer Sahasrabuddhe }
91b0f0dd25SSameer Sahasrabuddhe 
92b0f0dd25SSameer Sahasrabuddhe template <>
93f90849dfSpvanhout bool llvm::GenericUniformityAnalysisImpl<SSAContext>::isDivergentUse(
94f90849dfSpvanhout     const Use &U) const {
95f90849dfSpvanhout   const auto *V = U.get();
96f90849dfSpvanhout   if (isDivergent(V))
97f90849dfSpvanhout     return true;
98f90849dfSpvanhout   if (const auto *DefInstr = dyn_cast<Instruction>(V)) {
99f90849dfSpvanhout     const auto *UseInstr = cast<Instruction>(U.getUser());
100f90849dfSpvanhout     return isTemporalDivergent(*UseInstr->getParent(), *DefInstr);
101f90849dfSpvanhout   }
102f90849dfSpvanhout   return false;
103f90849dfSpvanhout }
104f90849dfSpvanhout 
105475ce4c2SSameer Sahasrabuddhe // This ensures explicit instantiation of
106475ce4c2SSameer Sahasrabuddhe // GenericUniformityAnalysisImpl::ImplDeleter::operator()
107475ce4c2SSameer Sahasrabuddhe template class llvm::GenericUniformityInfo<SSAContext>;
1085d98dc71SKrzysztof Drewniak template struct llvm::GenericUniformityAnalysisImplDeleter<
1095d98dc71SKrzysztof Drewniak     llvm::GenericUniformityAnalysisImpl<SSAContext>>;
110475ce4c2SSameer Sahasrabuddhe 
111475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===//
112475ce4c2SSameer Sahasrabuddhe //  UniformityInfoAnalysis and related pass implementations
113475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===//
114475ce4c2SSameer Sahasrabuddhe 
115475ce4c2SSameer Sahasrabuddhe llvm::UniformityInfo UniformityInfoAnalysis::run(Function &F,
116475ce4c2SSameer Sahasrabuddhe                                                  FunctionAnalysisManager &FAM) {
117475ce4c2SSameer Sahasrabuddhe   auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
118475ce4c2SSameer Sahasrabuddhe   auto &TTI = FAM.getResult<TargetIRAnalysis>(F);
119475ce4c2SSameer Sahasrabuddhe   auto &CI = FAM.getResult<CycleAnalysis>(F);
120*b14e30f1SSameer Sahasrabuddhe   UniformityInfo UI{DT, CI, &TTI};
121d61cba6dSMatt Arsenault   // Skip computation if we can assume everything is uniform.
12253fb907dSMatt Arsenault   if (TTI.hasBranchDivergence(&F))
123d61cba6dSMatt Arsenault     UI.compute();
124d61cba6dSMatt Arsenault 
125d61cba6dSMatt Arsenault   return UI;
126475ce4c2SSameer Sahasrabuddhe }
127475ce4c2SSameer Sahasrabuddhe 
128475ce4c2SSameer Sahasrabuddhe AnalysisKey UniformityInfoAnalysis::Key;
129475ce4c2SSameer Sahasrabuddhe 
130475ce4c2SSameer Sahasrabuddhe UniformityInfoPrinterPass::UniformityInfoPrinterPass(raw_ostream &OS)
131475ce4c2SSameer Sahasrabuddhe     : OS(OS) {}
132475ce4c2SSameer Sahasrabuddhe 
133475ce4c2SSameer Sahasrabuddhe PreservedAnalyses UniformityInfoPrinterPass::run(Function &F,
134475ce4c2SSameer Sahasrabuddhe                                                  FunctionAnalysisManager &AM) {
135475ce4c2SSameer Sahasrabuddhe   OS << "UniformityInfo for function '" << F.getName() << "':\n";
136475ce4c2SSameer Sahasrabuddhe   AM.getResult<UniformityInfoAnalysis>(F).print(OS);
137475ce4c2SSameer Sahasrabuddhe 
138475ce4c2SSameer Sahasrabuddhe   return PreservedAnalyses::all();
139475ce4c2SSameer Sahasrabuddhe }
140475ce4c2SSameer Sahasrabuddhe 
141475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===//
142475ce4c2SSameer Sahasrabuddhe //  UniformityInfoWrapperPass Implementation
143475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===//
144475ce4c2SSameer Sahasrabuddhe 
145475ce4c2SSameer Sahasrabuddhe char UniformityInfoWrapperPass::ID = 0;
146475ce4c2SSameer Sahasrabuddhe 
147475ce4c2SSameer Sahasrabuddhe UniformityInfoWrapperPass::UniformityInfoWrapperPass() : FunctionPass(ID) {
148475ce4c2SSameer Sahasrabuddhe   initializeUniformityInfoWrapperPassPass(*PassRegistry::getPassRegistry());
149475ce4c2SSameer Sahasrabuddhe }
150475ce4c2SSameer Sahasrabuddhe 
151c76acb9dSJay Foad INITIALIZE_PASS_BEGIN(UniformityInfoWrapperPass, "uniformity",
152c76acb9dSJay Foad                       "Uniformity Analysis", true, true)
153475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
154f90849dfSpvanhout INITIALIZE_PASS_DEPENDENCY(CycleInfoWrapperPass)
155475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
156c76acb9dSJay Foad INITIALIZE_PASS_END(UniformityInfoWrapperPass, "uniformity",
157c76acb9dSJay Foad                     "Uniformity Analysis", true, true)
158475ce4c2SSameer Sahasrabuddhe 
159475ce4c2SSameer Sahasrabuddhe void UniformityInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
160475ce4c2SSameer Sahasrabuddhe   AU.setPreservesAll();
161475ce4c2SSameer Sahasrabuddhe   AU.addRequired<DominatorTreeWrapperPass>();
162f90849dfSpvanhout   AU.addRequiredTransitive<CycleInfoWrapperPass>();
163475ce4c2SSameer Sahasrabuddhe   AU.addRequired<TargetTransformInfoWrapperPass>();
164475ce4c2SSameer Sahasrabuddhe }
165475ce4c2SSameer Sahasrabuddhe 
166475ce4c2SSameer Sahasrabuddhe bool UniformityInfoWrapperPass::runOnFunction(Function &F) {
167475ce4c2SSameer Sahasrabuddhe   auto &cycleInfo = getAnalysis<CycleInfoWrapperPass>().getResult();
168475ce4c2SSameer Sahasrabuddhe   auto &domTree = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
169475ce4c2SSameer Sahasrabuddhe   auto &targetTransformInfo =
170475ce4c2SSameer Sahasrabuddhe       getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
171475ce4c2SSameer Sahasrabuddhe 
172475ce4c2SSameer Sahasrabuddhe   m_function = &F;
173*b14e30f1SSameer Sahasrabuddhe   m_uniformityInfo = UniformityInfo{domTree, cycleInfo, &targetTransformInfo};
174d61cba6dSMatt Arsenault 
175d61cba6dSMatt Arsenault   // Skip computation if we can assume everything is uniform.
17653fb907dSMatt Arsenault   if (targetTransformInfo.hasBranchDivergence(m_function))
177d61cba6dSMatt Arsenault     m_uniformityInfo.compute();
178d61cba6dSMatt Arsenault 
179475ce4c2SSameer Sahasrabuddhe   return false;
180475ce4c2SSameer Sahasrabuddhe }
181475ce4c2SSameer Sahasrabuddhe 
182475ce4c2SSameer Sahasrabuddhe void UniformityInfoWrapperPass::print(raw_ostream &OS, const Module *) const {
183475ce4c2SSameer Sahasrabuddhe   OS << "UniformityInfo for function '" << m_function->getName() << "':\n";
184475ce4c2SSameer Sahasrabuddhe }
185475ce4c2SSameer Sahasrabuddhe 
186475ce4c2SSameer Sahasrabuddhe void UniformityInfoWrapperPass::releaseMemory() {
187475ce4c2SSameer Sahasrabuddhe   m_uniformityInfo = UniformityInfo{};
188475ce4c2SSameer Sahasrabuddhe   m_function = nullptr;
189475ce4c2SSameer Sahasrabuddhe }
190