145bb48eaSTom Stellard //===-- R600ClauseMergePass - Merge consecutive CF_ALU -------------------===// 245bb48eaSTom Stellard // 345bb48eaSTom Stellard // The LLVM Compiler Infrastructure 445bb48eaSTom Stellard // 545bb48eaSTom Stellard // This file is distributed under the University of Illinois Open Source 645bb48eaSTom Stellard // License. See LICENSE.TXT for details. 745bb48eaSTom Stellard // 845bb48eaSTom Stellard //===----------------------------------------------------------------------===// 945bb48eaSTom Stellard // 1045bb48eaSTom Stellard /// \file 1145bb48eaSTom Stellard /// R600EmitClauseMarker pass emits CFAlu instruction in a conservative maneer. 1245bb48eaSTom Stellard /// This pass is merging consecutive CFAlus where applicable. 1345bb48eaSTom Stellard /// It needs to be called after IfCvt for best results. 1445bb48eaSTom Stellard //===----------------------------------------------------------------------===// 1545bb48eaSTom Stellard 1645bb48eaSTom Stellard #include "AMDGPU.h" 1745bb48eaSTom Stellard #include "AMDGPUSubtarget.h" 1845bb48eaSTom Stellard #include "R600Defines.h" 1945bb48eaSTom Stellard #include "R600InstrInfo.h" 2045bb48eaSTom Stellard #include "R600MachineFunctionInfo.h" 2145bb48eaSTom Stellard #include "R600RegisterInfo.h" 2245bb48eaSTom Stellard #include "llvm/CodeGen/MachineFunctionPass.h" 2345bb48eaSTom Stellard #include "llvm/CodeGen/MachineInstrBuilder.h" 2445bb48eaSTom Stellard #include "llvm/CodeGen/MachineRegisterInfo.h" 2545bb48eaSTom Stellard #include "llvm/Support/Debug.h" 2645bb48eaSTom Stellard #include "llvm/Support/raw_ostream.h" 2745bb48eaSTom Stellard 2845bb48eaSTom Stellard using namespace llvm; 2945bb48eaSTom Stellard 3045bb48eaSTom Stellard #define DEBUG_TYPE "r600mergeclause" 3145bb48eaSTom Stellard 3245bb48eaSTom Stellard namespace { 3345bb48eaSTom Stellard 3445bb48eaSTom Stellard static bool isCFAlu(const MachineInstr *MI) { 3545bb48eaSTom Stellard switch (MI->getOpcode()) { 3645bb48eaSTom Stellard case AMDGPU::CF_ALU: 3745bb48eaSTom Stellard case AMDGPU::CF_ALU_PUSH_BEFORE: 3845bb48eaSTom Stellard return true; 3945bb48eaSTom Stellard default: 4045bb48eaSTom Stellard return false; 4145bb48eaSTom Stellard } 4245bb48eaSTom Stellard } 4345bb48eaSTom Stellard 4445bb48eaSTom Stellard class R600ClauseMergePass : public MachineFunctionPass { 4545bb48eaSTom Stellard 4645bb48eaSTom Stellard private: 4745bb48eaSTom Stellard static char ID; 4845bb48eaSTom Stellard const R600InstrInfo *TII; 4945bb48eaSTom Stellard 5045bb48eaSTom Stellard unsigned getCFAluSize(const MachineInstr *MI) const; 5145bb48eaSTom Stellard bool isCFAluEnabled(const MachineInstr *MI) const; 5245bb48eaSTom Stellard 5345bb48eaSTom Stellard /// IfCvt pass can generate "disabled" ALU clause marker that need to be 5445bb48eaSTom Stellard /// removed and their content affected to the previous alu clause. 5545bb48eaSTom Stellard /// This function parse instructions after CFAlu until it find a disabled 5645bb48eaSTom Stellard /// CFAlu and merge the content, or an enabled CFAlu. 5745bb48eaSTom Stellard void cleanPotentialDisabledCFAlu(MachineInstr *CFAlu) const; 5845bb48eaSTom Stellard 5945bb48eaSTom Stellard /// Check whether LatrCFAlu can be merged into RootCFAlu and do it if 6045bb48eaSTom Stellard /// it is the case. 6145bb48eaSTom Stellard bool mergeIfPossible(MachineInstr *RootCFAlu, const MachineInstr *LatrCFAlu) 6245bb48eaSTom Stellard const; 6345bb48eaSTom Stellard 6445bb48eaSTom Stellard public: 6545bb48eaSTom Stellard R600ClauseMergePass(TargetMachine &tm) : MachineFunctionPass(ID) { } 6645bb48eaSTom Stellard 6745bb48eaSTom Stellard bool runOnMachineFunction(MachineFunction &MF) override; 6845bb48eaSTom Stellard 6945bb48eaSTom Stellard const char *getPassName() const override; 7045bb48eaSTom Stellard }; 7145bb48eaSTom Stellard 7245bb48eaSTom Stellard char R600ClauseMergePass::ID = 0; 7345bb48eaSTom Stellard 7445bb48eaSTom Stellard unsigned R600ClauseMergePass::getCFAluSize(const MachineInstr *MI) const { 7545bb48eaSTom Stellard assert(isCFAlu(MI)); 7645bb48eaSTom Stellard return MI->getOperand( 7745bb48eaSTom Stellard TII->getOperandIdx(MI->getOpcode(), AMDGPU::OpName::COUNT)).getImm(); 7845bb48eaSTom Stellard } 7945bb48eaSTom Stellard 8045bb48eaSTom Stellard bool R600ClauseMergePass::isCFAluEnabled(const MachineInstr *MI) const { 8145bb48eaSTom Stellard assert(isCFAlu(MI)); 8245bb48eaSTom Stellard return MI->getOperand( 8345bb48eaSTom Stellard TII->getOperandIdx(MI->getOpcode(), AMDGPU::OpName::Enabled)).getImm(); 8445bb48eaSTom Stellard } 8545bb48eaSTom Stellard 8645bb48eaSTom Stellard void R600ClauseMergePass::cleanPotentialDisabledCFAlu(MachineInstr *CFAlu) 8745bb48eaSTom Stellard const { 8845bb48eaSTom Stellard int CntIdx = TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::COUNT); 8945bb48eaSTom Stellard MachineBasicBlock::iterator I = CFAlu, E = CFAlu->getParent()->end(); 9045bb48eaSTom Stellard I++; 9145bb48eaSTom Stellard do { 9245bb48eaSTom Stellard while (I!= E && !isCFAlu(I)) 9345bb48eaSTom Stellard I++; 9445bb48eaSTom Stellard if (I == E) 9545bb48eaSTom Stellard return; 9645bb48eaSTom Stellard MachineInstr *MI = I++; 9745bb48eaSTom Stellard if (isCFAluEnabled(MI)) 9845bb48eaSTom Stellard break; 9945bb48eaSTom Stellard CFAlu->getOperand(CntIdx).setImm(getCFAluSize(CFAlu) + getCFAluSize(MI)); 10045bb48eaSTom Stellard MI->eraseFromParent(); 10145bb48eaSTom Stellard } while (I != E); 10245bb48eaSTom Stellard } 10345bb48eaSTom Stellard 10445bb48eaSTom Stellard bool R600ClauseMergePass::mergeIfPossible(MachineInstr *RootCFAlu, 10545bb48eaSTom Stellard const MachineInstr *LatrCFAlu) const { 10645bb48eaSTom Stellard assert(isCFAlu(RootCFAlu) && isCFAlu(LatrCFAlu)); 10745bb48eaSTom Stellard int CntIdx = TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::COUNT); 10845bb48eaSTom Stellard unsigned RootInstCount = getCFAluSize(RootCFAlu), 10945bb48eaSTom Stellard LaterInstCount = getCFAluSize(LatrCFAlu); 11045bb48eaSTom Stellard unsigned CumuledInsts = RootInstCount + LaterInstCount; 11145bb48eaSTom Stellard if (CumuledInsts >= TII->getMaxAlusPerClause()) { 11245bb48eaSTom Stellard DEBUG(dbgs() << "Excess inst counts\n"); 11345bb48eaSTom Stellard return false; 11445bb48eaSTom Stellard } 11545bb48eaSTom Stellard if (RootCFAlu->getOpcode() == AMDGPU::CF_ALU_PUSH_BEFORE) 11645bb48eaSTom Stellard return false; 11745bb48eaSTom Stellard // Is KCache Bank 0 compatible ? 11845bb48eaSTom Stellard int Mode0Idx = 11945bb48eaSTom Stellard TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_MODE0); 12045bb48eaSTom Stellard int KBank0Idx = 12145bb48eaSTom Stellard TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_BANK0); 12245bb48eaSTom Stellard int KBank0LineIdx = 12345bb48eaSTom Stellard TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_ADDR0); 12445bb48eaSTom Stellard if (LatrCFAlu->getOperand(Mode0Idx).getImm() && 12545bb48eaSTom Stellard RootCFAlu->getOperand(Mode0Idx).getImm() && 12645bb48eaSTom Stellard (LatrCFAlu->getOperand(KBank0Idx).getImm() != 12745bb48eaSTom Stellard RootCFAlu->getOperand(KBank0Idx).getImm() || 12845bb48eaSTom Stellard LatrCFAlu->getOperand(KBank0LineIdx).getImm() != 12945bb48eaSTom Stellard RootCFAlu->getOperand(KBank0LineIdx).getImm())) { 13045bb48eaSTom Stellard DEBUG(dbgs() << "Wrong KC0\n"); 13145bb48eaSTom Stellard return false; 13245bb48eaSTom Stellard } 13345bb48eaSTom Stellard // Is KCache Bank 1 compatible ? 13445bb48eaSTom Stellard int Mode1Idx = 13545bb48eaSTom Stellard TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_MODE1); 13645bb48eaSTom Stellard int KBank1Idx = 13745bb48eaSTom Stellard TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_BANK1); 13845bb48eaSTom Stellard int KBank1LineIdx = 13945bb48eaSTom Stellard TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_ADDR1); 14045bb48eaSTom Stellard if (LatrCFAlu->getOperand(Mode1Idx).getImm() && 14145bb48eaSTom Stellard RootCFAlu->getOperand(Mode1Idx).getImm() && 14245bb48eaSTom Stellard (LatrCFAlu->getOperand(KBank1Idx).getImm() != 14345bb48eaSTom Stellard RootCFAlu->getOperand(KBank1Idx).getImm() || 14445bb48eaSTom Stellard LatrCFAlu->getOperand(KBank1LineIdx).getImm() != 14545bb48eaSTom Stellard RootCFAlu->getOperand(KBank1LineIdx).getImm())) { 14645bb48eaSTom Stellard DEBUG(dbgs() << "Wrong KC0\n"); 14745bb48eaSTom Stellard return false; 14845bb48eaSTom Stellard } 14945bb48eaSTom Stellard if (LatrCFAlu->getOperand(Mode0Idx).getImm()) { 15045bb48eaSTom Stellard RootCFAlu->getOperand(Mode0Idx).setImm( 15145bb48eaSTom Stellard LatrCFAlu->getOperand(Mode0Idx).getImm()); 15245bb48eaSTom Stellard RootCFAlu->getOperand(KBank0Idx).setImm( 15345bb48eaSTom Stellard LatrCFAlu->getOperand(KBank0Idx).getImm()); 15445bb48eaSTom Stellard RootCFAlu->getOperand(KBank0LineIdx).setImm( 15545bb48eaSTom Stellard LatrCFAlu->getOperand(KBank0LineIdx).getImm()); 15645bb48eaSTom Stellard } 15745bb48eaSTom Stellard if (LatrCFAlu->getOperand(Mode1Idx).getImm()) { 15845bb48eaSTom Stellard RootCFAlu->getOperand(Mode1Idx).setImm( 15945bb48eaSTom Stellard LatrCFAlu->getOperand(Mode1Idx).getImm()); 16045bb48eaSTom Stellard RootCFAlu->getOperand(KBank1Idx).setImm( 16145bb48eaSTom Stellard LatrCFAlu->getOperand(KBank1Idx).getImm()); 16245bb48eaSTom Stellard RootCFAlu->getOperand(KBank1LineIdx).setImm( 16345bb48eaSTom Stellard LatrCFAlu->getOperand(KBank1LineIdx).getImm()); 16445bb48eaSTom Stellard } 16545bb48eaSTom Stellard RootCFAlu->getOperand(CntIdx).setImm(CumuledInsts); 16645bb48eaSTom Stellard RootCFAlu->setDesc(TII->get(LatrCFAlu->getOpcode())); 16745bb48eaSTom Stellard return true; 16845bb48eaSTom Stellard } 16945bb48eaSTom Stellard 17045bb48eaSTom Stellard bool R600ClauseMergePass::runOnMachineFunction(MachineFunction &MF) { 171*7de74af9SAndrew Kaylor if (skipFunction(*MF.getFunction())) 172*7de74af9SAndrew Kaylor return false; 173*7de74af9SAndrew Kaylor 17445bb48eaSTom Stellard TII = static_cast<const R600InstrInfo *>(MF.getSubtarget().getInstrInfo()); 17545bb48eaSTom Stellard for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end(); 17645bb48eaSTom Stellard BB != BB_E; ++BB) { 17745bb48eaSTom Stellard MachineBasicBlock &MBB = *BB; 17845bb48eaSTom Stellard MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); 17945bb48eaSTom Stellard MachineBasicBlock::iterator LatestCFAlu = E; 18045bb48eaSTom Stellard while (I != E) { 18145bb48eaSTom Stellard MachineInstr *MI = I++; 18245bb48eaSTom Stellard if ((!TII->canBeConsideredALU(MI) && !isCFAlu(MI)) || 18345bb48eaSTom Stellard TII->mustBeLastInClause(MI->getOpcode())) 18445bb48eaSTom Stellard LatestCFAlu = E; 18545bb48eaSTom Stellard if (!isCFAlu(MI)) 18645bb48eaSTom Stellard continue; 18745bb48eaSTom Stellard cleanPotentialDisabledCFAlu(MI); 18845bb48eaSTom Stellard 18945bb48eaSTom Stellard if (LatestCFAlu != E && mergeIfPossible(LatestCFAlu, MI)) { 19045bb48eaSTom Stellard MI->eraseFromParent(); 19145bb48eaSTom Stellard } else { 19245bb48eaSTom Stellard assert(MI->getOperand(8).getImm() && "CF ALU instruction disabled"); 19345bb48eaSTom Stellard LatestCFAlu = MI; 19445bb48eaSTom Stellard } 19545bb48eaSTom Stellard } 19645bb48eaSTom Stellard } 19745bb48eaSTom Stellard return false; 19845bb48eaSTom Stellard } 19945bb48eaSTom Stellard 20045bb48eaSTom Stellard const char *R600ClauseMergePass::getPassName() const { 20145bb48eaSTom Stellard return "R600 Merge Clause Markers Pass"; 20245bb48eaSTom Stellard } 20345bb48eaSTom Stellard 20445bb48eaSTom Stellard } // end anonymous namespace 20545bb48eaSTom Stellard 20645bb48eaSTom Stellard 20745bb48eaSTom Stellard llvm::FunctionPass *llvm::createR600ClauseMergePass(TargetMachine &TM) { 20845bb48eaSTom Stellard return new R600ClauseMergePass(TM); 20945bb48eaSTom Stellard } 210