1 //===------------- PPCEarlyReturn.cpp - Form Early Returns ----------------===//
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 // A pass that form early (predicated) returns. If-conversion handles some of
10 // this, but this pass picks up some remaining cases.
12 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/PPCPredicates.h"
16 #include "PPCInstrBuilder.h"
17 #include "PPCInstrInfo.h"
18 #include "PPCMachineFunctionInfo.h"
19 #include "PPCTargetMachine.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/Statistic.h"
22 #include "llvm/CodeGen/MachineFrameInfo.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 #include "llvm/CodeGen/MachineInstrBuilder.h"
25 #include "llvm/CodeGen/MachineMemOperand.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/MC/MCAsmInfo.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/ErrorHandling.h"
30 #include "llvm/Support/TargetRegistry.h"
31 #include "llvm/Support/raw_ostream.h"
35 #define DEBUG_TYPE "ppc-early-ret"
36 STATISTIC(NumBCLR
, "Number of early conditional returns");
37 STATISTIC(NumBLR
, "Number of early returns");
40 // PPCEarlyReturn pass - For simple functions without epilogue code, move
41 // returns up, and create conditional returns, to avoid unnecessary
42 // branch-to-blr sequences.
43 struct PPCEarlyReturn
: public MachineFunctionPass
{
45 PPCEarlyReturn() : MachineFunctionPass(ID
) {
46 initializePPCEarlyReturnPass(*PassRegistry::getPassRegistry());
49 const TargetInstrInfo
*TII
;
52 bool processBlock(MachineBasicBlock
&ReturnMBB
) {
55 MachineBasicBlock::iterator I
= ReturnMBB
.begin();
56 I
= ReturnMBB
.SkipPHIsLabelsAndDebug(I
);
58 // The block must be essentially empty except for the blr.
59 if (I
== ReturnMBB
.end() ||
60 (I
->getOpcode() != PPC::BLR
&& I
->getOpcode() != PPC::BLR8
) ||
61 I
!= ReturnMBB
.getLastNonDebugInstr())
64 SmallVector
<MachineBasicBlock
*, 8> PredToRemove
;
65 for (MachineBasicBlock::pred_iterator PI
= ReturnMBB
.pred_begin(),
66 PIE
= ReturnMBB
.pred_end(); PI
!= PIE
; ++PI
) {
67 bool OtherReference
= false, BlockChanged
= false;
72 for (MachineBasicBlock::iterator J
= (*PI
)->getLastNonDebugInstr();;) {
73 if (J
== (*PI
)->end())
76 if (J
->getOpcode() == PPC::B
) {
77 if (J
->getOperand(0).getMBB() == &ReturnMBB
) {
78 // This is an unconditional branch to the return. Replace the
80 BuildMI(**PI
, J
, J
->getDebugLoc(), TII
->get(I
->getOpcode()))
82 MachineBasicBlock::iterator K
= J
--;
88 } else if (J
->getOpcode() == PPC::BCC
) {
89 if (J
->getOperand(2).getMBB() == &ReturnMBB
) {
90 // This is a conditional branch to the return. Replace the branch
92 BuildMI(**PI
, J
, J
->getDebugLoc(), TII
->get(PPC::BCCLR
))
93 .addImm(J
->getOperand(0).getImm())
94 .addReg(J
->getOperand(1).getReg())
96 MachineBasicBlock::iterator K
= J
--;
102 } else if (J
->getOpcode() == PPC::BC
|| J
->getOpcode() == PPC::BCn
) {
103 if (J
->getOperand(1).getMBB() == &ReturnMBB
) {
104 // This is a conditional branch to the return. Replace the branch
107 **PI
, J
, J
->getDebugLoc(),
108 TII
->get(J
->getOpcode() == PPC::BC
? PPC::BCLR
: PPC::BCLRn
))
109 .addReg(J
->getOperand(0).getReg())
110 .copyImplicitOps(*I
);
111 MachineBasicBlock::iterator K
= J
--;
112 K
->eraseFromParent();
117 } else if (J
->isBranch()) {
118 if (J
->isIndirectBranch()) {
119 if (ReturnMBB
.hasAddressTaken())
120 OtherReference
= true;
122 for (unsigned i
= 0; i
< J
->getNumOperands(); ++i
)
123 if (J
->getOperand(i
).isMBB() &&
124 J
->getOperand(i
).getMBB() == &ReturnMBB
)
125 OtherReference
= true;
126 } else if (!J
->isTerminator() && !J
->isDebugInstr())
129 if (J
== (*PI
)->begin())
135 if ((*PI
)->canFallThrough() && (*PI
)->isLayoutSuccessor(&ReturnMBB
))
136 OtherReference
= true;
138 // Predecessors are stored in a vector and can't be removed here.
139 if (!OtherReference
&& BlockChanged
) {
140 PredToRemove
.push_back(*PI
);
147 for (unsigned i
= 0, ie
= PredToRemove
.size(); i
!= ie
; ++i
)
148 PredToRemove
[i
]->removeSuccessor(&ReturnMBB
, true);
150 if (Changed
&& !ReturnMBB
.hasAddressTaken()) {
151 // We now might be able to merge this blr-only block into its
152 // by-layout predecessor.
153 if (ReturnMBB
.pred_size() == 1) {
154 MachineBasicBlock
&PrevMBB
= **ReturnMBB
.pred_begin();
155 if (PrevMBB
.isLayoutSuccessor(&ReturnMBB
) && PrevMBB
.canFallThrough()) {
156 // Move the blr into the preceding block.
157 PrevMBB
.splice(PrevMBB
.end(), &ReturnMBB
, I
);
158 PrevMBB
.removeSuccessor(&ReturnMBB
, true);
162 if (ReturnMBB
.pred_empty())
163 ReturnMBB
.eraseFromParent();
170 bool runOnMachineFunction(MachineFunction
&MF
) override
{
171 if (skipFunction(MF
.getFunction()))
174 TII
= MF
.getSubtarget().getInstrInfo();
176 bool Changed
= false;
178 // If the function does not have at least two blocks, then there is
183 // We can't use a range-based for loop due to clobbering the iterator.
184 for (MachineFunction::iterator I
= MF
.begin(), E
= MF
.end(); I
!= E
;) {
185 MachineBasicBlock
&B
= *I
++;
186 Changed
|= processBlock(B
);
192 MachineFunctionProperties
getRequiredProperties() const override
{
193 return MachineFunctionProperties().set(
194 MachineFunctionProperties::Property::NoVRegs
);
197 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
198 MachineFunctionPass::getAnalysisUsage(AU
);
203 INITIALIZE_PASS(PPCEarlyReturn
, DEBUG_TYPE
,
204 "PowerPC Early-Return Creation", false, false)
206 char PPCEarlyReturn::ID
= 0;
208 llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }