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