xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonCopyHoisting.cpp (revision 1ed2ef42e01771f5d8ca9be61e07dcf0fd47feba)
1 //===--------- HexagonCopyHoisting.cpp - Hexagon Copy Hoisting  ----------===//
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 // The purpose of this pass is to move the copy instructions that are
9 // present in all the successor of a basic block (BB) to the end of BB.
10 //===----------------------------------------------------------------------===//
11 
12 #include "HexagonTargetMachine.h"
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/ADT/PostOrderIterator.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/Twine.h"
17 #include "llvm/CodeGen/LiveInterval.h"
18 #include "llvm/CodeGen/LiveIntervals.h"
19 #include "llvm/CodeGen/MachineDominators.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/Debug.h"
23 
24 #define DEBUG_TYPE "CopyHoist"
25 
26 using namespace llvm;
27 
28 static cl::opt<std::string> CPHoistFn("cphoistfn", cl::Hidden, cl::desc(""),
29                                       cl::init(""));
30 
31 namespace {
32 
33 class HexagonCopyHoisting : public MachineFunctionPass {
34 
35 public:
36   static char ID;
37   HexagonCopyHoisting() : MachineFunctionPass(ID), MFN(nullptr), MRI(nullptr) {}
38 
39   StringRef getPassName() const override { return "Hexagon Copy Hoisting"; }
40 
41   void getAnalysisUsage(AnalysisUsage &AU) const override {
42     AU.addRequired<SlotIndexesWrapperPass>();
43     AU.addRequired<LiveIntervalsWrapperPass>();
44     AU.addPreserved<SlotIndexesWrapperPass>();
45     AU.addPreserved<LiveIntervalsWrapperPass>();
46     AU.addRequired<MachineDominatorTreeWrapperPass>();
47     AU.addPreserved<MachineDominatorTreeWrapperPass>();
48     MachineFunctionPass::getAnalysisUsage(AU);
49   }
50 
51   bool runOnMachineFunction(MachineFunction &Fn) override;
52   void collectCopyInst();
53   void addMItoCopyList(MachineInstr *MI);
54   bool analyzeCopy(MachineBasicBlock *BB);
55   bool isSafetoMove(MachineInstr *CandMI);
56   void moveCopyInstr(MachineBasicBlock *DestBB,
57                      std::pair<Register, Register> Key, MachineInstr *MI);
58 
59   MachineFunction *MFN;
60   MachineRegisterInfo *MRI;
61   std::vector<DenseMap<std::pair<Register, Register>, MachineInstr *>>
62       CopyMIList;
63 };
64 
65 } // namespace
66 
67 char HexagonCopyHoisting::ID = 0;
68 
69 namespace llvm {
70 char &HexagonCopyHoistingID = HexagonCopyHoisting::ID;
71 } // namespace llvm
72 
73 bool HexagonCopyHoisting::runOnMachineFunction(MachineFunction &Fn) {
74 
75   if ((CPHoistFn != "") && (CPHoistFn != Fn.getFunction().getName()))
76     return false;
77 
78   MFN = &Fn;
79   MRI = &Fn.getRegInfo();
80 
81   LLVM_DEBUG(dbgs() << "\nCopy Hoisting:" << "\'" << Fn.getName() << "\'\n");
82 
83   CopyMIList.clear();
84   CopyMIList.resize(Fn.getNumBlockIDs());
85 
86   // Traverse through all basic blocks and collect copy instructions.
87   collectCopyInst();
88 
89   // Traverse through the basic blocks again and move the COPY instructions
90   // that are present in all the successors of BB to BB.
91   bool Changed = false;
92   for (MachineBasicBlock *BB : post_order(&Fn)) {
93     if (!BB->empty()) {
94       if (BB->pred_size() != 1)
95         continue;
96       auto &BBCopyInst = CopyMIList[BB->getNumber()];
97       if (BBCopyInst.size() > 0)
98         Changed |= analyzeCopy(*BB->pred_begin());
99     }
100   }
101   // Re-compute liveness
102   if (Changed) {
103     LiveIntervals &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
104     SlotIndexes *SI = LIS.getSlotIndexes();
105     SI->reanalyze(Fn);
106     LIS.reanalyze(Fn);
107   }
108   return Changed;
109 }
110 
111 //===----------------------------------------------------------------------===//
112 // Save all COPY instructions for each basic block in CopyMIList vector.
113 //===----------------------------------------------------------------------===//
114 void HexagonCopyHoisting::collectCopyInst() {
115   for (MachineBasicBlock &BB : *MFN) {
116 #ifndef NDEBUG
117     auto &BBCopyInst = CopyMIList[BB.getNumber()];
118     LLVM_DEBUG(dbgs() << "Visiting BB#" << BB.getNumber() << ":\n");
119 #endif
120 
121     for (MachineInstr &MI : BB) {
122       if (MI.getOpcode() == TargetOpcode::COPY)
123         addMItoCopyList(&MI);
124     }
125     LLVM_DEBUG(dbgs() << "\tNumber of copies: " << BBCopyInst.size() << "\n");
126   }
127 }
128 
129 void HexagonCopyHoisting::addMItoCopyList(MachineInstr *MI) {
130   unsigned BBNum = MI->getParent()->getNumber();
131   auto &BBCopyInst = CopyMIList[BBNum];
132   Register DstReg = MI->getOperand(0).getReg();
133   Register SrcReg = MI->getOperand(1).getReg();
134 
135   if (!Register::isVirtualRegister(DstReg) ||
136       !Register::isVirtualRegister(SrcReg) ||
137       MRI->getRegClass(DstReg) != &Hexagon::IntRegsRegClass ||
138       MRI->getRegClass(SrcReg) != &Hexagon::IntRegsRegClass)
139     return;
140 
141   BBCopyInst.insert(std::pair(std::pair(SrcReg, DstReg), MI));
142 #ifndef NDEBUG
143   LLVM_DEBUG(dbgs() << "\tAdding Copy Instr to the list: " << MI << "\n");
144   for (auto II : BBCopyInst) {
145     MachineInstr *TempMI = II.getSecond();
146     LLVM_DEBUG(dbgs() << "\tIn the list: " << TempMI << "\n");
147   }
148 #endif
149 }
150 
151 //===----------------------------------------------------------------------===//
152 // Look at the COPY instructions of all the successors of BB. If the same
153 // instruction is present in every successor and can be safely moved,
154 // pull it into BB.
155 //===----------------------------------------------------------------------===//
156 bool HexagonCopyHoisting::analyzeCopy(MachineBasicBlock *BB) {
157 
158   bool Changed = false;
159   if (BB->succ_size() < 2)
160     return false;
161 
162   for (MachineBasicBlock *SB : BB->successors()) {
163     if (SB->pred_size() != 1 || SB->isEHPad() || SB->hasAddressTaken())
164       return false;
165   }
166 
167   MachineBasicBlock *SBB1 = *BB->succ_begin();
168   auto &BBCopyInst1 = CopyMIList[SBB1->getNumber()];
169 
170   for (auto II : BBCopyInst1) {
171     std::pair<Register, Register> Key = II.getFirst();
172     MachineInstr *MI = II.getSecond();
173     bool IsSafetoMove = true;
174     for (MachineBasicBlock *SuccBB : BB->successors()) {
175       auto &SuccBBCopyInst = CopyMIList[SuccBB->getNumber()];
176       auto It = SuccBBCopyInst.find(Key);
177       if (It == SuccBBCopyInst.end()) {
178         // Same copy not present in this successor
179         IsSafetoMove = false;
180         break;
181       }
182       // If present, make sure that it's safe to pull this copy instruction
183       // into the predecessor.
184       MachineInstr *SuccMI = It->second;
185       if (!isSafetoMove(SuccMI)) {
186         IsSafetoMove = false;
187         break;
188       }
189     }
190     // If we have come this far, this copy instruction can be safely
191     // moved to the predecessor basic block.
192     if (IsSafetoMove) {
193       LLVM_DEBUG(dbgs() << "\t\t Moving instr to BB#" << BB->getNumber() << ": "
194                         << MI << "\n");
195       moveCopyInstr(BB, Key, MI);
196       // Add my into BB copyMI list.
197       Changed = true;
198     }
199   }
200 
201 #ifndef NDEBUG
202   auto &BBCopyInst = CopyMIList[BB->getNumber()];
203   for (auto II : BBCopyInst) {
204     MachineInstr *TempMI = II.getSecond();
205     LLVM_DEBUG(dbgs() << "\tIn the list: " << TempMI << "\n");
206   }
207 #endif
208   return Changed;
209 }
210 
211 bool HexagonCopyHoisting::isSafetoMove(MachineInstr *CandMI) {
212   // Make sure that it's safe to move this 'copy' instruction to the predecessor
213   // basic block.
214   assert(CandMI->getOperand(0).isReg() && CandMI->getOperand(1).isReg());
215   Register DefR = CandMI->getOperand(0).getReg();
216   Register UseR = CandMI->getOperand(1).getReg();
217 
218   MachineBasicBlock *BB = CandMI->getParent();
219   // There should not be a def/use of DefR between the start of BB and CandMI.
220   MachineBasicBlock::iterator MII, MIE;
221   for (MII = BB->begin(), MIE = CandMI; MII != MIE; ++MII) {
222     MachineInstr *OtherMI = &*MII;
223     for (const MachineOperand &Mo : OtherMI->operands())
224       if (Mo.isReg() && Mo.getReg() == DefR)
225         return false;
226   }
227   // There should not be a def of UseR between the start of BB and CandMI.
228   for (MII = BB->begin(), MIE = CandMI; MII != MIE; ++MII) {
229     MachineInstr *OtherMI = &*MII;
230     for (const MachineOperand &Mo : OtherMI->operands())
231       if (Mo.isReg() && Mo.isDef() && Mo.getReg() == UseR)
232         return false;
233   }
234   return true;
235 }
236 
237 void HexagonCopyHoisting::moveCopyInstr(MachineBasicBlock *DestBB,
238                                         std::pair<Register, Register> Key,
239                                         MachineInstr *MI) {
240   MachineBasicBlock::iterator FirstTI = DestBB->getFirstTerminator();
241   assert(FirstTI != DestBB->end());
242 
243   DestBB->splice(FirstTI, MI->getParent(), MI);
244 
245   addMItoCopyList(MI);
246   for (MachineBasicBlock *SuccBB : drop_begin(DestBB->successors())) {
247     auto &BBCopyInst = CopyMIList[SuccBB->getNumber()];
248     MachineInstr *SuccMI = BBCopyInst[Key];
249     SuccMI->eraseFromParent();
250     BBCopyInst.erase(Key);
251   }
252 }
253 
254 //===----------------------------------------------------------------------===//
255 //                         Public Constructor Functions
256 //===----------------------------------------------------------------------===//
257 
258 INITIALIZE_PASS(HexagonCopyHoisting, "hexagon-move-phicopy",
259                 "Hexagon move phi copy", false, false)
260 
261 FunctionPass *llvm::createHexagonCopyHoisting() {
262   return new HexagonCopyHoisting();
263 }
264