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