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 void initializePPCEarlyReturnPass(PassRegistry
&);
44 // PPCEarlyReturn pass - For simple functions without epilogue code, move
45 // returns up, and create conditional returns, to avoid unnecessary
46 // branch-to-blr sequences.
47 struct PPCEarlyReturn
: public MachineFunctionPass
{
49 PPCEarlyReturn() : MachineFunctionPass(ID
) {
50 initializePPCEarlyReturnPass(*PassRegistry::getPassRegistry());
53 const TargetInstrInfo
*TII
;
56 bool processBlock(MachineBasicBlock
&ReturnMBB
) {
59 MachineBasicBlock::iterator I
= ReturnMBB
.begin();
60 I
= ReturnMBB
.SkipPHIsLabelsAndDebug(I
);
62 // The block must be essentially empty except for the blr.
63 if (I
== ReturnMBB
.end() ||
64 (I
->getOpcode() != PPC::BLR
&& I
->getOpcode() != PPC::BLR8
) ||
65 I
!= ReturnMBB
.getLastNonDebugInstr())
68 SmallVector
<MachineBasicBlock
*, 8> PredToRemove
;
69 for (MachineBasicBlock::pred_iterator PI
= ReturnMBB
.pred_begin(),
70 PIE
= ReturnMBB
.pred_end(); PI
!= PIE
; ++PI
) {
71 bool OtherReference
= false, BlockChanged
= false;
76 for (MachineBasicBlock::iterator J
= (*PI
)->getLastNonDebugInstr();;) {
77 if (J
== (*PI
)->end())
80 if (J
->getOpcode() == PPC::B
) {
81 if (J
->getOperand(0).getMBB() == &ReturnMBB
) {
82 // This is an unconditional branch to the return. Replace the
84 BuildMI(**PI
, J
, J
->getDebugLoc(), TII
->get(I
->getOpcode()))
86 MachineBasicBlock::iterator K
= J
--;
92 } else if (J
->getOpcode() == PPC::BCC
) {
93 if (J
->getOperand(2).getMBB() == &ReturnMBB
) {
94 // This is a conditional branch to the return. Replace the branch
96 BuildMI(**PI
, J
, J
->getDebugLoc(), TII
->get(PPC::BCCLR
))
97 .addImm(J
->getOperand(0).getImm())
98 .addReg(J
->getOperand(1).getReg())
100 MachineBasicBlock::iterator K
= J
--;
101 K
->eraseFromParent();
106 } else if (J
->getOpcode() == PPC::BC
|| J
->getOpcode() == PPC::BCn
) {
107 if (J
->getOperand(1).getMBB() == &ReturnMBB
) {
108 // This is a conditional branch to the return. Replace the branch
111 **PI
, J
, J
->getDebugLoc(),
112 TII
->get(J
->getOpcode() == PPC::BC
? PPC::BCLR
: PPC::BCLRn
))
113 .addReg(J
->getOperand(0).getReg())
114 .copyImplicitOps(*I
);
115 MachineBasicBlock::iterator K
= J
--;
116 K
->eraseFromParent();
121 } else if (J
->isBranch()) {
122 if (J
->isIndirectBranch()) {
123 if (ReturnMBB
.hasAddressTaken())
124 OtherReference
= true;
126 for (unsigned i
= 0; i
< J
->getNumOperands(); ++i
)
127 if (J
->getOperand(i
).isMBB() &&
128 J
->getOperand(i
).getMBB() == &ReturnMBB
)
129 OtherReference
= true;
130 } else if (!J
->isTerminator() && !J
->isDebugInstr())
133 if (J
== (*PI
)->begin())
139 if ((*PI
)->canFallThrough() && (*PI
)->isLayoutSuccessor(&ReturnMBB
))
140 OtherReference
= true;
142 // Predecessors are stored in a vector and can't be removed here.
143 if (!OtherReference
&& BlockChanged
) {
144 PredToRemove
.push_back(*PI
);
151 for (unsigned i
= 0, ie
= PredToRemove
.size(); i
!= ie
; ++i
)
152 PredToRemove
[i
]->removeSuccessor(&ReturnMBB
, true);
154 if (Changed
&& !ReturnMBB
.hasAddressTaken()) {
155 // We now might be able to merge this blr-only block into its
156 // by-layout predecessor.
157 if (ReturnMBB
.pred_size() == 1) {
158 MachineBasicBlock
&PrevMBB
= **ReturnMBB
.pred_begin();
159 if (PrevMBB
.isLayoutSuccessor(&ReturnMBB
) && PrevMBB
.canFallThrough()) {
160 // Move the blr into the preceding block.
161 PrevMBB
.splice(PrevMBB
.end(), &ReturnMBB
, I
);
162 PrevMBB
.removeSuccessor(&ReturnMBB
, true);
166 if (ReturnMBB
.pred_empty())
167 ReturnMBB
.eraseFromParent();
174 bool runOnMachineFunction(MachineFunction
&MF
) override
{
175 if (skipFunction(MF
.getFunction()))
178 TII
= MF
.getSubtarget().getInstrInfo();
180 bool Changed
= false;
182 // If the function does not have at least two blocks, then there is
187 for (MachineFunction::iterator I
= MF
.begin(); I
!= MF
.end();) {
188 MachineBasicBlock
&B
= *I
++;
196 MachineFunctionProperties
getRequiredProperties() const override
{
197 return MachineFunctionProperties().set(
198 MachineFunctionProperties::Property::NoVRegs
);
201 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
202 MachineFunctionPass::getAnalysisUsage(AU
);
207 INITIALIZE_PASS(PPCEarlyReturn
, DEBUG_TYPE
,
208 "PowerPC Early-Return Creation", false, false)
210 char PPCEarlyReturn::ID
= 0;
212 llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }