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