1 //===-- ARMBlockPlacement.cpp - ARM block placement pass ------------===//
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 //===----------------------------------------------------------------------===//
9 // This pass re-arranges machine basic blocks to suit target requirements.
10 // Currently it only moves blocks to fix backwards WLS branches.
12 //===----------------------------------------------------------------------===//
15 #include "ARMBaseInstrInfo.h"
16 #include "ARMBasicBlockInfo.h"
17 #include "ARMSubtarget.h"
18 #include "MVETailPredUtils.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/MachineLoopInfo.h"
25 #define DEBUG_TYPE "arm-block-placement"
26 #define DEBUG_PREFIX "ARM Block Placement: "
29 class ARMBlockPlacement
: public MachineFunctionPass
{
31 const ARMBaseInstrInfo
*TII
;
32 std::unique_ptr
<ARMBasicBlockUtils
> BBUtils
= nullptr;
33 MachineLoopInfo
*MLI
= nullptr;
37 ARMBlockPlacement() : MachineFunctionPass(ID
) {}
39 bool runOnMachineFunction(MachineFunction
&MF
) override
;
40 void moveBasicBlock(MachineBasicBlock
*BB
, MachineBasicBlock
*Before
);
41 bool blockIsBefore(MachineBasicBlock
*BB
, MachineBasicBlock
*Other
);
42 bool fixBackwardsWLS(MachineLoop
*ML
);
43 bool processPostOrderLoops(MachineLoop
*ML
);
44 bool revertWhileToDo(MachineInstr
*WLS
, MachineLoop
*ML
);
46 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
47 AU
.addRequired
<MachineLoopInfo
>();
48 MachineFunctionPass::getAnalysisUsage(AU
);
54 FunctionPass
*llvm::createARMBlockPlacementPass() {
55 return new ARMBlockPlacement();
58 char ARMBlockPlacement::ID
= 0;
60 INITIALIZE_PASS(ARMBlockPlacement
, DEBUG_TYPE
, "ARM block placement", false,
63 static MachineInstr
*findWLSInBlock(MachineBasicBlock
*MBB
) {
64 for (auto &Terminator
: MBB
->terminators()) {
65 if (isWhileLoopStart(Terminator
))
71 /// Find WhileLoopStart in the loop predecessor BB or otherwise in its only
72 /// predecessor. If found, returns (BB, WLS Instr) pair, otherwise a null pair.
73 static MachineInstr
*findWLS(MachineLoop
*ML
) {
74 MachineBasicBlock
*Predecessor
= ML
->getLoopPredecessor();
77 MachineInstr
*WlsInstr
= findWLSInBlock(Predecessor
);
80 if (Predecessor
->pred_size() == 1)
81 return findWLSInBlock(*Predecessor
->pred_begin());
85 // Revert a WhileLoopStart to an equivalent DoLoopStart and branch. Note that
86 // because of the branches this requires an extra block to be created.
87 bool ARMBlockPlacement::revertWhileToDo(MachineInstr
*WLS
, MachineLoop
*ML
) {
88 // lr = t2WhileLoopStartTP r0, r1, TgtBB
94 // LR = t2DoLoopStartTP r0, r1
96 MachineBasicBlock
*Preheader
= WLS
->getParent();
97 assert(WLS
!= &Preheader
->back());
98 assert(WLS
->getNextNode() == &Preheader
->back());
99 MachineInstr
*Br
= &Preheader
->back();
100 assert(Br
->getOpcode() == ARM::t2B
);
101 assert(Br
->getOperand(1).getImm() == 14);
103 // Clear the kill flags, as the cmp/bcc will no longer kill any operands.
104 WLS
->getOperand(1).setIsKill(false);
105 if (WLS
->getOpcode() == ARM::t2WhileLoopStartTP
)
106 WLS
->getOperand(2).setIsKill(false);
108 // Create the new block
109 MachineBasicBlock
*NewBlock
= Preheader
->getParent()->CreateMachineBasicBlock(
110 Preheader
->getBasicBlock());
111 Preheader
->getParent()->insert(++Preheader
->getIterator(), NewBlock
);
113 Br
->removeFromParent();
114 NewBlock
->insert(NewBlock
->end(), Br
);
115 // And setup the successors correctly.
116 Preheader
->replaceSuccessor(Br
->getOperand(0).getMBB(), NewBlock
);
117 NewBlock
->addSuccessor(Br
->getOperand(0).getMBB());
119 // Create a new DLS to replace the WLS
120 MachineInstrBuilder MIB
=
121 BuildMI(*NewBlock
, Br
, WLS
->getDebugLoc(),
122 TII
->get(WLS
->getOpcode() == ARM::t2WhileLoopStartTP
123 ? ARM::t2DoLoopStartTP
124 : ARM::t2DoLoopStart
));
125 MIB
.add(WLS
->getOperand(0));
126 MIB
.add(WLS
->getOperand(1));
127 if (WLS
->getOpcode() == ARM::t2WhileLoopStartTP
)
128 MIB
.add(WLS
->getOperand(2));
130 LLVM_DEBUG(dbgs() << DEBUG_PREFIX
131 << "Reverting While Loop to Do Loop: " << *WLS
<< "\n");
133 RevertWhileLoopStartLR(WLS
, TII
, ARM::t2Bcc
, true);
135 LivePhysRegs LiveRegs
;
136 computeAndAddLiveIns(LiveRegs
, *NewBlock
);
138 Preheader
->getParent()->RenumberBlocks();
139 BBUtils
->computeAllBlockSizes();
140 BBUtils
->adjustBBOffsetsAfter(Preheader
);
145 /// Checks if loop has a backwards branching WLS, and if possible, fixes it.
146 /// This requires checking the predecessor (ie. preheader or it's predecessor)
147 /// for a WLS and if its loopExit/target is before it.
148 /// If moving the predecessor won't convert a WLS (to the predecessor) from
149 /// a forward to a backward branching WLS, then move the predecessor block
150 /// to before the loopExit/target.
151 bool ARMBlockPlacement::fixBackwardsWLS(MachineLoop
*ML
) {
152 MachineInstr
*WlsInstr
= findWLS(ML
);
156 MachineBasicBlock
*Predecessor
= WlsInstr
->getParent();
157 MachineBasicBlock
*LoopExit
= getWhileLoopStartTargetBB(*WlsInstr
);
159 // We don't want to move Preheader to before the function's entry block.
160 if (!LoopExit
->getPrevNode())
162 if (blockIsBefore(Predecessor
, LoopExit
))
164 LLVM_DEBUG(dbgs() << DEBUG_PREFIX
<< "Found a backwards WLS from "
165 << Predecessor
->getFullName() << " to "
166 << LoopExit
->getFullName() << "\n");
168 // Make sure no forward branching WLSs to the Predecessor become backwards
169 // branching. An example loop structure where the Predecessor can't be moved,
170 // since bb2's WLS will become forwards once bb3 is moved before/above bb1.
175 // bb3: - Predecessor
178 for (auto It
= ++LoopExit
->getIterator(); It
!= Predecessor
->getIterator();
180 MachineBasicBlock
*MBB
= &*It
;
181 for (auto &Terminator
: MBB
->terminators()) {
182 if (!isWhileLoopStart(Terminator
))
184 MachineBasicBlock
*WLSTarget
= getWhileLoopStartTargetBB(Terminator
);
185 // TODO: Analyse the blocks to make a decision if it would be worth
186 // moving Preheader even if we'd introduce a backwards WLS
187 if (WLSTarget
== Predecessor
) {
189 dbgs() << DEBUG_PREFIX
190 << "Can't move Predecessor"
191 "block as it would convert a WLS from forward to a "
192 "backwards branching WLS\n");
193 return revertWhileToDo(WlsInstr
, ML
);
198 moveBasicBlock(Predecessor
, LoopExit
);
202 /// Updates ordering (of WLS BB and their loopExits) in inner loops first
203 /// Returns true if any change was made in any of the loops
204 bool ARMBlockPlacement::processPostOrderLoops(MachineLoop
*ML
) {
205 bool Changed
= false;
206 for (auto *InnerML
: *ML
)
207 Changed
|= processPostOrderLoops(InnerML
);
208 return Changed
| fixBackwardsWLS(ML
);
211 bool ARMBlockPlacement::runOnMachineFunction(MachineFunction
&MF
) {
212 if (skipFunction(MF
.getFunction()))
214 const ARMSubtarget
&ST
= static_cast<const ARMSubtarget
&>(MF
.getSubtarget());
217 LLVM_DEBUG(dbgs() << DEBUG_PREFIX
<< "Running on " << MF
.getName() << "\n");
218 MLI
= &getAnalysis
<MachineLoopInfo
>();
219 TII
= static_cast<const ARMBaseInstrInfo
*>(ST
.getInstrInfo());
220 BBUtils
= std::unique_ptr
<ARMBasicBlockUtils
>(new ARMBasicBlockUtils(MF
));
222 BBUtils
->computeAllBlockSizes();
223 BBUtils
->adjustBBOffsetsAfter(&MF
.front());
224 bool Changed
= false;
226 // Find loops with a backwards branching WLS and fix if possible.
227 for (auto *ML
: *MLI
)
228 Changed
|= processPostOrderLoops(ML
);
233 bool ARMBlockPlacement::blockIsBefore(MachineBasicBlock
*BB
,
234 MachineBasicBlock
*Other
) {
235 return BBUtils
->getOffsetOf(Other
) > BBUtils
->getOffsetOf(BB
);
238 // Moves a BasicBlock before another, without changing the control flow
239 void ARMBlockPlacement::moveBasicBlock(MachineBasicBlock
*BB
,
240 MachineBasicBlock
*Before
) {
241 LLVM_DEBUG(dbgs() << DEBUG_PREFIX
<< "Moving " << BB
->getName() << " before "
242 << Before
->getName() << "\n");
243 MachineBasicBlock
*BBPrevious
= BB
->getPrevNode();
244 assert(BBPrevious
&& "Cannot move the function entry basic block");
245 MachineBasicBlock
*BBNext
= BB
->getNextNode();
247 MachineBasicBlock
*BeforePrev
= Before
->getPrevNode();
249 "Cannot move the given block to before the function entry block");
250 MachineFunction
*F
= BB
->getParent();
251 BB
->moveBefore(Before
);
253 // Since only the blocks are to be moved around (but the control flow must
254 // not change), if there were any fall-throughs (to/from adjacent blocks),
255 // replace with unconditional branch to the fall through block.
256 auto FixFallthrough
= [&](MachineBasicBlock
*From
, MachineBasicBlock
*To
) {
257 LLVM_DEBUG(dbgs() << DEBUG_PREFIX
<< "Checking for fallthrough from "
258 << From
->getName() << " to " << To
->getName() << "\n");
259 assert(From
->isSuccessor(To
) &&
260 "'To' is expected to be a successor of 'From'");
261 MachineInstr
&Terminator
= *(--From
->terminators().end());
262 if (!Terminator
.isUnconditionalBranch()) {
263 // The BB doesn't have an unconditional branch so it relied on
264 // fall-through. Fix by adding an unconditional branch to the moved BB.
265 MachineInstrBuilder MIB
=
266 BuildMI(From
, Terminator
.getDebugLoc(), TII
->get(ARM::t2B
));
268 MIB
.addImm(ARMCC::CondCodes::AL
);
269 MIB
.addReg(ARM::NoRegister
);
270 LLVM_DEBUG(dbgs() << DEBUG_PREFIX
<< "Adding unconditional branch from "
271 << From
->getName() << " to " << To
->getName() << ": "
276 // Fix fall-through to the moved BB from the one that used to be before it.
277 if (BBPrevious
->isSuccessor(BB
))
278 FixFallthrough(BBPrevious
, BB
);
279 // Fix fall through from the destination BB to the one that used to before it.
280 if (BeforePrev
->isSuccessor(Before
))
281 FixFallthrough(BeforePrev
, Before
);
282 // Fix fall through from the moved BB to the one that used to follow.
283 if (BBNext
&& BB
->isSuccessor(BBNext
))
284 FixFallthrough(BB
, BBNext
);
287 BBUtils
->computeAllBlockSizes();
288 BBUtils
->adjustBBOffsetsAfter(BB
);