15ffd83dbSDimitry Andric //===-- SIPostRABundler.cpp -----------------------------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric /// \file 105ffd83dbSDimitry Andric /// This pass creates bundles of memory instructions to protect adjacent loads 115ffd83dbSDimitry Andric /// and stores from beeing rescheduled apart from each other post-RA. 125ffd83dbSDimitry Andric /// 135ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 145ffd83dbSDimitry Andric 155ffd83dbSDimitry Andric #include "AMDGPU.h" 16*e8d8bef9SDimitry Andric #include "GCNSubtarget.h" 175ffd83dbSDimitry Andric #include "llvm/ADT/SmallSet.h" 185ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 195ffd83dbSDimitry Andric 205ffd83dbSDimitry Andric using namespace llvm; 215ffd83dbSDimitry Andric 225ffd83dbSDimitry Andric #define DEBUG_TYPE "si-post-ra-bundler" 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric namespace { 255ffd83dbSDimitry Andric 265ffd83dbSDimitry Andric class SIPostRABundler : public MachineFunctionPass { 275ffd83dbSDimitry Andric public: 285ffd83dbSDimitry Andric static char ID; 295ffd83dbSDimitry Andric 305ffd83dbSDimitry Andric public: 315ffd83dbSDimitry Andric SIPostRABundler() : MachineFunctionPass(ID) { 325ffd83dbSDimitry Andric initializeSIPostRABundlerPass(*PassRegistry::getPassRegistry()); 335ffd83dbSDimitry Andric } 345ffd83dbSDimitry Andric 355ffd83dbSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 365ffd83dbSDimitry Andric 375ffd83dbSDimitry Andric StringRef getPassName() const override { 385ffd83dbSDimitry Andric return "SI post-RA bundler"; 395ffd83dbSDimitry Andric } 405ffd83dbSDimitry Andric 415ffd83dbSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 425ffd83dbSDimitry Andric AU.setPreservesAll(); 435ffd83dbSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 445ffd83dbSDimitry Andric } 455ffd83dbSDimitry Andric 465ffd83dbSDimitry Andric private: 475ffd83dbSDimitry Andric const SIRegisterInfo *TRI; 485ffd83dbSDimitry Andric 495ffd83dbSDimitry Andric SmallSet<Register, 16> Defs; 505ffd83dbSDimitry Andric 515ffd83dbSDimitry Andric bool isDependentLoad(const MachineInstr &MI) const; 525ffd83dbSDimitry Andric 535ffd83dbSDimitry Andric }; 545ffd83dbSDimitry Andric 555ffd83dbSDimitry Andric } // End anonymous namespace. 565ffd83dbSDimitry Andric 575ffd83dbSDimitry Andric INITIALIZE_PASS(SIPostRABundler, DEBUG_TYPE, "SI post-RA bundler", false, false) 585ffd83dbSDimitry Andric 595ffd83dbSDimitry Andric char SIPostRABundler::ID = 0; 605ffd83dbSDimitry Andric 615ffd83dbSDimitry Andric char &llvm::SIPostRABundlerID = SIPostRABundler::ID; 625ffd83dbSDimitry Andric 635ffd83dbSDimitry Andric FunctionPass *llvm::createSIPostRABundlerPass() { 645ffd83dbSDimitry Andric return new SIPostRABundler(); 655ffd83dbSDimitry Andric } 665ffd83dbSDimitry Andric 675ffd83dbSDimitry Andric bool SIPostRABundler::isDependentLoad(const MachineInstr &MI) const { 685ffd83dbSDimitry Andric if (!MI.mayLoad()) 695ffd83dbSDimitry Andric return false; 705ffd83dbSDimitry Andric 715ffd83dbSDimitry Andric for (const MachineOperand &Op : MI.explicit_operands()) { 725ffd83dbSDimitry Andric if (!Op.isReg()) 735ffd83dbSDimitry Andric continue; 745ffd83dbSDimitry Andric Register Reg = Op.getReg(); 755ffd83dbSDimitry Andric for (Register Def : Defs) 765ffd83dbSDimitry Andric if (TRI->regsOverlap(Reg, Def)) 775ffd83dbSDimitry Andric return true; 785ffd83dbSDimitry Andric } 795ffd83dbSDimitry Andric 805ffd83dbSDimitry Andric return false; 815ffd83dbSDimitry Andric } 825ffd83dbSDimitry Andric 835ffd83dbSDimitry Andric bool SIPostRABundler::runOnMachineFunction(MachineFunction &MF) { 845ffd83dbSDimitry Andric if (skipFunction(MF.getFunction())) 855ffd83dbSDimitry Andric return false; 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric TRI = MF.getSubtarget<GCNSubtarget>().getRegisterInfo(); 885ffd83dbSDimitry Andric bool Changed = false; 895ffd83dbSDimitry Andric const uint64_t MemFlags = SIInstrFlags::MTBUF | SIInstrFlags::MUBUF | 905ffd83dbSDimitry Andric SIInstrFlags::SMRD | SIInstrFlags::DS | 915ffd83dbSDimitry Andric SIInstrFlags::FLAT | SIInstrFlags::MIMG; 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric for (MachineBasicBlock &MBB : MF) { 945ffd83dbSDimitry Andric MachineBasicBlock::instr_iterator Next; 955ffd83dbSDimitry Andric MachineBasicBlock::instr_iterator B = MBB.instr_begin(); 965ffd83dbSDimitry Andric MachineBasicBlock::instr_iterator E = MBB.instr_end(); 975ffd83dbSDimitry Andric for (auto I = B; I != E; I = Next) { 985ffd83dbSDimitry Andric Next = std::next(I); 995ffd83dbSDimitry Andric 1005ffd83dbSDimitry Andric const uint64_t IMemFlags = I->getDesc().TSFlags & MemFlags; 1015ffd83dbSDimitry Andric 1025ffd83dbSDimitry Andric if (IMemFlags == 0 || I->isBundled() || !I->mayLoadOrStore() || 1035ffd83dbSDimitry Andric B->mayLoad() != I->mayLoad() || B->mayStore() != I->mayStore() || 1045ffd83dbSDimitry Andric ((B->getDesc().TSFlags & MemFlags) != IMemFlags) || 1055ffd83dbSDimitry Andric isDependentLoad(*I)) { 1065ffd83dbSDimitry Andric 1075ffd83dbSDimitry Andric if (B != I) { 1085ffd83dbSDimitry Andric if (std::next(B) != I) { 1095ffd83dbSDimitry Andric finalizeBundle(MBB, B, I); 1105ffd83dbSDimitry Andric Changed = true; 1115ffd83dbSDimitry Andric } 1125ffd83dbSDimitry Andric Next = I; 1135ffd83dbSDimitry Andric } 1145ffd83dbSDimitry Andric 1155ffd83dbSDimitry Andric B = Next; 1165ffd83dbSDimitry Andric Defs.clear(); 1175ffd83dbSDimitry Andric continue; 1185ffd83dbSDimitry Andric } 1195ffd83dbSDimitry Andric 1205ffd83dbSDimitry Andric if (I->getNumExplicitDefs() == 0) 1215ffd83dbSDimitry Andric continue; 1225ffd83dbSDimitry Andric 1235ffd83dbSDimitry Andric Defs.insert(I->defs().begin()->getReg()); 1245ffd83dbSDimitry Andric } 1255ffd83dbSDimitry Andric 1265ffd83dbSDimitry Andric if (B != E && std::next(B) != E) { 1275ffd83dbSDimitry Andric finalizeBundle(MBB, B, E); 1285ffd83dbSDimitry Andric Changed = true; 1295ffd83dbSDimitry Andric } 1305ffd83dbSDimitry Andric 1315ffd83dbSDimitry Andric Defs.clear(); 1325ffd83dbSDimitry Andric } 1335ffd83dbSDimitry Andric 1345ffd83dbSDimitry Andric return Changed; 1355ffd83dbSDimitry Andric } 136