1bdd1243dSDimitry Andric //===- MachineUniformityAnalysis.cpp --------------------------------------===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric 9bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineUniformityAnalysis.h" 10bdd1243dSDimitry Andric #include "llvm/ADT/GenericUniformityImpl.h" 11bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineCycleAnalysis.h" 12bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 13bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 14bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineSSAContext.h" 15bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 16bdd1243dSDimitry Andric #include "llvm/InitializePasses.h" 17bdd1243dSDimitry Andric 18bdd1243dSDimitry Andric using namespace llvm; 19bdd1243dSDimitry Andric 20bdd1243dSDimitry Andric template <> 21bdd1243dSDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::hasDivergentDefs( 22bdd1243dSDimitry Andric const MachineInstr &I) const { 2306c3fb27SDimitry Andric for (auto &op : I.all_defs()) { 24bdd1243dSDimitry Andric if (isDivergent(op.getReg())) 25bdd1243dSDimitry Andric return true; 26bdd1243dSDimitry Andric } 27bdd1243dSDimitry Andric return false; 28bdd1243dSDimitry Andric } 29bdd1243dSDimitry Andric 30bdd1243dSDimitry Andric template <> 31bdd1243dSDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::markDefsDivergent( 3206c3fb27SDimitry Andric const MachineInstr &Instr) { 33bdd1243dSDimitry Andric bool insertedDivergent = false; 34bdd1243dSDimitry Andric const auto &MRI = F.getRegInfo(); 3506c3fb27SDimitry Andric const auto &RBI = *F.getSubtarget().getRegBankInfo(); 36bdd1243dSDimitry Andric const auto &TRI = *MRI.getTargetRegisterInfo(); 3706c3fb27SDimitry Andric for (auto &op : Instr.all_defs()) { 38bdd1243dSDimitry Andric if (!op.getReg().isVirtual()) 39bdd1243dSDimitry Andric continue; 40bdd1243dSDimitry Andric assert(!op.getSubReg()); 4106c3fb27SDimitry Andric if (TRI.isUniformReg(MRI, RBI, op.getReg())) 42bdd1243dSDimitry Andric continue; 43bdd1243dSDimitry Andric insertedDivergent |= markDivergent(op.getReg()); 44bdd1243dSDimitry Andric } 45bdd1243dSDimitry Andric return insertedDivergent; 46bdd1243dSDimitry Andric } 47bdd1243dSDimitry Andric 48bdd1243dSDimitry Andric template <> 49bdd1243dSDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() { 50bdd1243dSDimitry Andric const auto &InstrInfo = *F.getSubtarget().getInstrInfo(); 51bdd1243dSDimitry Andric 52bdd1243dSDimitry Andric for (const MachineBasicBlock &block : F) { 53bdd1243dSDimitry Andric for (const MachineInstr &instr : block) { 54bdd1243dSDimitry Andric auto uniformity = InstrInfo.getInstructionUniformity(instr); 55bdd1243dSDimitry Andric if (uniformity == InstructionUniformity::AlwaysUniform) { 56bdd1243dSDimitry Andric addUniformOverride(instr); 57bdd1243dSDimitry Andric continue; 58bdd1243dSDimitry Andric } 59bdd1243dSDimitry Andric 60bdd1243dSDimitry Andric if (uniformity == InstructionUniformity::NeverUniform) { 6106c3fb27SDimitry Andric markDivergent(instr); 62bdd1243dSDimitry Andric } 63bdd1243dSDimitry Andric } 64bdd1243dSDimitry Andric } 65bdd1243dSDimitry Andric } 66bdd1243dSDimitry Andric 67bdd1243dSDimitry Andric template <> 68bdd1243dSDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers( 69bdd1243dSDimitry Andric Register Reg) { 7006c3fb27SDimitry Andric assert(isDivergent(Reg)); 71bdd1243dSDimitry Andric const auto &RegInfo = F.getRegInfo(); 72bdd1243dSDimitry Andric for (MachineInstr &UserInstr : RegInfo.use_instructions(Reg)) { 7306c3fb27SDimitry Andric markDivergent(UserInstr); 74bdd1243dSDimitry Andric } 75bdd1243dSDimitry Andric } 76bdd1243dSDimitry Andric 77bdd1243dSDimitry Andric template <> 78bdd1243dSDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers( 79bdd1243dSDimitry Andric const MachineInstr &Instr) { 80bdd1243dSDimitry Andric assert(!isAlwaysUniform(Instr)); 81bdd1243dSDimitry Andric if (Instr.isTerminator()) 82bdd1243dSDimitry Andric return; 8306c3fb27SDimitry Andric for (const MachineOperand &op : Instr.all_defs()) { 8406c3fb27SDimitry Andric auto Reg = op.getReg(); 8506c3fb27SDimitry Andric if (isDivergent(Reg)) 8606c3fb27SDimitry Andric pushUsers(Reg); 87bdd1243dSDimitry Andric } 88bdd1243dSDimitry Andric } 89bdd1243dSDimitry Andric 90bdd1243dSDimitry Andric template <> 91bdd1243dSDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::usesValueFromCycle( 92bdd1243dSDimitry Andric const MachineInstr &I, const MachineCycle &DefCycle) const { 93bdd1243dSDimitry Andric assert(!isAlwaysUniform(I)); 94bdd1243dSDimitry Andric for (auto &Op : I.operands()) { 95bdd1243dSDimitry Andric if (!Op.isReg() || !Op.readsReg()) 96bdd1243dSDimitry Andric continue; 97bdd1243dSDimitry Andric auto Reg = Op.getReg(); 9806c3fb27SDimitry Andric 9906c3fb27SDimitry Andric // FIXME: Physical registers need to be properly checked instead of always 10006c3fb27SDimitry Andric // returning true 10106c3fb27SDimitry Andric if (Reg.isPhysical()) 10206c3fb27SDimitry Andric return true; 10306c3fb27SDimitry Andric 104bdd1243dSDimitry Andric auto *Def = F.getRegInfo().getVRegDef(Reg); 105bdd1243dSDimitry Andric if (DefCycle.contains(Def->getParent())) 106bdd1243dSDimitry Andric return true; 107bdd1243dSDimitry Andric } 108bdd1243dSDimitry Andric return false; 109bdd1243dSDimitry Andric } 110bdd1243dSDimitry Andric 11106c3fb27SDimitry Andric template <> 11206c3fb27SDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>:: 11306c3fb27SDimitry Andric propagateTemporalDivergence(const MachineInstr &I, 11406c3fb27SDimitry Andric const MachineCycle &DefCycle) { 11506c3fb27SDimitry Andric const auto &RegInfo = F.getRegInfo(); 11606c3fb27SDimitry Andric for (auto &Op : I.all_defs()) { 11706c3fb27SDimitry Andric if (!Op.getReg().isVirtual()) 11806c3fb27SDimitry Andric continue; 11906c3fb27SDimitry Andric auto Reg = Op.getReg(); 12006c3fb27SDimitry Andric if (isDivergent(Reg)) 12106c3fb27SDimitry Andric continue; 12206c3fb27SDimitry Andric for (MachineInstr &UserInstr : RegInfo.use_instructions(Reg)) { 12306c3fb27SDimitry Andric if (DefCycle.contains(UserInstr.getParent())) 12406c3fb27SDimitry Andric continue; 12506c3fb27SDimitry Andric markDivergent(UserInstr); 12606c3fb27SDimitry Andric } 12706c3fb27SDimitry Andric } 12806c3fb27SDimitry Andric } 12906c3fb27SDimitry Andric 13006c3fb27SDimitry Andric template <> 13106c3fb27SDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::isDivergentUse( 13206c3fb27SDimitry Andric const MachineOperand &U) const { 13306c3fb27SDimitry Andric if (!U.isReg()) 13406c3fb27SDimitry Andric return false; 13506c3fb27SDimitry Andric 13606c3fb27SDimitry Andric auto Reg = U.getReg(); 13706c3fb27SDimitry Andric if (isDivergent(Reg)) 13806c3fb27SDimitry Andric return true; 13906c3fb27SDimitry Andric 14006c3fb27SDimitry Andric const auto &RegInfo = F.getRegInfo(); 14106c3fb27SDimitry Andric auto *Def = RegInfo.getOneDef(Reg); 14206c3fb27SDimitry Andric if (!Def) 14306c3fb27SDimitry Andric return true; 14406c3fb27SDimitry Andric 14506c3fb27SDimitry Andric auto *DefInstr = Def->getParent(); 14606c3fb27SDimitry Andric auto *UseInstr = U.getParent(); 14706c3fb27SDimitry Andric return isTemporalDivergent(*UseInstr->getParent(), *DefInstr); 14806c3fb27SDimitry Andric } 14906c3fb27SDimitry Andric 150bdd1243dSDimitry Andric // This ensures explicit instantiation of 151bdd1243dSDimitry Andric // GenericUniformityAnalysisImpl::ImplDeleter::operator() 152bdd1243dSDimitry Andric template class llvm::GenericUniformityInfo<MachineSSAContext>; 153bdd1243dSDimitry Andric template struct llvm::GenericUniformityAnalysisImplDeleter< 154bdd1243dSDimitry Andric llvm::GenericUniformityAnalysisImpl<MachineSSAContext>>; 155bdd1243dSDimitry Andric 15606c3fb27SDimitry Andric MachineUniformityInfo llvm::computeMachineUniformityInfo( 15706c3fb27SDimitry Andric MachineFunction &F, const MachineCycleInfo &cycleInfo, 15806c3fb27SDimitry Andric const MachineDomTree &domTree, bool HasBranchDivergence) { 159bdd1243dSDimitry Andric assert(F.getRegInfo().isSSA() && "Expected to be run on SSA form!"); 160*5f757f3fSDimitry Andric MachineUniformityInfo UI(domTree, cycleInfo); 16106c3fb27SDimitry Andric if (HasBranchDivergence) 16206c3fb27SDimitry Andric UI.compute(); 16306c3fb27SDimitry Andric return UI; 164bdd1243dSDimitry Andric } 165bdd1243dSDimitry Andric 166bdd1243dSDimitry Andric namespace { 167bdd1243dSDimitry Andric 168bdd1243dSDimitry Andric /// Legacy analysis pass which computes a \ref MachineUniformityInfo. 169bdd1243dSDimitry Andric class MachineUniformityAnalysisPass : public MachineFunctionPass { 170bdd1243dSDimitry Andric MachineUniformityInfo UI; 171bdd1243dSDimitry Andric 172bdd1243dSDimitry Andric public: 173bdd1243dSDimitry Andric static char ID; 174bdd1243dSDimitry Andric 175bdd1243dSDimitry Andric MachineUniformityAnalysisPass(); 176bdd1243dSDimitry Andric 177bdd1243dSDimitry Andric MachineUniformityInfo &getUniformityInfo() { return UI; } 178bdd1243dSDimitry Andric const MachineUniformityInfo &getUniformityInfo() const { return UI; } 179bdd1243dSDimitry Andric 180bdd1243dSDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 181bdd1243dSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 182bdd1243dSDimitry Andric void print(raw_ostream &OS, const Module *M = nullptr) const override; 183bdd1243dSDimitry Andric 184bdd1243dSDimitry Andric // TODO: verify analysis 185bdd1243dSDimitry Andric }; 186bdd1243dSDimitry Andric 187bdd1243dSDimitry Andric class MachineUniformityInfoPrinterPass : public MachineFunctionPass { 188bdd1243dSDimitry Andric public: 189bdd1243dSDimitry Andric static char ID; 190bdd1243dSDimitry Andric 191bdd1243dSDimitry Andric MachineUniformityInfoPrinterPass(); 192bdd1243dSDimitry Andric 193bdd1243dSDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 194bdd1243dSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 195bdd1243dSDimitry Andric }; 196bdd1243dSDimitry Andric 197bdd1243dSDimitry Andric } // namespace 198bdd1243dSDimitry Andric 199bdd1243dSDimitry Andric char MachineUniformityAnalysisPass::ID = 0; 200bdd1243dSDimitry Andric 201bdd1243dSDimitry Andric MachineUniformityAnalysisPass::MachineUniformityAnalysisPass() 202bdd1243dSDimitry Andric : MachineFunctionPass(ID) { 203bdd1243dSDimitry Andric initializeMachineUniformityAnalysisPassPass(*PassRegistry::getPassRegistry()); 204bdd1243dSDimitry Andric } 205bdd1243dSDimitry Andric 206bdd1243dSDimitry Andric INITIALIZE_PASS_BEGIN(MachineUniformityAnalysisPass, "machine-uniformity", 207bdd1243dSDimitry Andric "Machine Uniformity Info Analysis", true, true) 208bdd1243dSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass) 209bdd1243dSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) 210bdd1243dSDimitry Andric INITIALIZE_PASS_END(MachineUniformityAnalysisPass, "machine-uniformity", 211bdd1243dSDimitry Andric "Machine Uniformity Info Analysis", true, true) 212bdd1243dSDimitry Andric 213bdd1243dSDimitry Andric void MachineUniformityAnalysisPass::getAnalysisUsage(AnalysisUsage &AU) const { 214bdd1243dSDimitry Andric AU.setPreservesAll(); 215bdd1243dSDimitry Andric AU.addRequired<MachineCycleInfoWrapperPass>(); 216bdd1243dSDimitry Andric AU.addRequired<MachineDominatorTree>(); 217bdd1243dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 218bdd1243dSDimitry Andric } 219bdd1243dSDimitry Andric 220bdd1243dSDimitry Andric bool MachineUniformityAnalysisPass::runOnMachineFunction(MachineFunction &MF) { 221bdd1243dSDimitry Andric auto &DomTree = getAnalysis<MachineDominatorTree>().getBase(); 222bdd1243dSDimitry Andric auto &CI = getAnalysis<MachineCycleInfoWrapperPass>().getCycleInfo(); 22306c3fb27SDimitry Andric // FIXME: Query TTI::hasBranchDivergence. -run-pass seems to end up with a 22406c3fb27SDimitry Andric // default NoTTI 22506c3fb27SDimitry Andric UI = computeMachineUniformityInfo(MF, CI, DomTree, true); 226bdd1243dSDimitry Andric return false; 227bdd1243dSDimitry Andric } 228bdd1243dSDimitry Andric 229bdd1243dSDimitry Andric void MachineUniformityAnalysisPass::print(raw_ostream &OS, 230bdd1243dSDimitry Andric const Module *) const { 231bdd1243dSDimitry Andric OS << "MachineUniformityInfo for function: " << UI.getFunction().getName() 232bdd1243dSDimitry Andric << "\n"; 233bdd1243dSDimitry Andric UI.print(OS); 234bdd1243dSDimitry Andric } 235bdd1243dSDimitry Andric 236bdd1243dSDimitry Andric char MachineUniformityInfoPrinterPass::ID = 0; 237bdd1243dSDimitry Andric 238bdd1243dSDimitry Andric MachineUniformityInfoPrinterPass::MachineUniformityInfoPrinterPass() 239bdd1243dSDimitry Andric : MachineFunctionPass(ID) { 240bdd1243dSDimitry Andric initializeMachineUniformityInfoPrinterPassPass( 241bdd1243dSDimitry Andric *PassRegistry::getPassRegistry()); 242bdd1243dSDimitry Andric } 243bdd1243dSDimitry Andric 244bdd1243dSDimitry Andric INITIALIZE_PASS_BEGIN(MachineUniformityInfoPrinterPass, 245bdd1243dSDimitry Andric "print-machine-uniformity", 246bdd1243dSDimitry Andric "Print Machine Uniformity Info Analysis", true, true) 247bdd1243dSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineUniformityAnalysisPass) 248bdd1243dSDimitry Andric INITIALIZE_PASS_END(MachineUniformityInfoPrinterPass, 249bdd1243dSDimitry Andric "print-machine-uniformity", 250bdd1243dSDimitry Andric "Print Machine Uniformity Info Analysis", true, true) 251bdd1243dSDimitry Andric 252bdd1243dSDimitry Andric void MachineUniformityInfoPrinterPass::getAnalysisUsage( 253bdd1243dSDimitry Andric AnalysisUsage &AU) const { 254bdd1243dSDimitry Andric AU.setPreservesAll(); 255bdd1243dSDimitry Andric AU.addRequired<MachineUniformityAnalysisPass>(); 256bdd1243dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 257bdd1243dSDimitry Andric } 258bdd1243dSDimitry Andric 259bdd1243dSDimitry Andric bool MachineUniformityInfoPrinterPass::runOnMachineFunction( 260bdd1243dSDimitry Andric MachineFunction &F) { 261bdd1243dSDimitry Andric auto &UI = getAnalysis<MachineUniformityAnalysisPass>(); 262bdd1243dSDimitry Andric UI.print(errs()); 263bdd1243dSDimitry Andric return false; 264bdd1243dSDimitry Andric } 265