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