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