brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.8 KiB · e4b82ce Raw
274 lines · cpp
1//===- MachineUniformityAnalysis.cpp --------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/CodeGen/MachineUniformityAnalysis.h"10#include "llvm/ADT/GenericUniformityImpl.h"11#include "llvm/Analysis/TargetTransformInfo.h"12#include "llvm/CodeGen/MachineCycleAnalysis.h"13#include "llvm/CodeGen/MachineDominators.h"14#include "llvm/CodeGen/MachineRegisterInfo.h"15#include "llvm/CodeGen/MachineSSAContext.h"16#include "llvm/CodeGen/TargetInstrInfo.h"17#include "llvm/InitializePasses.h"18 19using namespace llvm;20 21template <>22bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::hasDivergentDefs(23    const MachineInstr &I) const {24  for (auto &op : I.all_defs()) {25    if (isDivergent(op.getReg()))26      return true;27  }28  return false;29}30 31template <>32bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::markDefsDivergent(33    const MachineInstr &Instr) {34  bool insertedDivergent = false;35  const auto &MRI = F.getRegInfo();36  const auto &RBI = *F.getSubtarget().getRegBankInfo();37  const auto &TRI = *MRI.getTargetRegisterInfo();38  for (auto &op : Instr.all_defs()) {39    if (!op.getReg().isVirtual())40      continue;41    assert(!op.getSubReg());42    if (TRI.isUniformReg(MRI, RBI, op.getReg()))43      continue;44    insertedDivergent |= markDivergent(op.getReg());45  }46  return insertedDivergent;47}48 49template <>50void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {51  const auto &InstrInfo = *F.getSubtarget().getInstrInfo();52 53  for (const MachineBasicBlock &block : F) {54    for (const MachineInstr &instr : block) {55      auto uniformity = InstrInfo.getInstructionUniformity(instr);56      if (uniformity == InstructionUniformity::AlwaysUniform) {57        addUniformOverride(instr);58        continue;59      }60 61      if (uniformity == InstructionUniformity::NeverUniform) {62        markDivergent(instr);63      }64    }65  }66}67 68template <>69void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(70    Register Reg) {71  assert(isDivergent(Reg));72  const auto &RegInfo = F.getRegInfo();73  for (MachineInstr &UserInstr : RegInfo.use_instructions(Reg)) {74    markDivergent(UserInstr);75  }76}77 78template <>79void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(80    const MachineInstr &Instr) {81  assert(!isAlwaysUniform(Instr));82  if (Instr.isTerminator())83    return;84  for (const MachineOperand &op : Instr.all_defs()) {85    auto Reg = op.getReg();86    if (isDivergent(Reg))87      pushUsers(Reg);88  }89}90 91template <>92bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::usesValueFromCycle(93    const MachineInstr &I, const MachineCycle &DefCycle) const {94  assert(!isAlwaysUniform(I));95  for (auto &Op : I.operands()) {96    if (!Op.isReg() || !Op.readsReg())97      continue;98    auto Reg = Op.getReg();99 100    // FIXME: Physical registers need to be properly checked instead of always101    // returning true102    if (Reg.isPhysical())103      return true;104 105    auto *Def = F.getRegInfo().getVRegDef(Reg);106    if (DefCycle.contains(Def->getParent()))107      return true;108  }109  return false;110}111 112template <>113void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::114    propagateTemporalDivergence(const MachineInstr &I,115                                const MachineCycle &DefCycle) {116  const auto &RegInfo = F.getRegInfo();117  for (auto &Op : I.all_defs()) {118    if (!Op.getReg().isVirtual())119      continue;120    auto Reg = Op.getReg();121    for (MachineInstr &UserInstr : RegInfo.use_instructions(Reg)) {122      if (DefCycle.contains(UserInstr.getParent()))123        continue;124      markDivergent(UserInstr);125 126      recordTemporalDivergence(Reg, &UserInstr, &DefCycle);127    }128  }129}130 131template <>132bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::isDivergentUse(133    const MachineOperand &U) const {134  if (!U.isReg())135    return false;136 137  auto Reg = U.getReg();138  if (isDivergent(Reg))139    return true;140 141  const auto &RegInfo = F.getRegInfo();142  auto *Def = RegInfo.getOneDef(Reg);143  if (!Def)144    return true;145 146  auto *DefInstr = Def->getParent();147  auto *UseInstr = U.getParent();148  return isTemporalDivergent(*UseInstr->getParent(), *DefInstr);149}150 151// This ensures explicit instantiation of152// GenericUniformityAnalysisImpl::ImplDeleter::operator()153template class llvm::GenericUniformityInfo<MachineSSAContext>;154template struct llvm::GenericUniformityAnalysisImplDeleter<155    llvm::GenericUniformityAnalysisImpl<MachineSSAContext>>;156 157MachineUniformityInfo llvm::computeMachineUniformityInfo(158    MachineFunction &F, const MachineCycleInfo &cycleInfo,159    const MachineDominatorTree &domTree, bool HasBranchDivergence) {160  assert(F.getRegInfo().isSSA() && "Expected to be run on SSA form!");161  MachineUniformityInfo UI(domTree, cycleInfo);162  if (HasBranchDivergence)163    UI.compute();164  return UI;165}166 167namespace {168 169class MachineUniformityInfoPrinterPass : public MachineFunctionPass {170public:171  static char ID;172 173  MachineUniformityInfoPrinterPass();174 175  bool runOnMachineFunction(MachineFunction &F) override;176  void getAnalysisUsage(AnalysisUsage &AU) const override;177};178 179} // namespace180 181AnalysisKey MachineUniformityAnalysis::Key;182 183MachineUniformityAnalysis::Result184MachineUniformityAnalysis::run(MachineFunction &MF,185                               MachineFunctionAnalysisManager &MFAM) {186  auto &DomTree = MFAM.getResult<MachineDominatorTreeAnalysis>(MF);187  auto &CI = MFAM.getResult<MachineCycleAnalysis>(MF);188  auto &FAM = MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF)189                  .getManager();190  auto &F = MF.getFunction();191  auto &TTI = FAM.getResult<TargetIRAnalysis>(F);192  return computeMachineUniformityInfo(MF, CI, DomTree,193                                      TTI.hasBranchDivergence(&F));194}195 196PreservedAnalyses197MachineUniformityPrinterPass::run(MachineFunction &MF,198                                  MachineFunctionAnalysisManager &MFAM) {199  auto &MUI = MFAM.getResult<MachineUniformityAnalysis>(MF);200  OS << "MachineUniformityInfo for function: ";201  MF.getFunction().printAsOperand(OS, /*PrintType=*/false);202  OS << '\n';203  MUI.print(OS);204  return PreservedAnalyses::all();205}206 207char MachineUniformityAnalysisPass::ID = 0;208 209MachineUniformityAnalysisPass::MachineUniformityAnalysisPass()210    : MachineFunctionPass(ID) {211  initializeMachineUniformityAnalysisPassPass(*PassRegistry::getPassRegistry());212}213 214INITIALIZE_PASS_BEGIN(MachineUniformityAnalysisPass, "machine-uniformity",215                      "Machine Uniformity Info Analysis", false, true)216INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)217INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)218INITIALIZE_PASS_END(MachineUniformityAnalysisPass, "machine-uniformity",219                    "Machine Uniformity Info Analysis", false, true)220 221void MachineUniformityAnalysisPass::getAnalysisUsage(AnalysisUsage &AU) const {222  AU.setPreservesAll();223  AU.addRequiredTransitive<MachineCycleInfoWrapperPass>();224  AU.addRequired<MachineDominatorTreeWrapperPass>();225  MachineFunctionPass::getAnalysisUsage(AU);226}227 228bool MachineUniformityAnalysisPass::runOnMachineFunction(MachineFunction &MF) {229  auto &DomTree = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();230  auto &CI = getAnalysis<MachineCycleInfoWrapperPass>().getCycleInfo();231  // FIXME: Query TTI::hasBranchDivergence. -run-pass seems to end up with a232  // default NoTTI233  UI = computeMachineUniformityInfo(MF, CI, DomTree, true);234  return false;235}236 237void MachineUniformityAnalysisPass::print(raw_ostream &OS,238                                          const Module *) const {239  OS << "MachineUniformityInfo for function: ";240  UI.getFunction().getFunction().printAsOperand(OS, /*PrintType=*/false);241  OS << '\n';242  UI.print(OS);243}244 245char MachineUniformityInfoPrinterPass::ID = 0;246 247MachineUniformityInfoPrinterPass::MachineUniformityInfoPrinterPass()248    : MachineFunctionPass(ID) {249  initializeMachineUniformityInfoPrinterPassPass(250      *PassRegistry::getPassRegistry());251}252 253INITIALIZE_PASS_BEGIN(MachineUniformityInfoPrinterPass,254                      "print-machine-uniformity",255                      "Print Machine Uniformity Info Analysis", true, true)256INITIALIZE_PASS_DEPENDENCY(MachineUniformityAnalysisPass)257INITIALIZE_PASS_END(MachineUniformityInfoPrinterPass,258                    "print-machine-uniformity",259                    "Print Machine Uniformity Info Analysis", true, true)260 261void MachineUniformityInfoPrinterPass::getAnalysisUsage(262    AnalysisUsage &AU) const {263  AU.setPreservesAll();264  AU.addRequired<MachineUniformityAnalysisPass>();265  MachineFunctionPass::getAnalysisUsage(AU);266}267 268bool MachineUniformityInfoPrinterPass::runOnMachineFunction(269    MachineFunction &F) {270  auto &UI = getAnalysis<MachineUniformityAnalysisPass>();271  UI.print(errs());272  return false;273}274