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