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 //===----------------------------------------------------------------------===//
15 #include "PPCInstrInfo.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/MachineMemOperand.h"
22 #include "llvm/Support/ErrorHandling.h"
26 #define DEBUG_TYPE "ppc-early-ret"
27 STATISTIC(NumBCLR
, "Number of early conditional returns");
28 STATISTIC(NumBLR
, "Number of early returns");
31 // PPCEarlyReturn pass - For simple functions without epilogue code, move
32 // returns up, and create conditional returns, to avoid unnecessary
33 // branch-to-blr sequences.
34 struct PPCEarlyReturn
: public MachineFunctionPass
{
36 PPCEarlyReturn() : MachineFunctionPass(ID
) {
37 initializePPCEarlyReturnPass(*PassRegistry::getPassRegistry());
40 const TargetInstrInfo
*TII
;
43 bool processBlock(MachineBasicBlock
&ReturnMBB
) {
46 MachineBasicBlock::iterator I
= ReturnMBB
.begin();
47 I
= ReturnMBB
.SkipPHIsLabelsAndDebug(I
);
49 // The block must be essentially empty except for the blr.
50 if (I
== ReturnMBB
.end() ||
51 (I
->getOpcode() != PPC::BLR
&& I
->getOpcode() != PPC::BLR8
) ||
52 I
!= ReturnMBB
.getLastNonDebugInstr())
55 SmallVector
<MachineBasicBlock
*, 8> PredToRemove
;
56 for (MachineBasicBlock
*Pred
: ReturnMBB
.predecessors()) {
57 bool OtherReference
= false, BlockChanged
= false;
62 for (MachineBasicBlock::iterator J
= Pred
->getLastNonDebugInstr();;) {
66 if (J
->getOpcode() == PPC::B
) {
67 if (J
->getOperand(0).getMBB() == &ReturnMBB
) {
68 // This is an unconditional branch to the return. Replace the
70 MachineInstr
*MI
= ReturnMBB
.getParent()->CloneMachineInstr(&*I
);
73 MachineBasicBlock::iterator K
= J
--;
79 } else if (J
->getOpcode() == PPC::BCC
) {
80 if (J
->getOperand(2).getMBB() == &ReturnMBB
) {
81 // This is a conditional branch to the return. Replace the branch
83 MachineInstr
*MI
= ReturnMBB
.getParent()->CloneMachineInstr(&*I
);
84 MI
->setDesc(TII
->get(PPC::BCCLR
));
85 MachineInstrBuilder(*ReturnMBB
.getParent(), MI
)
86 .add(J
->getOperand(0))
87 .add(J
->getOperand(1));
90 MachineBasicBlock::iterator K
= J
--;
96 } else if (J
->getOpcode() == PPC::BC
|| J
->getOpcode() == PPC::BCn
) {
97 if (J
->getOperand(1).getMBB() == &ReturnMBB
) {
98 // This is a conditional branch to the return. Replace the branch
100 MachineInstr
*MI
= ReturnMBB
.getParent()->CloneMachineInstr(&*I
);
102 TII
->get(J
->getOpcode() == PPC::BC
? PPC::BCLR
: PPC::BCLRn
));
103 MachineInstrBuilder(*ReturnMBB
.getParent(), MI
)
104 .add(J
->getOperand(0));
107 MachineBasicBlock::iterator K
= J
--;
108 K
->eraseFromParent();
113 } else if (J
->isBranch()) {
114 if (J
->isIndirectBranch()) {
115 if (ReturnMBB
.hasAddressTaken())
116 OtherReference
= true;
118 for (unsigned i
= 0; i
< J
->getNumOperands(); ++i
)
119 if (J
->getOperand(i
).isMBB() &&
120 J
->getOperand(i
).getMBB() == &ReturnMBB
)
121 OtherReference
= true;
122 } else if (!J
->isTerminator() && !J
->isDebugInstr())
125 if (J
== Pred
->begin())
131 if (Pred
->canFallThrough() && Pred
->isLayoutSuccessor(&ReturnMBB
))
132 OtherReference
= true;
134 // Predecessors are stored in a vector and can't be removed here.
135 if (!OtherReference
&& BlockChanged
) {
136 PredToRemove
.push_back(Pred
);
143 for (MachineBasicBlock
*MBB
: PredToRemove
)
144 MBB
->removeSuccessor(&ReturnMBB
, true);
146 if (Changed
&& !ReturnMBB
.hasAddressTaken()) {
147 // We now might be able to merge this blr-only block into its
148 // by-layout predecessor.
149 if (ReturnMBB
.pred_size() == 1) {
150 MachineBasicBlock
&PrevMBB
= **ReturnMBB
.pred_begin();
151 if (PrevMBB
.isLayoutSuccessor(&ReturnMBB
) && PrevMBB
.canFallThrough()) {
152 // Move the blr into the preceding block.
153 PrevMBB
.splice(PrevMBB
.end(), &ReturnMBB
, I
);
154 PrevMBB
.removeSuccessor(&ReturnMBB
, true);
158 if (ReturnMBB
.pred_empty())
159 ReturnMBB
.eraseFromParent();
166 bool runOnMachineFunction(MachineFunction
&MF
) override
{
167 if (skipFunction(MF
.getFunction()))
170 TII
= MF
.getSubtarget().getInstrInfo();
172 bool Changed
= false;
174 // If the function does not have at least two blocks, then there is
179 for (MachineBasicBlock
&B
: llvm::make_early_inc_range(MF
))
180 Changed
|= processBlock(B
);
185 MachineFunctionProperties
getRequiredProperties() const override
{
186 return MachineFunctionProperties().set(
187 MachineFunctionProperties::Property::NoVRegs
);
190 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
191 MachineFunctionPass::getAnalysisUsage(AU
);
196 INITIALIZE_PASS(PPCEarlyReturn
, DEBUG_TYPE
,
197 "PowerPC Early-Return Creation", false, false)
199 char PPCEarlyReturn::ID
= 0;
201 llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }