1 //===--------- HexagonCopyHoisting.cpp - Hexagon Copy Hoisting ----------===//
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
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 //===----------------------------------------------------------------------===//
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"
24 #define DEBUG_TYPE "CopyHoist"
28 static cl::opt
<std::string
> CPHoistFn("cphoistfn", cl::Hidden
, cl::desc(""),
32 void initializeHexagonCopyHoistingPass(PassRegistry
&Registry
);
33 FunctionPass
*createHexagonCopyHoisting();
38 class HexagonCopyHoisting
: public MachineFunctionPass
{
42 HexagonCopyHoisting() : MachineFunctionPass(ID
), MFN(nullptr), MRI(nullptr) {
43 initializeHexagonCopyHoistingPass(*PassRegistry::getPassRegistry());
46 StringRef
getPassName() const override
{ return "Hexagon Copy Hoisting"; }
48 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
49 AU
.addRequired
<SlotIndexesWrapperPass
>();
50 AU
.addRequired
<LiveIntervalsWrapperPass
>();
51 AU
.addPreserved
<SlotIndexesWrapperPass
>();
52 AU
.addPreserved
<LiveIntervalsWrapperPass
>();
53 AU
.addRequired
<MachineDominatorTreeWrapperPass
>();
54 AU
.addPreserved
<MachineDominatorTreeWrapperPass
>();
55 MachineFunctionPass::getAnalysisUsage(AU
);
58 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
59 void collectCopyInst();
60 void addMItoCopyList(MachineInstr
*MI
);
61 bool analyzeCopy(MachineBasicBlock
*BB
);
62 bool isSafetoMove(MachineInstr
*CandMI
);
63 void moveCopyInstr(MachineBasicBlock
*DestBB
,
64 std::pair
<Register
, Register
> Key
, MachineInstr
*MI
);
67 MachineRegisterInfo
*MRI
;
68 std::vector
<DenseMap
<std::pair
<Register
, Register
>, MachineInstr
*>>
74 char HexagonCopyHoisting::ID
= 0;
77 char &HexagonCopyHoistingID
= HexagonCopyHoisting::ID
;
80 bool HexagonCopyHoisting::runOnMachineFunction(MachineFunction
&Fn
) {
82 if ((CPHoistFn
!= "") && (CPHoistFn
!= Fn
.getFunction().getName()))
86 MRI
= &Fn
.getRegInfo();
88 LLVM_DEBUG(dbgs() << "\nCopy Hoisting:" << "\'" << Fn
.getName() << "\'\n");
91 CopyMIList
.resize(Fn
.getNumBlockIDs());
93 // Traverse through all basic blocks and collect copy instructions.
96 // Traverse through the basic blocks again and move the COPY instructions
97 // that are present in all the successors of BB to BB.
99 for (MachineBasicBlock
*BB
: post_order(&Fn
)) {
101 if (BB
->pred_size() != 1)
103 auto &BBCopyInst
= CopyMIList
[BB
->getNumber()];
104 if (BBCopyInst
.size() > 0)
105 Changed
|= analyzeCopy(*BB
->pred_begin());
108 // Re-compute liveness
110 LiveIntervals
&LIS
= getAnalysis
<LiveIntervalsWrapperPass
>().getLIS();
111 SlotIndexes
*SI
= LIS
.getSlotIndexes();
118 //===----------------------------------------------------------------------===//
119 // Save all COPY instructions for each basic block in CopyMIList vector.
120 //===----------------------------------------------------------------------===//
121 void HexagonCopyHoisting::collectCopyInst() {
122 for (MachineBasicBlock
&BB
: *MFN
) {
124 auto &BBCopyInst
= CopyMIList
[BB
.getNumber()];
125 LLVM_DEBUG(dbgs() << "Visiting BB#" << BB
.getNumber() << ":\n");
128 for (MachineInstr
&MI
: BB
) {
129 if (MI
.getOpcode() == TargetOpcode::COPY
)
130 addMItoCopyList(&MI
);
132 LLVM_DEBUG(dbgs() << "\tNumber of copies: " << BBCopyInst
.size() << "\n");
136 void HexagonCopyHoisting::addMItoCopyList(MachineInstr
*MI
) {
137 unsigned BBNum
= MI
->getParent()->getNumber();
138 auto &BBCopyInst
= CopyMIList
[BBNum
];
139 Register DstReg
= MI
->getOperand(0).getReg();
140 Register SrcReg
= MI
->getOperand(1).getReg();
142 if (!Register::isVirtualRegister(DstReg
) ||
143 !Register::isVirtualRegister(SrcReg
) ||
144 MRI
->getRegClass(DstReg
) != &Hexagon::IntRegsRegClass
||
145 MRI
->getRegClass(SrcReg
) != &Hexagon::IntRegsRegClass
)
148 BBCopyInst
.insert(std::pair(std::pair(SrcReg
, DstReg
), MI
));
150 LLVM_DEBUG(dbgs() << "\tAdding Copy Instr to the list: " << MI
<< "\n");
151 for (auto II
: BBCopyInst
) {
152 MachineInstr
*TempMI
= II
.getSecond();
153 LLVM_DEBUG(dbgs() << "\tIn the list: " << TempMI
<< "\n");
158 //===----------------------------------------------------------------------===//
159 // Look at the COPY instructions of all the successors of BB. If the same
160 // instruction is present in every successor and can be safely moved,
162 //===----------------------------------------------------------------------===//
163 bool HexagonCopyHoisting::analyzeCopy(MachineBasicBlock
*BB
) {
165 bool Changed
= false;
166 if (BB
->succ_size() < 2)
169 for (MachineBasicBlock
*SB
: BB
->successors()) {
170 if (SB
->pred_size() != 1 || SB
->isEHPad() || SB
->hasAddressTaken())
174 MachineBasicBlock
*SBB1
= *BB
->succ_begin();
175 auto &BBCopyInst1
= CopyMIList
[SBB1
->getNumber()];
177 for (auto II
: BBCopyInst1
) {
178 std::pair
<Register
, Register
> Key
= II
.getFirst();
179 MachineInstr
*MI
= II
.getSecond();
180 bool IsSafetoMove
= true;
181 for (MachineBasicBlock
*SuccBB
: BB
->successors()) {
182 auto &SuccBBCopyInst
= CopyMIList
[SuccBB
->getNumber()];
183 if (!SuccBBCopyInst
.count(Key
)) {
184 // Same copy not present in this successor
185 IsSafetoMove
= false;
188 // If present, make sure that it's safe to pull this copy instruction
189 // into the predecessor.
190 MachineInstr
*SuccMI
= SuccBBCopyInst
[Key
];
191 if (!isSafetoMove(SuccMI
)) {
192 IsSafetoMove
= false;
196 // If we have come this far, this copy instruction can be safely
197 // moved to the predecessor basic block.
199 LLVM_DEBUG(dbgs() << "\t\t Moving instr to BB#" << BB
->getNumber() << ": "
201 moveCopyInstr(BB
, Key
, MI
);
202 // Add my into BB copyMI list.
208 auto &BBCopyInst
= CopyMIList
[BB
->getNumber()];
209 for (auto II
: BBCopyInst
) {
210 MachineInstr
*TempMI
= II
.getSecond();
211 LLVM_DEBUG(dbgs() << "\tIn the list: " << TempMI
<< "\n");
217 bool HexagonCopyHoisting::isSafetoMove(MachineInstr
*CandMI
) {
218 // Make sure that it's safe to move this 'copy' instruction to the predecessor
220 assert(CandMI
->getOperand(0).isReg() && CandMI
->getOperand(1).isReg());
221 Register DefR
= CandMI
->getOperand(0).getReg();
222 Register UseR
= CandMI
->getOperand(1).getReg();
224 MachineBasicBlock
*BB
= CandMI
->getParent();
225 // There should not be a def/use of DefR between the start of BB and CandMI.
226 MachineBasicBlock::iterator MII
, MIE
;
227 for (MII
= BB
->begin(), MIE
= CandMI
; MII
!= MIE
; ++MII
) {
228 MachineInstr
*OtherMI
= &*MII
;
229 for (const MachineOperand
&Mo
: OtherMI
->operands())
230 if (Mo
.isReg() && Mo
.getReg() == DefR
)
233 // There should not be a def of UseR between the start of BB and CandMI.
234 for (MII
= BB
->begin(), MIE
= CandMI
; MII
!= MIE
; ++MII
) {
235 MachineInstr
*OtherMI
= &*MII
;
236 for (const MachineOperand
&Mo
: OtherMI
->operands())
237 if (Mo
.isReg() && Mo
.isDef() && Mo
.getReg() == UseR
)
243 void HexagonCopyHoisting::moveCopyInstr(MachineBasicBlock
*DestBB
,
244 std::pair
<Register
, Register
> Key
,
246 MachineBasicBlock::iterator FirstTI
= DestBB
->getFirstTerminator();
247 assert(FirstTI
!= DestBB
->end());
249 DestBB
->splice(FirstTI
, MI
->getParent(), MI
);
252 for (MachineBasicBlock
*SuccBB
: drop_begin(DestBB
->successors())) {
253 auto &BBCopyInst
= CopyMIList
[SuccBB
->getNumber()];
254 MachineInstr
*SuccMI
= BBCopyInst
[Key
];
255 SuccMI
->eraseFromParent();
256 BBCopyInst
.erase(Key
);
260 //===----------------------------------------------------------------------===//
261 // Public Constructor Functions
262 //===----------------------------------------------------------------------===//
264 INITIALIZE_PASS(HexagonCopyHoisting
, "hexagon-move-phicopy",
265 "Hexagon move phi copy", false, false)
267 FunctionPass
*llvm::createHexagonCopyHoisting() {
268 return new HexagonCopyHoisting();