145bb48eaSTom Stellard //===-- R600ClauseMergePass - Merge consecutive CF_ALU -------------------===//
245bb48eaSTom Stellard //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
645bb48eaSTom Stellard //
745bb48eaSTom Stellard //===----------------------------------------------------------------------===//
845bb48eaSTom Stellard //
945bb48eaSTom Stellard /// \file
106527b2a4SSebastian Neubauer /// R600EmitClauseMarker pass emits CFAlu instruction in a conservative manner.
1145bb48eaSTom Stellard /// This pass is merging consecutive CFAlus where applicable.
1245bb48eaSTom Stellard /// It needs to be called after IfCvt for best results.
1345bb48eaSTom Stellard //===----------------------------------------------------------------------===//
1445bb48eaSTom Stellard 
1548958d02SDaniil Fukalov #include "MCTargetDesc/R600MCTargetDesc.h"
1648958d02SDaniil Fukalov #include "R600.h"
17560d7e04Sdfukalov #include "R600Subtarget.h"
18*989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineFunctionPass.h"
1945bb48eaSTom Stellard 
2045bb48eaSTom Stellard using namespace llvm;
2145bb48eaSTom Stellard 
2245bb48eaSTom Stellard #define DEBUG_TYPE "r600mergeclause"
2345bb48eaSTom Stellard 
2445bb48eaSTom Stellard namespace {
2545bb48eaSTom Stellard 
isCFAlu(const MachineInstr & MI)264d295118SDuncan P. N. Exon Smith static bool isCFAlu(const MachineInstr &MI) {
274d295118SDuncan P. N. Exon Smith   switch (MI.getOpcode()) {
28c5a154dbSTom Stellard   case R600::CF_ALU:
29c5a154dbSTom Stellard   case R600::CF_ALU_PUSH_BEFORE:
3045bb48eaSTom Stellard     return true;
3145bb48eaSTom Stellard   default:
3245bb48eaSTom Stellard     return false;
3345bb48eaSTom Stellard   }
3445bb48eaSTom Stellard }
3545bb48eaSTom Stellard 
3645bb48eaSTom Stellard class R600ClauseMergePass : public MachineFunctionPass {
3745bb48eaSTom Stellard 
3845bb48eaSTom Stellard private:
3945bb48eaSTom Stellard   const R600InstrInfo *TII;
4045bb48eaSTom Stellard 
414d295118SDuncan P. N. Exon Smith   unsigned getCFAluSize(const MachineInstr &MI) const;
424d295118SDuncan P. N. Exon Smith   bool isCFAluEnabled(const MachineInstr &MI) const;
4345bb48eaSTom Stellard 
4445bb48eaSTom Stellard   /// IfCvt pass can generate "disabled" ALU clause marker that need to be
4545bb48eaSTom Stellard   /// removed and their content affected to the previous alu clause.
4645bb48eaSTom Stellard   /// This function parse instructions after CFAlu until it find a disabled
4745bb48eaSTom Stellard   /// CFAlu and merge the content, or an enabled CFAlu.
484d295118SDuncan P. N. Exon Smith   void cleanPotentialDisabledCFAlu(MachineInstr &CFAlu) const;
4945bb48eaSTom Stellard 
5045bb48eaSTom Stellard   /// Check whether LatrCFAlu can be merged into RootCFAlu and do it if
5145bb48eaSTom Stellard   /// it is the case.
524d295118SDuncan P. N. Exon Smith   bool mergeIfPossible(MachineInstr &RootCFAlu,
534d295118SDuncan P. N. Exon Smith                        const MachineInstr &LatrCFAlu) const;
5445bb48eaSTom Stellard 
5545bb48eaSTom Stellard public:
56a2f57be2STom Stellard   static char ID;
57a2f57be2STom Stellard 
R600ClauseMergePass()588b61764cSFrancis Visoiu Mistrih   R600ClauseMergePass() : MachineFunctionPass(ID) { }
5945bb48eaSTom Stellard 
6045bb48eaSTom Stellard   bool runOnMachineFunction(MachineFunction &MF) override;
6145bb48eaSTom Stellard 
62117296c0SMehdi Amini   StringRef getPassName() const override;
6345bb48eaSTom Stellard };
6445bb48eaSTom Stellard 
65a2f57be2STom Stellard } // end anonymous namespace
66a2f57be2STom Stellard 
67a2f57be2STom Stellard INITIALIZE_PASS_BEGIN(R600ClauseMergePass, DEBUG_TYPE,
68a2f57be2STom Stellard                       "R600 Clause Merge", false, false)
69a2f57be2STom Stellard INITIALIZE_PASS_END(R600ClauseMergePass, DEBUG_TYPE,
70a2f57be2STom Stellard                     "R600 Clause Merge", false, false)
71a2f57be2STom Stellard 
7245bb48eaSTom Stellard char R600ClauseMergePass::ID = 0;
7345bb48eaSTom Stellard 
74a2f57be2STom Stellard char &llvm::R600ClauseMergePassID = R600ClauseMergePass::ID;
75a2f57be2STom Stellard 
getCFAluSize(const MachineInstr & MI) const764d295118SDuncan P. N. Exon Smith unsigned R600ClauseMergePass::getCFAluSize(const MachineInstr &MI) const {
7745bb48eaSTom Stellard   assert(isCFAlu(MI));
784d295118SDuncan P. N. Exon Smith   return MI
79c5a154dbSTom Stellard       .getOperand(TII->getOperandIdx(MI.getOpcode(), R600::OpName::COUNT))
804d295118SDuncan P. N. Exon Smith       .getImm();
8145bb48eaSTom Stellard }
8245bb48eaSTom Stellard 
isCFAluEnabled(const MachineInstr & MI) const834d295118SDuncan P. N. Exon Smith bool R600ClauseMergePass::isCFAluEnabled(const MachineInstr &MI) const {
8445bb48eaSTom Stellard   assert(isCFAlu(MI));
854d295118SDuncan P. N. Exon Smith   return MI
86c5a154dbSTom Stellard       .getOperand(TII->getOperandIdx(MI.getOpcode(), R600::OpName::Enabled))
874d295118SDuncan P. N. Exon Smith       .getImm();
8845bb48eaSTom Stellard }
8945bb48eaSTom Stellard 
cleanPotentialDisabledCFAlu(MachineInstr & CFAlu) const904d295118SDuncan P. N. Exon Smith void R600ClauseMergePass::cleanPotentialDisabledCFAlu(
914d295118SDuncan P. N. Exon Smith     MachineInstr &CFAlu) const {
92c5a154dbSTom Stellard   int CntIdx = TII->getOperandIdx(R600::CF_ALU, R600::OpName::COUNT);
934d295118SDuncan P. N. Exon Smith   MachineBasicBlock::iterator I = CFAlu, E = CFAlu.getParent()->end();
9445bb48eaSTom Stellard   I++;
9545bb48eaSTom Stellard   do {
964d295118SDuncan P. N. Exon Smith     while (I != E && !isCFAlu(*I))
9745bb48eaSTom Stellard       I++;
9845bb48eaSTom Stellard     if (I == E)
9945bb48eaSTom Stellard       return;
1004d295118SDuncan P. N. Exon Smith     MachineInstr &MI = *I++;
10145bb48eaSTom Stellard     if (isCFAluEnabled(MI))
10245bb48eaSTom Stellard       break;
1034d295118SDuncan P. N. Exon Smith     CFAlu.getOperand(CntIdx).setImm(getCFAluSize(CFAlu) + getCFAluSize(MI));
1044d295118SDuncan P. N. Exon Smith     MI.eraseFromParent();
10545bb48eaSTom Stellard   } while (I != E);
10645bb48eaSTom Stellard }
10745bb48eaSTom Stellard 
mergeIfPossible(MachineInstr & RootCFAlu,const MachineInstr & LatrCFAlu) const1084d295118SDuncan P. N. Exon Smith bool R600ClauseMergePass::mergeIfPossible(MachineInstr &RootCFAlu,
1094d295118SDuncan P. N. Exon Smith                                           const MachineInstr &LatrCFAlu) const {
11045bb48eaSTom Stellard   assert(isCFAlu(RootCFAlu) && isCFAlu(LatrCFAlu));
111c5a154dbSTom Stellard   int CntIdx = TII->getOperandIdx(R600::CF_ALU, R600::OpName::COUNT);
11245bb48eaSTom Stellard   unsigned RootInstCount = getCFAluSize(RootCFAlu),
11345bb48eaSTom Stellard       LaterInstCount = getCFAluSize(LatrCFAlu);
11445bb48eaSTom Stellard   unsigned CumuledInsts = RootInstCount + LaterInstCount;
11545bb48eaSTom Stellard   if (CumuledInsts >= TII->getMaxAlusPerClause()) {
116d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Excess inst counts\n");
11745bb48eaSTom Stellard     return false;
11845bb48eaSTom Stellard   }
119c5a154dbSTom Stellard   if (RootCFAlu.getOpcode() == R600::CF_ALU_PUSH_BEFORE)
12045bb48eaSTom Stellard     return false;
12145bb48eaSTom Stellard   // Is KCache Bank 0 compatible ?
12245bb48eaSTom Stellard   int Mode0Idx =
123c5a154dbSTom Stellard       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_MODE0);
12445bb48eaSTom Stellard   int KBank0Idx =
125c5a154dbSTom Stellard       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_BANK0);
12645bb48eaSTom Stellard   int KBank0LineIdx =
127c5a154dbSTom Stellard       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_ADDR0);
1284d295118SDuncan P. N. Exon Smith   if (LatrCFAlu.getOperand(Mode0Idx).getImm() &&
1294d295118SDuncan P. N. Exon Smith       RootCFAlu.getOperand(Mode0Idx).getImm() &&
1304d295118SDuncan P. N. Exon Smith       (LatrCFAlu.getOperand(KBank0Idx).getImm() !=
1314d295118SDuncan P. N. Exon Smith            RootCFAlu.getOperand(KBank0Idx).getImm() ||
1324d295118SDuncan P. N. Exon Smith        LatrCFAlu.getOperand(KBank0LineIdx).getImm() !=
1334d295118SDuncan P. N. Exon Smith            RootCFAlu.getOperand(KBank0LineIdx).getImm())) {
134d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Wrong KC0\n");
13545bb48eaSTom Stellard     return false;
13645bb48eaSTom Stellard   }
13745bb48eaSTom Stellard   // Is KCache Bank 1 compatible ?
13845bb48eaSTom Stellard   int Mode1Idx =
139c5a154dbSTom Stellard       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_MODE1);
14045bb48eaSTom Stellard   int KBank1Idx =
141c5a154dbSTom Stellard       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_BANK1);
14245bb48eaSTom Stellard   int KBank1LineIdx =
143c5a154dbSTom Stellard       TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_ADDR1);
1444d295118SDuncan P. N. Exon Smith   if (LatrCFAlu.getOperand(Mode1Idx).getImm() &&
1454d295118SDuncan P. N. Exon Smith       RootCFAlu.getOperand(Mode1Idx).getImm() &&
1464d295118SDuncan P. N. Exon Smith       (LatrCFAlu.getOperand(KBank1Idx).getImm() !=
1474d295118SDuncan P. N. Exon Smith            RootCFAlu.getOperand(KBank1Idx).getImm() ||
1484d295118SDuncan P. N. Exon Smith        LatrCFAlu.getOperand(KBank1LineIdx).getImm() !=
1494d295118SDuncan P. N. Exon Smith            RootCFAlu.getOperand(KBank1LineIdx).getImm())) {
150d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Wrong KC0\n");
15145bb48eaSTom Stellard     return false;
15245bb48eaSTom Stellard   }
1534d295118SDuncan P. N. Exon Smith   if (LatrCFAlu.getOperand(Mode0Idx).getImm()) {
1544d295118SDuncan P. N. Exon Smith     RootCFAlu.getOperand(Mode0Idx).setImm(
1554d295118SDuncan P. N. Exon Smith         LatrCFAlu.getOperand(Mode0Idx).getImm());
1564d295118SDuncan P. N. Exon Smith     RootCFAlu.getOperand(KBank0Idx).setImm(
1574d295118SDuncan P. N. Exon Smith         LatrCFAlu.getOperand(KBank0Idx).getImm());
1584d295118SDuncan P. N. Exon Smith     RootCFAlu.getOperand(KBank0LineIdx)
1594d295118SDuncan P. N. Exon Smith         .setImm(LatrCFAlu.getOperand(KBank0LineIdx).getImm());
16045bb48eaSTom Stellard   }
1614d295118SDuncan P. N. Exon Smith   if (LatrCFAlu.getOperand(Mode1Idx).getImm()) {
1624d295118SDuncan P. N. Exon Smith     RootCFAlu.getOperand(Mode1Idx).setImm(
1634d295118SDuncan P. N. Exon Smith         LatrCFAlu.getOperand(Mode1Idx).getImm());
1644d295118SDuncan P. N. Exon Smith     RootCFAlu.getOperand(KBank1Idx).setImm(
1654d295118SDuncan P. N. Exon Smith         LatrCFAlu.getOperand(KBank1Idx).getImm());
1664d295118SDuncan P. N. Exon Smith     RootCFAlu.getOperand(KBank1LineIdx)
1674d295118SDuncan P. N. Exon Smith         .setImm(LatrCFAlu.getOperand(KBank1LineIdx).getImm());
16845bb48eaSTom Stellard   }
1694d295118SDuncan P. N. Exon Smith   RootCFAlu.getOperand(CntIdx).setImm(CumuledInsts);
1704d295118SDuncan P. N. Exon Smith   RootCFAlu.setDesc(TII->get(LatrCFAlu.getOpcode()));
17145bb48eaSTom Stellard   return true;
17245bb48eaSTom Stellard }
17345bb48eaSTom Stellard 
runOnMachineFunction(MachineFunction & MF)17445bb48eaSTom Stellard bool R600ClauseMergePass::runOnMachineFunction(MachineFunction &MF) {
175f1caa283SMatthias Braun   if (skipFunction(MF.getFunction()))
1767de74af9SAndrew Kaylor     return false;
1777de74af9SAndrew Kaylor 
17843e92fe3SMatt Arsenault   const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
17943e92fe3SMatt Arsenault   TII = ST.getInstrInfo();
18043e92fe3SMatt Arsenault 
18159a26448SKazu Hirata   for (MachineBasicBlock &MBB : MF) {
18245bb48eaSTom Stellard     MachineBasicBlock::iterator I = MBB.begin(),  E = MBB.end();
18345bb48eaSTom Stellard     MachineBasicBlock::iterator LatestCFAlu = E;
18445bb48eaSTom Stellard     while (I != E) {
1854d295118SDuncan P. N. Exon Smith       MachineInstr &MI = *I++;
1864d295118SDuncan P. N. Exon Smith       if ((!TII->canBeConsideredALU(MI) && !isCFAlu(MI)) ||
1874d295118SDuncan P. N. Exon Smith           TII->mustBeLastInClause(MI.getOpcode()))
18845bb48eaSTom Stellard         LatestCFAlu = E;
18945bb48eaSTom Stellard       if (!isCFAlu(MI))
19045bb48eaSTom Stellard         continue;
19145bb48eaSTom Stellard       cleanPotentialDisabledCFAlu(MI);
19245bb48eaSTom Stellard 
1934d295118SDuncan P. N. Exon Smith       if (LatestCFAlu != E && mergeIfPossible(*LatestCFAlu, MI)) {
1944d295118SDuncan P. N. Exon Smith         MI.eraseFromParent();
19545bb48eaSTom Stellard       } else {
1964d295118SDuncan P. N. Exon Smith         assert(MI.getOperand(8).getImm() && "CF ALU instruction disabled");
19745bb48eaSTom Stellard         LatestCFAlu = MI;
19845bb48eaSTom Stellard       }
19945bb48eaSTom Stellard     }
20045bb48eaSTom Stellard   }
20145bb48eaSTom Stellard   return false;
20245bb48eaSTom Stellard }
20345bb48eaSTom Stellard 
getPassName() const204117296c0SMehdi Amini StringRef R600ClauseMergePass::getPassName() const {
20545bb48eaSTom Stellard   return "R600 Merge Clause Markers Pass";
20645bb48eaSTom Stellard }
20745bb48eaSTom Stellard 
createR600ClauseMergePass()2088b61764cSFrancis Visoiu Mistrih llvm::FunctionPass *llvm::createR600ClauseMergePass() {
2098b61764cSFrancis Visoiu Mistrih   return new R600ClauseMergePass();
21045bb48eaSTom Stellard }
211