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