xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1*bdd1243dSDimitry Andric //===- MachineUniformityAnalysis.cpp --------------------------------------===//
2*bdd1243dSDimitry Andric //
3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bdd1243dSDimitry Andric //
7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8*bdd1243dSDimitry Andric 
9*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineUniformityAnalysis.h"
10*bdd1243dSDimitry Andric #include "llvm/ADT/GenericUniformityImpl.h"
11*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineCycleAnalysis.h"
12*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
13*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
14*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineSSAContext.h"
15*bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
16*bdd1243dSDimitry Andric #include "llvm/InitializePasses.h"
17*bdd1243dSDimitry Andric 
18*bdd1243dSDimitry Andric using namespace llvm;
19*bdd1243dSDimitry Andric 
20*bdd1243dSDimitry Andric template <>
21*bdd1243dSDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::hasDivergentDefs(
22*bdd1243dSDimitry Andric     const MachineInstr &I) const {
23*bdd1243dSDimitry Andric   for (auto &op : I.operands()) {
24*bdd1243dSDimitry Andric     if (!op.isReg() || !op.isDef())
25*bdd1243dSDimitry Andric       continue;
26*bdd1243dSDimitry Andric     if (isDivergent(op.getReg()))
27*bdd1243dSDimitry Andric       return true;
28*bdd1243dSDimitry Andric   }
29*bdd1243dSDimitry Andric   return false;
30*bdd1243dSDimitry Andric }
31*bdd1243dSDimitry Andric 
32*bdd1243dSDimitry Andric template <>
33*bdd1243dSDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::markDefsDivergent(
34*bdd1243dSDimitry Andric     const MachineInstr &Instr, bool AllDefsDivergent) {
35*bdd1243dSDimitry Andric   bool insertedDivergent = false;
36*bdd1243dSDimitry Andric   const auto &MRI = F.getRegInfo();
37*bdd1243dSDimitry Andric   const auto &TRI = *MRI.getTargetRegisterInfo();
38*bdd1243dSDimitry Andric   for (auto &op : Instr.operands()) {
39*bdd1243dSDimitry Andric     if (!op.isReg() || !op.isDef())
40*bdd1243dSDimitry Andric       continue;
41*bdd1243dSDimitry Andric     if (!op.getReg().isVirtual())
42*bdd1243dSDimitry Andric       continue;
43*bdd1243dSDimitry Andric     assert(!op.getSubReg());
44*bdd1243dSDimitry Andric     if (!AllDefsDivergent) {
45*bdd1243dSDimitry Andric       auto *RC = MRI.getRegClassOrNull(op.getReg());
46*bdd1243dSDimitry Andric       if (RC && !TRI.isDivergentRegClass(RC))
47*bdd1243dSDimitry Andric         continue;
48*bdd1243dSDimitry Andric     }
49*bdd1243dSDimitry Andric     insertedDivergent |= markDivergent(op.getReg());
50*bdd1243dSDimitry Andric   }
51*bdd1243dSDimitry Andric   return insertedDivergent;
52*bdd1243dSDimitry Andric }
53*bdd1243dSDimitry Andric 
54*bdd1243dSDimitry Andric template <>
55*bdd1243dSDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
56*bdd1243dSDimitry Andric   const auto &InstrInfo = *F.getSubtarget().getInstrInfo();
57*bdd1243dSDimitry Andric 
58*bdd1243dSDimitry Andric   for (const MachineBasicBlock &block : F) {
59*bdd1243dSDimitry Andric     for (const MachineInstr &instr : block) {
60*bdd1243dSDimitry Andric       auto uniformity = InstrInfo.getInstructionUniformity(instr);
61*bdd1243dSDimitry Andric       if (uniformity == InstructionUniformity::AlwaysUniform) {
62*bdd1243dSDimitry Andric         addUniformOverride(instr);
63*bdd1243dSDimitry Andric         continue;
64*bdd1243dSDimitry Andric       }
65*bdd1243dSDimitry Andric 
66*bdd1243dSDimitry Andric       if (uniformity == InstructionUniformity::NeverUniform) {
67*bdd1243dSDimitry Andric         markDefsDivergent(instr, /* AllDefsDivergent = */ false);
68*bdd1243dSDimitry Andric       }
69*bdd1243dSDimitry Andric     }
70*bdd1243dSDimitry Andric   }
71*bdd1243dSDimitry Andric }
72*bdd1243dSDimitry Andric 
73*bdd1243dSDimitry Andric template <>
74*bdd1243dSDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
75*bdd1243dSDimitry Andric     Register Reg) {
76*bdd1243dSDimitry Andric   const auto &RegInfo = F.getRegInfo();
77*bdd1243dSDimitry Andric   for (MachineInstr &UserInstr : RegInfo.use_instructions(Reg)) {
78*bdd1243dSDimitry Andric     if (isAlwaysUniform(UserInstr))
79*bdd1243dSDimitry Andric       continue;
80*bdd1243dSDimitry Andric     if (markDivergent(UserInstr))
81*bdd1243dSDimitry Andric       Worklist.push_back(&UserInstr);
82*bdd1243dSDimitry Andric   }
83*bdd1243dSDimitry Andric }
84*bdd1243dSDimitry Andric 
85*bdd1243dSDimitry Andric template <>
86*bdd1243dSDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
87*bdd1243dSDimitry Andric     const MachineInstr &Instr) {
88*bdd1243dSDimitry Andric   assert(!isAlwaysUniform(Instr));
89*bdd1243dSDimitry Andric   if (Instr.isTerminator())
90*bdd1243dSDimitry Andric     return;
91*bdd1243dSDimitry Andric   for (const MachineOperand &op : Instr.operands()) {
92*bdd1243dSDimitry Andric     if (op.isReg() && op.isDef() && op.getReg().isVirtual())
93*bdd1243dSDimitry Andric       pushUsers(op.getReg());
94*bdd1243dSDimitry Andric   }
95*bdd1243dSDimitry Andric }
96*bdd1243dSDimitry Andric 
97*bdd1243dSDimitry Andric template <>
98*bdd1243dSDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::usesValueFromCycle(
99*bdd1243dSDimitry Andric     const MachineInstr &I, const MachineCycle &DefCycle) const {
100*bdd1243dSDimitry Andric   assert(!isAlwaysUniform(I));
101*bdd1243dSDimitry Andric   for (auto &Op : I.operands()) {
102*bdd1243dSDimitry Andric     if (!Op.isReg() || !Op.readsReg())
103*bdd1243dSDimitry Andric       continue;
104*bdd1243dSDimitry Andric     auto Reg = Op.getReg();
105*bdd1243dSDimitry Andric     assert(Reg.isVirtual());
106*bdd1243dSDimitry Andric     auto *Def = F.getRegInfo().getVRegDef(Reg);
107*bdd1243dSDimitry Andric     if (DefCycle.contains(Def->getParent()))
108*bdd1243dSDimitry Andric       return true;
109*bdd1243dSDimitry Andric   }
110*bdd1243dSDimitry Andric   return false;
111*bdd1243dSDimitry Andric }
112*bdd1243dSDimitry Andric 
113*bdd1243dSDimitry Andric // This ensures explicit instantiation of
114*bdd1243dSDimitry Andric // GenericUniformityAnalysisImpl::ImplDeleter::operator()
115*bdd1243dSDimitry Andric template class llvm::GenericUniformityInfo<MachineSSAContext>;
116*bdd1243dSDimitry Andric template struct llvm::GenericUniformityAnalysisImplDeleter<
117*bdd1243dSDimitry Andric     llvm::GenericUniformityAnalysisImpl<MachineSSAContext>>;
118*bdd1243dSDimitry Andric 
119*bdd1243dSDimitry Andric MachineUniformityInfo
120*bdd1243dSDimitry Andric llvm::computeMachineUniformityInfo(MachineFunction &F,
121*bdd1243dSDimitry Andric                                    const MachineCycleInfo &cycleInfo,
122*bdd1243dSDimitry Andric                                    const MachineDomTree &domTree) {
123*bdd1243dSDimitry Andric   assert(F.getRegInfo().isSSA() && "Expected to be run on SSA form!");
124*bdd1243dSDimitry Andric   return MachineUniformityInfo(F, domTree, cycleInfo);
125*bdd1243dSDimitry Andric }
126*bdd1243dSDimitry Andric 
127*bdd1243dSDimitry Andric namespace {
128*bdd1243dSDimitry Andric 
129*bdd1243dSDimitry Andric /// Legacy analysis pass which computes a \ref MachineUniformityInfo.
130*bdd1243dSDimitry Andric class MachineUniformityAnalysisPass : public MachineFunctionPass {
131*bdd1243dSDimitry Andric   MachineUniformityInfo UI;
132*bdd1243dSDimitry Andric 
133*bdd1243dSDimitry Andric public:
134*bdd1243dSDimitry Andric   static char ID;
135*bdd1243dSDimitry Andric 
136*bdd1243dSDimitry Andric   MachineUniformityAnalysisPass();
137*bdd1243dSDimitry Andric 
138*bdd1243dSDimitry Andric   MachineUniformityInfo &getUniformityInfo() { return UI; }
139*bdd1243dSDimitry Andric   const MachineUniformityInfo &getUniformityInfo() const { return UI; }
140*bdd1243dSDimitry Andric 
141*bdd1243dSDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
142*bdd1243dSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
143*bdd1243dSDimitry Andric   void print(raw_ostream &OS, const Module *M = nullptr) const override;
144*bdd1243dSDimitry Andric 
145*bdd1243dSDimitry Andric   // TODO: verify analysis
146*bdd1243dSDimitry Andric };
147*bdd1243dSDimitry Andric 
148*bdd1243dSDimitry Andric class MachineUniformityInfoPrinterPass : public MachineFunctionPass {
149*bdd1243dSDimitry Andric public:
150*bdd1243dSDimitry Andric   static char ID;
151*bdd1243dSDimitry Andric 
152*bdd1243dSDimitry Andric   MachineUniformityInfoPrinterPass();
153*bdd1243dSDimitry Andric 
154*bdd1243dSDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
155*bdd1243dSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
156*bdd1243dSDimitry Andric };
157*bdd1243dSDimitry Andric 
158*bdd1243dSDimitry Andric } // namespace
159*bdd1243dSDimitry Andric 
160*bdd1243dSDimitry Andric char MachineUniformityAnalysisPass::ID = 0;
161*bdd1243dSDimitry Andric 
162*bdd1243dSDimitry Andric MachineUniformityAnalysisPass::MachineUniformityAnalysisPass()
163*bdd1243dSDimitry Andric     : MachineFunctionPass(ID) {
164*bdd1243dSDimitry Andric   initializeMachineUniformityAnalysisPassPass(*PassRegistry::getPassRegistry());
165*bdd1243dSDimitry Andric }
166*bdd1243dSDimitry Andric 
167*bdd1243dSDimitry Andric INITIALIZE_PASS_BEGIN(MachineUniformityAnalysisPass, "machine-uniformity",
168*bdd1243dSDimitry Andric                       "Machine Uniformity Info Analysis", true, true)
169*bdd1243dSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)
170*bdd1243dSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
171*bdd1243dSDimitry Andric INITIALIZE_PASS_END(MachineUniformityAnalysisPass, "machine-uniformity",
172*bdd1243dSDimitry Andric                     "Machine Uniformity Info Analysis", true, true)
173*bdd1243dSDimitry Andric 
174*bdd1243dSDimitry Andric void MachineUniformityAnalysisPass::getAnalysisUsage(AnalysisUsage &AU) const {
175*bdd1243dSDimitry Andric   AU.setPreservesAll();
176*bdd1243dSDimitry Andric   AU.addRequired<MachineCycleInfoWrapperPass>();
177*bdd1243dSDimitry Andric   AU.addRequired<MachineDominatorTree>();
178*bdd1243dSDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
179*bdd1243dSDimitry Andric }
180*bdd1243dSDimitry Andric 
181*bdd1243dSDimitry Andric bool MachineUniformityAnalysisPass::runOnMachineFunction(MachineFunction &MF) {
182*bdd1243dSDimitry Andric   auto &DomTree = getAnalysis<MachineDominatorTree>().getBase();
183*bdd1243dSDimitry Andric   auto &CI = getAnalysis<MachineCycleInfoWrapperPass>().getCycleInfo();
184*bdd1243dSDimitry Andric   UI = computeMachineUniformityInfo(MF, CI, DomTree);
185*bdd1243dSDimitry Andric   return false;
186*bdd1243dSDimitry Andric }
187*bdd1243dSDimitry Andric 
188*bdd1243dSDimitry Andric void MachineUniformityAnalysisPass::print(raw_ostream &OS,
189*bdd1243dSDimitry Andric                                           const Module *) const {
190*bdd1243dSDimitry Andric   OS << "MachineUniformityInfo for function: " << UI.getFunction().getName()
191*bdd1243dSDimitry Andric      << "\n";
192*bdd1243dSDimitry Andric   UI.print(OS);
193*bdd1243dSDimitry Andric }
194*bdd1243dSDimitry Andric 
195*bdd1243dSDimitry Andric char MachineUniformityInfoPrinterPass::ID = 0;
196*bdd1243dSDimitry Andric 
197*bdd1243dSDimitry Andric MachineUniformityInfoPrinterPass::MachineUniformityInfoPrinterPass()
198*bdd1243dSDimitry Andric     : MachineFunctionPass(ID) {
199*bdd1243dSDimitry Andric   initializeMachineUniformityInfoPrinterPassPass(
200*bdd1243dSDimitry Andric       *PassRegistry::getPassRegistry());
201*bdd1243dSDimitry Andric }
202*bdd1243dSDimitry Andric 
203*bdd1243dSDimitry Andric INITIALIZE_PASS_BEGIN(MachineUniformityInfoPrinterPass,
204*bdd1243dSDimitry Andric                       "print-machine-uniformity",
205*bdd1243dSDimitry Andric                       "Print Machine Uniformity Info Analysis", true, true)
206*bdd1243dSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineUniformityAnalysisPass)
207*bdd1243dSDimitry Andric INITIALIZE_PASS_END(MachineUniformityInfoPrinterPass,
208*bdd1243dSDimitry Andric                     "print-machine-uniformity",
209*bdd1243dSDimitry Andric                     "Print Machine Uniformity Info Analysis", true, true)
210*bdd1243dSDimitry Andric 
211*bdd1243dSDimitry Andric void MachineUniformityInfoPrinterPass::getAnalysisUsage(
212*bdd1243dSDimitry Andric     AnalysisUsage &AU) const {
213*bdd1243dSDimitry Andric   AU.setPreservesAll();
214*bdd1243dSDimitry Andric   AU.addRequired<MachineUniformityAnalysisPass>();
215*bdd1243dSDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
216*bdd1243dSDimitry Andric }
217*bdd1243dSDimitry Andric 
218*bdd1243dSDimitry Andric bool MachineUniformityInfoPrinterPass::runOnMachineFunction(
219*bdd1243dSDimitry Andric     MachineFunction &F) {
220*bdd1243dSDimitry Andric   auto &UI = getAnalysis<MachineUniformityAnalysisPass>();
221*bdd1243dSDimitry Andric   UI.print(errs());
222*bdd1243dSDimitry Andric   return false;
223*bdd1243dSDimitry Andric }
224