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