xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/SIPostRABundler.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry Andric //===-- SIPostRABundler.cpp -----------------------------------------------===//
2*5ffd83dbSDimitry Andric //
3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd83dbSDimitry Andric //
7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric //
9*5ffd83dbSDimitry Andric /// \file
10*5ffd83dbSDimitry Andric /// This pass creates bundles of memory instructions to protect adjacent loads
11*5ffd83dbSDimitry Andric /// and stores from beeing rescheduled apart from each other post-RA.
12*5ffd83dbSDimitry Andric ///
13*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
14*5ffd83dbSDimitry Andric 
15*5ffd83dbSDimitry Andric #include "AMDGPU.h"
16*5ffd83dbSDimitry Andric #include "AMDGPUSubtarget.h"
17*5ffd83dbSDimitry Andric #include "SIDefines.h"
18*5ffd83dbSDimitry Andric #include "SIInstrInfo.h"
19*5ffd83dbSDimitry Andric #include "llvm/ADT/SmallSet.h"
20*5ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
21*5ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h"
22*5ffd83dbSDimitry Andric #include "llvm/InitializePasses.h"
23*5ffd83dbSDimitry Andric 
24*5ffd83dbSDimitry Andric using namespace llvm;
25*5ffd83dbSDimitry Andric 
26*5ffd83dbSDimitry Andric #define DEBUG_TYPE "si-post-ra-bundler"
27*5ffd83dbSDimitry Andric 
28*5ffd83dbSDimitry Andric namespace {
29*5ffd83dbSDimitry Andric 
30*5ffd83dbSDimitry Andric class SIPostRABundler : public MachineFunctionPass {
31*5ffd83dbSDimitry Andric public:
32*5ffd83dbSDimitry Andric   static char ID;
33*5ffd83dbSDimitry Andric 
34*5ffd83dbSDimitry Andric public:
35*5ffd83dbSDimitry Andric   SIPostRABundler() : MachineFunctionPass(ID) {
36*5ffd83dbSDimitry Andric     initializeSIPostRABundlerPass(*PassRegistry::getPassRegistry());
37*5ffd83dbSDimitry Andric   }
38*5ffd83dbSDimitry Andric 
39*5ffd83dbSDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
40*5ffd83dbSDimitry Andric 
41*5ffd83dbSDimitry Andric   StringRef getPassName() const override {
42*5ffd83dbSDimitry Andric     return "SI post-RA bundler";
43*5ffd83dbSDimitry Andric   }
44*5ffd83dbSDimitry Andric 
45*5ffd83dbSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
46*5ffd83dbSDimitry Andric     AU.setPreservesAll();
47*5ffd83dbSDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
48*5ffd83dbSDimitry Andric   }
49*5ffd83dbSDimitry Andric 
50*5ffd83dbSDimitry Andric private:
51*5ffd83dbSDimitry Andric   const SIRegisterInfo *TRI;
52*5ffd83dbSDimitry Andric 
53*5ffd83dbSDimitry Andric   SmallSet<Register, 16> Defs;
54*5ffd83dbSDimitry Andric 
55*5ffd83dbSDimitry Andric   bool isDependentLoad(const MachineInstr &MI) const;
56*5ffd83dbSDimitry Andric 
57*5ffd83dbSDimitry Andric };
58*5ffd83dbSDimitry Andric 
59*5ffd83dbSDimitry Andric } // End anonymous namespace.
60*5ffd83dbSDimitry Andric 
61*5ffd83dbSDimitry Andric INITIALIZE_PASS(SIPostRABundler, DEBUG_TYPE, "SI post-RA bundler", false, false)
62*5ffd83dbSDimitry Andric 
63*5ffd83dbSDimitry Andric char SIPostRABundler::ID = 0;
64*5ffd83dbSDimitry Andric 
65*5ffd83dbSDimitry Andric char &llvm::SIPostRABundlerID = SIPostRABundler::ID;
66*5ffd83dbSDimitry Andric 
67*5ffd83dbSDimitry Andric FunctionPass *llvm::createSIPostRABundlerPass() {
68*5ffd83dbSDimitry Andric   return new SIPostRABundler();
69*5ffd83dbSDimitry Andric }
70*5ffd83dbSDimitry Andric 
71*5ffd83dbSDimitry Andric bool SIPostRABundler::isDependentLoad(const MachineInstr &MI) const {
72*5ffd83dbSDimitry Andric   if (!MI.mayLoad())
73*5ffd83dbSDimitry Andric     return false;
74*5ffd83dbSDimitry Andric 
75*5ffd83dbSDimitry Andric   for (const MachineOperand &Op : MI.explicit_operands()) {
76*5ffd83dbSDimitry Andric     if (!Op.isReg())
77*5ffd83dbSDimitry Andric       continue;
78*5ffd83dbSDimitry Andric     Register Reg = Op.getReg();
79*5ffd83dbSDimitry Andric     for (Register Def : Defs)
80*5ffd83dbSDimitry Andric       if (TRI->regsOverlap(Reg, Def))
81*5ffd83dbSDimitry Andric         return true;
82*5ffd83dbSDimitry Andric   }
83*5ffd83dbSDimitry Andric 
84*5ffd83dbSDimitry Andric   return false;
85*5ffd83dbSDimitry Andric }
86*5ffd83dbSDimitry Andric 
87*5ffd83dbSDimitry Andric bool SIPostRABundler::runOnMachineFunction(MachineFunction &MF) {
88*5ffd83dbSDimitry Andric   if (skipFunction(MF.getFunction()))
89*5ffd83dbSDimitry Andric     return false;
90*5ffd83dbSDimitry Andric 
91*5ffd83dbSDimitry Andric   TRI = MF.getSubtarget<GCNSubtarget>().getRegisterInfo();
92*5ffd83dbSDimitry Andric   bool Changed = false;
93*5ffd83dbSDimitry Andric   const uint64_t MemFlags = SIInstrFlags::MTBUF | SIInstrFlags::MUBUF |
94*5ffd83dbSDimitry Andric                             SIInstrFlags::SMRD | SIInstrFlags::DS |
95*5ffd83dbSDimitry Andric                             SIInstrFlags::FLAT | SIInstrFlags::MIMG;
96*5ffd83dbSDimitry Andric 
97*5ffd83dbSDimitry Andric   for (MachineBasicBlock &MBB : MF) {
98*5ffd83dbSDimitry Andric     MachineBasicBlock::instr_iterator Next;
99*5ffd83dbSDimitry Andric     MachineBasicBlock::instr_iterator B = MBB.instr_begin();
100*5ffd83dbSDimitry Andric     MachineBasicBlock::instr_iterator E = MBB.instr_end();
101*5ffd83dbSDimitry Andric     for (auto I = B; I != E; I = Next) {
102*5ffd83dbSDimitry Andric       Next = std::next(I);
103*5ffd83dbSDimitry Andric 
104*5ffd83dbSDimitry Andric       const uint64_t IMemFlags = I->getDesc().TSFlags & MemFlags;
105*5ffd83dbSDimitry Andric 
106*5ffd83dbSDimitry Andric       if (IMemFlags == 0 || I->isBundled() || !I->mayLoadOrStore() ||
107*5ffd83dbSDimitry Andric           B->mayLoad() != I->mayLoad() || B->mayStore() != I->mayStore() ||
108*5ffd83dbSDimitry Andric           ((B->getDesc().TSFlags & MemFlags) != IMemFlags) ||
109*5ffd83dbSDimitry Andric           isDependentLoad(*I)) {
110*5ffd83dbSDimitry Andric 
111*5ffd83dbSDimitry Andric         if (B != I) {
112*5ffd83dbSDimitry Andric           if (std::next(B) != I) {
113*5ffd83dbSDimitry Andric             finalizeBundle(MBB, B, I);
114*5ffd83dbSDimitry Andric             Changed = true;
115*5ffd83dbSDimitry Andric           }
116*5ffd83dbSDimitry Andric           Next = I;
117*5ffd83dbSDimitry Andric         }
118*5ffd83dbSDimitry Andric 
119*5ffd83dbSDimitry Andric         B = Next;
120*5ffd83dbSDimitry Andric         Defs.clear();
121*5ffd83dbSDimitry Andric         continue;
122*5ffd83dbSDimitry Andric       }
123*5ffd83dbSDimitry Andric 
124*5ffd83dbSDimitry Andric       if (I->getNumExplicitDefs() == 0)
125*5ffd83dbSDimitry Andric         continue;
126*5ffd83dbSDimitry Andric 
127*5ffd83dbSDimitry Andric       Defs.insert(I->defs().begin()->getReg());
128*5ffd83dbSDimitry Andric     }
129*5ffd83dbSDimitry Andric 
130*5ffd83dbSDimitry Andric     if (B != E && std::next(B) != E) {
131*5ffd83dbSDimitry Andric       finalizeBundle(MBB, B, E);
132*5ffd83dbSDimitry Andric       Changed = true;
133*5ffd83dbSDimitry Andric     }
134*5ffd83dbSDimitry Andric 
135*5ffd83dbSDimitry Andric     Defs.clear();
136*5ffd83dbSDimitry Andric   }
137*5ffd83dbSDimitry Andric 
138*5ffd83dbSDimitry Andric   return Changed;
139*5ffd83dbSDimitry Andric }
140