Home | History | Annotate | Line # | Download | only in AMDGPU
      1 //===-- R600ClauseMergePass - Merge consecutive CF_ALU -------------------===//
      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-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 /// \file
     10 /// R600EmitClauseMarker pass emits CFAlu instruction in a conservative maneer.
     11 /// This pass is merging consecutive CFAlus where applicable.
     12 /// It needs to be called after IfCvt for best results.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "AMDGPU.h"
     16 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
     17 #include "R600Subtarget.h"
     18 
     19 using namespace llvm;
     20 
     21 #define DEBUG_TYPE "r600mergeclause"
     22 
     23 namespace {
     24 
     25 static bool isCFAlu(const MachineInstr &MI) {
     26   switch (MI.getOpcode()) {
     27   case R600::CF_ALU:
     28   case R600::CF_ALU_PUSH_BEFORE:
     29     return true;
     30   default:
     31     return false;
     32   }
     33 }
     34 
     35 class R600ClauseMergePass : public MachineFunctionPass {
     36 
     37 private:
     38   const R600InstrInfo *TII;
     39 
     40   unsigned getCFAluSize(const MachineInstr &MI) const;
     41   bool isCFAluEnabled(const MachineInstr &MI) const;
     42 
     43   /// IfCvt pass can generate "disabled" ALU clause marker that need to be
     44   /// removed and their content affected to the previous alu clause.
     45   /// This function parse instructions after CFAlu until it find a disabled
     46   /// CFAlu and merge the content, or an enabled CFAlu.
     47   void cleanPotentialDisabledCFAlu(MachineInstr &CFAlu) const;
     48 
     49   /// Check whether LatrCFAlu can be merged into RootCFAlu and do it if
     50   /// it is the case.
     51   bool mergeIfPossible(MachineInstr &RootCFAlu,
     52                        const MachineInstr &LatrCFAlu) const;
     53 
     54 public:
     55   static char ID;
     56 
     57   R600ClauseMergePass() : MachineFunctionPass(ID) { }
     58 
     59   bool runOnMachineFunction(MachineFunction &MF) override;
     60 
     61   StringRef getPassName() const override;
     62 };
     63 
     64 } // end anonymous namespace
     65 
     66 INITIALIZE_PASS_BEGIN(R600ClauseMergePass, DEBUG_TYPE,
     67                       "R600 Clause Merge", false, false)
     68 INITIALIZE_PASS_END(R600ClauseMergePass, DEBUG_TYPE,
     69                     "R600 Clause Merge", false, false)
     70 
     71 char R600ClauseMergePass::ID = 0;
     72 
     73 char &llvm::R600ClauseMergePassID = R600ClauseMergePass::ID;
     74 
     75 unsigned R600ClauseMergePass::getCFAluSize(const MachineInstr &MI) const {
     76   assert(isCFAlu(MI));
     77   return MI
     78       .getOperand(TII->getOperandIdx(MI.getOpcode(), R600::OpName::COUNT))
     79       .getImm();
     80 }
     81 
     82 bool R600ClauseMergePass::isCFAluEnabled(const MachineInstr &MI) const {
     83   assert(isCFAlu(MI));
     84   return MI
     85       .getOperand(TII->getOperandIdx(MI.getOpcode(), R600::OpName::Enabled))
     86       .getImm();
     87 }
     88 
     89 void R600ClauseMergePass::cleanPotentialDisabledCFAlu(
     90     MachineInstr &CFAlu) const {
     91   int CntIdx = TII->getOperandIdx(R600::CF_ALU, R600::OpName::COUNT);
     92   MachineBasicBlock::iterator I = CFAlu, E = CFAlu.getParent()->end();
     93   I++;
     94   do {
     95     while (I != E && !isCFAlu(*I))
     96       I++;
     97     if (I == E)
     98       return;
     99     MachineInstr &MI = *I++;
    100     if (isCFAluEnabled(MI))
    101       break;
    102     CFAlu.getOperand(CntIdx).setImm(getCFAluSize(CFAlu) + getCFAluSize(MI));
    103     MI.eraseFromParent();
    104   } while (I != E);
    105 }
    106 
    107 bool R600ClauseMergePass::mergeIfPossible(MachineInstr &RootCFAlu,
    108                                           const MachineInstr &LatrCFAlu) const {
    109   assert(isCFAlu(RootCFAlu) && isCFAlu(LatrCFAlu));
    110   int CntIdx = TII->getOperandIdx(R600::CF_ALU, R600::OpName::COUNT);
    111   unsigned RootInstCount = getCFAluSize(RootCFAlu),
    112       LaterInstCount = getCFAluSize(LatrCFAlu);
    113   unsigned CumuledInsts = RootInstCount + LaterInstCount;
    114   if (CumuledInsts >= TII->getMaxAlusPerClause()) {
    115     LLVM_DEBUG(dbgs() << "Excess inst counts\n");
    116     return false;
    117   }
    118   if (RootCFAlu.getOpcode() == R600::CF_ALU_PUSH_BEFORE)
    119     return false;
    120   // Is KCache Bank 0 compatible ?
    121   int Mode0Idx =
    122       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_MODE0);
    123   int KBank0Idx =
    124       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_BANK0);
    125   int KBank0LineIdx =
    126       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_ADDR0);
    127   if (LatrCFAlu.getOperand(Mode0Idx).getImm() &&
    128       RootCFAlu.getOperand(Mode0Idx).getImm() &&
    129       (LatrCFAlu.getOperand(KBank0Idx).getImm() !=
    130            RootCFAlu.getOperand(KBank0Idx).getImm() ||
    131        LatrCFAlu.getOperand(KBank0LineIdx).getImm() !=
    132            RootCFAlu.getOperand(KBank0LineIdx).getImm())) {
    133     LLVM_DEBUG(dbgs() << "Wrong KC0\n");
    134     return false;
    135   }
    136   // Is KCache Bank 1 compatible ?
    137   int Mode1Idx =
    138       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_MODE1);
    139   int KBank1Idx =
    140       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_BANK1);
    141   int KBank1LineIdx =
    142       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_ADDR1);
    143   if (LatrCFAlu.getOperand(Mode1Idx).getImm() &&
    144       RootCFAlu.getOperand(Mode1Idx).getImm() &&
    145       (LatrCFAlu.getOperand(KBank1Idx).getImm() !=
    146            RootCFAlu.getOperand(KBank1Idx).getImm() ||
    147        LatrCFAlu.getOperand(KBank1LineIdx).getImm() !=
    148            RootCFAlu.getOperand(KBank1LineIdx).getImm())) {
    149     LLVM_DEBUG(dbgs() << "Wrong KC0\n");
    150     return false;
    151   }
    152   if (LatrCFAlu.getOperand(Mode0Idx).getImm()) {
    153     RootCFAlu.getOperand(Mode0Idx).setImm(
    154         LatrCFAlu.getOperand(Mode0Idx).getImm());
    155     RootCFAlu.getOperand(KBank0Idx).setImm(
    156         LatrCFAlu.getOperand(KBank0Idx).getImm());
    157     RootCFAlu.getOperand(KBank0LineIdx)
    158         .setImm(LatrCFAlu.getOperand(KBank0LineIdx).getImm());
    159   }
    160   if (LatrCFAlu.getOperand(Mode1Idx).getImm()) {
    161     RootCFAlu.getOperand(Mode1Idx).setImm(
    162         LatrCFAlu.getOperand(Mode1Idx).getImm());
    163     RootCFAlu.getOperand(KBank1Idx).setImm(
    164         LatrCFAlu.getOperand(KBank1Idx).getImm());
    165     RootCFAlu.getOperand(KBank1LineIdx)
    166         .setImm(LatrCFAlu.getOperand(KBank1LineIdx).getImm());
    167   }
    168   RootCFAlu.getOperand(CntIdx).setImm(CumuledInsts);
    169   RootCFAlu.setDesc(TII->get(LatrCFAlu.getOpcode()));
    170   return true;
    171 }
    172 
    173 bool R600ClauseMergePass::runOnMachineFunction(MachineFunction &MF) {
    174   if (skipFunction(MF.getFunction()))
    175     return false;
    176 
    177   const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
    178   TII = ST.getInstrInfo();
    179 
    180   for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
    181                                                   BB != BB_E; ++BB) {
    182     MachineBasicBlock &MBB = *BB;
    183     MachineBasicBlock::iterator I = MBB.begin(),  E = MBB.end();
    184     MachineBasicBlock::iterator LatestCFAlu = E;
    185     while (I != E) {
    186       MachineInstr &MI = *I++;
    187       if ((!TII->canBeConsideredALU(MI) && !isCFAlu(MI)) ||
    188           TII->mustBeLastInClause(MI.getOpcode()))
    189         LatestCFAlu = E;
    190       if (!isCFAlu(MI))
    191         continue;
    192       cleanPotentialDisabledCFAlu(MI);
    193 
    194       if (LatestCFAlu != E && mergeIfPossible(*LatestCFAlu, MI)) {
    195         MI.eraseFromParent();
    196       } else {
    197         assert(MI.getOperand(8).getImm() && "CF ALU instruction disabled");
    198         LatestCFAlu = MI;
    199       }
    200     }
    201   }
    202   return false;
    203 }
    204 
    205 StringRef R600ClauseMergePass::getPassName() const {
    206   return "R600 Merge Clause Markers Pass";
    207 }
    208 
    209 llvm::FunctionPass *llvm::createR600ClauseMergePass() {
    210   return new R600ClauseMergePass();
    211 }
    212