xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/SIPostRABundler.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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