xref: /llvm-project/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp (revision 1562b70eaf6e0b95910fa684dfc53bd5ca6252e7)
1475ce4c2SSameer Sahasrabuddhe //===- MachineUniformityAnalysis.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/CodeGen/MachineUniformityAnalysis.h"
10475ce4c2SSameer Sahasrabuddhe #include "llvm/ADT/GenericUniformityImpl.h"
11475ce4c2SSameer Sahasrabuddhe #include "llvm/CodeGen/MachineCycleAnalysis.h"
12475ce4c2SSameer Sahasrabuddhe #include "llvm/CodeGen/MachineDominators.h"
13475ce4c2SSameer Sahasrabuddhe #include "llvm/CodeGen/MachineRegisterInfo.h"
14475ce4c2SSameer Sahasrabuddhe #include "llvm/CodeGen/MachineSSAContext.h"
15475ce4c2SSameer Sahasrabuddhe #include "llvm/CodeGen/TargetInstrInfo.h"
16475ce4c2SSameer Sahasrabuddhe #include "llvm/InitializePasses.h"
17475ce4c2SSameer Sahasrabuddhe 
18475ce4c2SSameer Sahasrabuddhe using namespace llvm;
19475ce4c2SSameer Sahasrabuddhe 
20475ce4c2SSameer Sahasrabuddhe template <>
21475ce4c2SSameer Sahasrabuddhe bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::hasDivergentDefs(
22475ce4c2SSameer Sahasrabuddhe     const MachineInstr &I) const {
235022fc2aSJay Foad   for (auto &op : I.all_defs()) {
24475ce4c2SSameer Sahasrabuddhe     if (isDivergent(op.getReg()))
25475ce4c2SSameer Sahasrabuddhe       return true;
26475ce4c2SSameer Sahasrabuddhe   }
27475ce4c2SSameer Sahasrabuddhe   return false;
28475ce4c2SSameer Sahasrabuddhe }
29475ce4c2SSameer Sahasrabuddhe 
30475ce4c2SSameer Sahasrabuddhe template <>
31475ce4c2SSameer Sahasrabuddhe bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::markDefsDivergent(
32fbe1c061SSameer Sahasrabuddhe     const MachineInstr &Instr) {
33475ce4c2SSameer Sahasrabuddhe   bool insertedDivergent = false;
34475ce4c2SSameer Sahasrabuddhe   const auto &MRI = F.getRegInfo();
35fbe1c061SSameer Sahasrabuddhe   const auto &RBI = *F.getSubtarget().getRegBankInfo();
36475ce4c2SSameer Sahasrabuddhe   const auto &TRI = *MRI.getTargetRegisterInfo();
375022fc2aSJay Foad   for (auto &op : Instr.all_defs()) {
38475ce4c2SSameer Sahasrabuddhe     if (!op.getReg().isVirtual())
39475ce4c2SSameer Sahasrabuddhe       continue;
40475ce4c2SSameer Sahasrabuddhe     assert(!op.getSubReg());
41fbe1c061SSameer Sahasrabuddhe     if (TRI.isUniformReg(MRI, RBI, op.getReg()))
42475ce4c2SSameer Sahasrabuddhe       continue;
43475ce4c2SSameer Sahasrabuddhe     insertedDivergent |= markDivergent(op.getReg());
44475ce4c2SSameer Sahasrabuddhe   }
45475ce4c2SSameer Sahasrabuddhe   return insertedDivergent;
46475ce4c2SSameer Sahasrabuddhe }
47475ce4c2SSameer Sahasrabuddhe 
48475ce4c2SSameer Sahasrabuddhe template <>
49475ce4c2SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
50475ce4c2SSameer Sahasrabuddhe   const auto &InstrInfo = *F.getSubtarget().getInstrInfo();
51475ce4c2SSameer Sahasrabuddhe 
52475ce4c2SSameer Sahasrabuddhe   for (const MachineBasicBlock &block : F) {
53475ce4c2SSameer Sahasrabuddhe     for (const MachineInstr &instr : block) {
54475ce4c2SSameer Sahasrabuddhe       auto uniformity = InstrInfo.getInstructionUniformity(instr);
55475ce4c2SSameer Sahasrabuddhe       if (uniformity == InstructionUniformity::AlwaysUniform) {
56475ce4c2SSameer Sahasrabuddhe         addUniformOverride(instr);
57475ce4c2SSameer Sahasrabuddhe         continue;
58475ce4c2SSameer Sahasrabuddhe       }
59475ce4c2SSameer Sahasrabuddhe 
60475ce4c2SSameer Sahasrabuddhe       if (uniformity == InstructionUniformity::NeverUniform) {
610a170eb7SSameer Sahasrabuddhe         markDivergent(instr);
62475ce4c2SSameer Sahasrabuddhe       }
63475ce4c2SSameer Sahasrabuddhe     }
64475ce4c2SSameer Sahasrabuddhe   }
65475ce4c2SSameer Sahasrabuddhe }
66475ce4c2SSameer Sahasrabuddhe 
67475ce4c2SSameer Sahasrabuddhe template <>
68475ce4c2SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
69475ce4c2SSameer Sahasrabuddhe     Register Reg) {
700a170eb7SSameer Sahasrabuddhe   assert(isDivergent(Reg));
71475ce4c2SSameer Sahasrabuddhe   const auto &RegInfo = F.getRegInfo();
72475ce4c2SSameer Sahasrabuddhe   for (MachineInstr &UserInstr : RegInfo.use_instructions(Reg)) {
730a170eb7SSameer Sahasrabuddhe     markDivergent(UserInstr);
74475ce4c2SSameer Sahasrabuddhe   }
75475ce4c2SSameer Sahasrabuddhe }
76475ce4c2SSameer Sahasrabuddhe 
77475ce4c2SSameer Sahasrabuddhe template <>
78475ce4c2SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
79475ce4c2SSameer Sahasrabuddhe     const MachineInstr &Instr) {
80475ce4c2SSameer Sahasrabuddhe   assert(!isAlwaysUniform(Instr));
81475ce4c2SSameer Sahasrabuddhe   if (Instr.isTerminator())
82475ce4c2SSameer Sahasrabuddhe     return;
835022fc2aSJay Foad   for (const MachineOperand &op : Instr.all_defs()) {
840a170eb7SSameer Sahasrabuddhe     auto Reg = op.getReg();
850a170eb7SSameer Sahasrabuddhe     if (isDivergent(Reg))
860a170eb7SSameer Sahasrabuddhe       pushUsers(Reg);
87475ce4c2SSameer Sahasrabuddhe   }
88475ce4c2SSameer Sahasrabuddhe }
89475ce4c2SSameer Sahasrabuddhe 
90475ce4c2SSameer Sahasrabuddhe template <>
91475ce4c2SSameer Sahasrabuddhe bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::usesValueFromCycle(
92475ce4c2SSameer Sahasrabuddhe     const MachineInstr &I, const MachineCycle &DefCycle) const {
93475ce4c2SSameer Sahasrabuddhe   assert(!isAlwaysUniform(I));
94475ce4c2SSameer Sahasrabuddhe   for (auto &Op : I.operands()) {
95475ce4c2SSameer Sahasrabuddhe     if (!Op.isReg() || !Op.readsReg())
96475ce4c2SSameer Sahasrabuddhe       continue;
97475ce4c2SSameer Sahasrabuddhe     auto Reg = Op.getReg();
985230f6c1SYashwant Singh 
995230f6c1SYashwant Singh     // FIXME: Physical registers need to be properly checked instead of always
1005230f6c1SYashwant Singh     // returning true
1015230f6c1SYashwant Singh     if (Reg.isPhysical())
1025230f6c1SYashwant Singh       return true;
1035230f6c1SYashwant Singh 
104475ce4c2SSameer Sahasrabuddhe     auto *Def = F.getRegInfo().getVRegDef(Reg);
105475ce4c2SSameer Sahasrabuddhe     if (DefCycle.contains(Def->getParent()))
106475ce4c2SSameer Sahasrabuddhe       return true;
107475ce4c2SSameer Sahasrabuddhe   }
108475ce4c2SSameer Sahasrabuddhe   return false;
109475ce4c2SSameer Sahasrabuddhe }
110475ce4c2SSameer Sahasrabuddhe 
111f90849dfSpvanhout template <>
112b0f0dd25SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::
113b0f0dd25SSameer Sahasrabuddhe     propagateTemporalDivergence(const MachineInstr &I,
114b0f0dd25SSameer Sahasrabuddhe                                 const MachineCycle &DefCycle) {
115b0f0dd25SSameer Sahasrabuddhe   const auto &RegInfo = F.getRegInfo();
1165022fc2aSJay Foad   for (auto &Op : I.all_defs()) {
117b0f0dd25SSameer Sahasrabuddhe     if (!Op.getReg().isVirtual())
118b0f0dd25SSameer Sahasrabuddhe       continue;
119b0f0dd25SSameer Sahasrabuddhe     auto Reg = Op.getReg();
120b0f0dd25SSameer Sahasrabuddhe     if (isDivergent(Reg))
121b0f0dd25SSameer Sahasrabuddhe       continue;
122b0f0dd25SSameer Sahasrabuddhe     for (MachineInstr &UserInstr : RegInfo.use_instructions(Reg)) {
123b0f0dd25SSameer Sahasrabuddhe       if (DefCycle.contains(UserInstr.getParent()))
124b0f0dd25SSameer Sahasrabuddhe         continue;
1250a170eb7SSameer Sahasrabuddhe       markDivergent(UserInstr);
126b0f0dd25SSameer Sahasrabuddhe     }
127b0f0dd25SSameer Sahasrabuddhe   }
128b0f0dd25SSameer Sahasrabuddhe }
129b0f0dd25SSameer Sahasrabuddhe 
130b0f0dd25SSameer Sahasrabuddhe template <>
131f90849dfSpvanhout bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::isDivergentUse(
132f90849dfSpvanhout     const MachineOperand &U) const {
133f90849dfSpvanhout   if (!U.isReg())
134f90849dfSpvanhout     return false;
135f90849dfSpvanhout 
136f90849dfSpvanhout   auto Reg = U.getReg();
137f90849dfSpvanhout   if (isDivergent(Reg))
138f90849dfSpvanhout     return true;
139f90849dfSpvanhout 
140f90849dfSpvanhout   const auto &RegInfo = F.getRegInfo();
141f90849dfSpvanhout   auto *Def = RegInfo.getOneDef(Reg);
142f90849dfSpvanhout   if (!Def)
143f90849dfSpvanhout     return true;
144f90849dfSpvanhout 
145f90849dfSpvanhout   auto *DefInstr = Def->getParent();
146f90849dfSpvanhout   auto *UseInstr = U.getParent();
147f90849dfSpvanhout   return isTemporalDivergent(*UseInstr->getParent(), *DefInstr);
148f90849dfSpvanhout }
149f90849dfSpvanhout 
150475ce4c2SSameer Sahasrabuddhe // This ensures explicit instantiation of
151475ce4c2SSameer Sahasrabuddhe // GenericUniformityAnalysisImpl::ImplDeleter::operator()
152475ce4c2SSameer Sahasrabuddhe template class llvm::GenericUniformityInfo<MachineSSAContext>;
1535d98dc71SKrzysztof Drewniak template struct llvm::GenericUniformityAnalysisImplDeleter<
1545d98dc71SKrzysztof Drewniak     llvm::GenericUniformityAnalysisImpl<MachineSSAContext>>;
155475ce4c2SSameer Sahasrabuddhe 
156d61cba6dSMatt Arsenault MachineUniformityInfo llvm::computeMachineUniformityInfo(
157d61cba6dSMatt Arsenault     MachineFunction &F, const MachineCycleInfo &cycleInfo,
158837dc542Spaperchalice     const MachineDominatorTree &domTree, bool HasBranchDivergence) {
159ad3996c1SHaojian Wu   assert(F.getRegInfo().isSSA() && "Expected to be run on SSA form!");
160b14e30f1SSameer Sahasrabuddhe   MachineUniformityInfo UI(domTree, cycleInfo);
161d61cba6dSMatt Arsenault   if (HasBranchDivergence)
162d61cba6dSMatt Arsenault     UI.compute();
163d61cba6dSMatt Arsenault   return UI;
164475ce4c2SSameer Sahasrabuddhe }
165475ce4c2SSameer Sahasrabuddhe 
166475ce4c2SSameer Sahasrabuddhe namespace {
167475ce4c2SSameer Sahasrabuddhe 
168475ce4c2SSameer Sahasrabuddhe class MachineUniformityInfoPrinterPass : public MachineFunctionPass {
169475ce4c2SSameer Sahasrabuddhe public:
170475ce4c2SSameer Sahasrabuddhe   static char ID;
171475ce4c2SSameer Sahasrabuddhe 
172475ce4c2SSameer Sahasrabuddhe   MachineUniformityInfoPrinterPass();
173475ce4c2SSameer Sahasrabuddhe 
174475ce4c2SSameer Sahasrabuddhe   bool runOnMachineFunction(MachineFunction &F) override;
175475ce4c2SSameer Sahasrabuddhe   void getAnalysisUsage(AnalysisUsage &AU) const override;
176475ce4c2SSameer Sahasrabuddhe };
177475ce4c2SSameer Sahasrabuddhe 
178475ce4c2SSameer Sahasrabuddhe } // namespace
179475ce4c2SSameer Sahasrabuddhe 
180475ce4c2SSameer Sahasrabuddhe char MachineUniformityAnalysisPass::ID = 0;
181475ce4c2SSameer Sahasrabuddhe 
182475ce4c2SSameer Sahasrabuddhe MachineUniformityAnalysisPass::MachineUniformityAnalysisPass()
183475ce4c2SSameer Sahasrabuddhe     : MachineFunctionPass(ID) {
184475ce4c2SSameer Sahasrabuddhe   initializeMachineUniformityAnalysisPassPass(*PassRegistry::getPassRegistry());
185475ce4c2SSameer Sahasrabuddhe }
186475ce4c2SSameer Sahasrabuddhe 
187475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_BEGIN(MachineUniformityAnalysisPass, "machine-uniformity",
188475ce4c2SSameer Sahasrabuddhe                       "Machine Uniformity Info Analysis", true, true)
189475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)
190837dc542Spaperchalice INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
191475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_END(MachineUniformityAnalysisPass, "machine-uniformity",
192475ce4c2SSameer Sahasrabuddhe                     "Machine Uniformity Info Analysis", true, true)
193475ce4c2SSameer Sahasrabuddhe 
194475ce4c2SSameer Sahasrabuddhe void MachineUniformityAnalysisPass::getAnalysisUsage(AnalysisUsage &AU) const {
195475ce4c2SSameer Sahasrabuddhe   AU.setPreservesAll();
196475ce4c2SSameer Sahasrabuddhe   AU.addRequired<MachineCycleInfoWrapperPass>();
197837dc542Spaperchalice   AU.addRequired<MachineDominatorTreeWrapperPass>();
198475ce4c2SSameer Sahasrabuddhe   MachineFunctionPass::getAnalysisUsage(AU);
199475ce4c2SSameer Sahasrabuddhe }
200475ce4c2SSameer Sahasrabuddhe 
201475ce4c2SSameer Sahasrabuddhe bool MachineUniformityAnalysisPass::runOnMachineFunction(MachineFunction &MF) {
202*1562b70eSpaperchalice   auto &DomTree = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
203475ce4c2SSameer Sahasrabuddhe   auto &CI = getAnalysis<MachineCycleInfoWrapperPass>().getCycleInfo();
204d61cba6dSMatt Arsenault   // FIXME: Query TTI::hasBranchDivergence. -run-pass seems to end up with a
205d61cba6dSMatt Arsenault   // default NoTTI
206d61cba6dSMatt Arsenault   UI = computeMachineUniformityInfo(MF, CI, DomTree, true);
207475ce4c2SSameer Sahasrabuddhe   return false;
208475ce4c2SSameer Sahasrabuddhe }
209475ce4c2SSameer Sahasrabuddhe 
210475ce4c2SSameer Sahasrabuddhe void MachineUniformityAnalysisPass::print(raw_ostream &OS,
211475ce4c2SSameer Sahasrabuddhe                                           const Module *) const {
212475ce4c2SSameer Sahasrabuddhe   OS << "MachineUniformityInfo for function: " << UI.getFunction().getName()
213475ce4c2SSameer Sahasrabuddhe      << "\n";
214475ce4c2SSameer Sahasrabuddhe   UI.print(OS);
215475ce4c2SSameer Sahasrabuddhe }
216475ce4c2SSameer Sahasrabuddhe 
217475ce4c2SSameer Sahasrabuddhe char MachineUniformityInfoPrinterPass::ID = 0;
218475ce4c2SSameer Sahasrabuddhe 
219475ce4c2SSameer Sahasrabuddhe MachineUniformityInfoPrinterPass::MachineUniformityInfoPrinterPass()
220475ce4c2SSameer Sahasrabuddhe     : MachineFunctionPass(ID) {
221475ce4c2SSameer Sahasrabuddhe   initializeMachineUniformityInfoPrinterPassPass(
222475ce4c2SSameer Sahasrabuddhe       *PassRegistry::getPassRegistry());
223475ce4c2SSameer Sahasrabuddhe }
224475ce4c2SSameer Sahasrabuddhe 
225475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_BEGIN(MachineUniformityInfoPrinterPass,
226475ce4c2SSameer Sahasrabuddhe                       "print-machine-uniformity",
227475ce4c2SSameer Sahasrabuddhe                       "Print Machine Uniformity Info Analysis", true, true)
228475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_DEPENDENCY(MachineUniformityAnalysisPass)
229475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_END(MachineUniformityInfoPrinterPass,
230475ce4c2SSameer Sahasrabuddhe                     "print-machine-uniformity",
231475ce4c2SSameer Sahasrabuddhe                     "Print Machine Uniformity Info Analysis", true, true)
232475ce4c2SSameer Sahasrabuddhe 
233475ce4c2SSameer Sahasrabuddhe void MachineUniformityInfoPrinterPass::getAnalysisUsage(
234475ce4c2SSameer Sahasrabuddhe     AnalysisUsage &AU) const {
235475ce4c2SSameer Sahasrabuddhe   AU.setPreservesAll();
236475ce4c2SSameer Sahasrabuddhe   AU.addRequired<MachineUniformityAnalysisPass>();
237475ce4c2SSameer Sahasrabuddhe   MachineFunctionPass::getAnalysisUsage(AU);
238475ce4c2SSameer Sahasrabuddhe }
239475ce4c2SSameer Sahasrabuddhe 
240475ce4c2SSameer Sahasrabuddhe bool MachineUniformityInfoPrinterPass::runOnMachineFunction(
241475ce4c2SSameer Sahasrabuddhe     MachineFunction &F) {
242475ce4c2SSameer Sahasrabuddhe   auto &UI = getAnalysis<MachineUniformityAnalysisPass>();
243475ce4c2SSameer Sahasrabuddhe   UI.print(errs());
244475ce4c2SSameer Sahasrabuddhe   return false;
245475ce4c2SSameer Sahasrabuddhe }
246