LLVM 20.0.0git
PPCEarlyReturn.cpp
Go to the documentation of this file.
1//===------------- PPCEarlyReturn.cpp - Form Early Returns ----------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// A pass that form early (predicated) returns. If-conversion handles some of
10// this, but this pass picks up some remaining cases.
11//
12//===----------------------------------------------------------------------===//
13
15#include "PPC.h"
16#include "PPCInstrBuilder.h"
17#include "PPCInstrInfo.h"
19#include "PPCTargetMachine.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/Statistic.h"
27#include "llvm/MC/MCAsmInfo.h"
29#include "llvm/Support/Debug.h"
32
33using namespace llvm;
34
35#define DEBUG_TYPE "ppc-early-ret"
36STATISTIC(NumBCLR, "Number of early conditional returns");
37STATISTIC(NumBLR, "Number of early returns");
38
39namespace {
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 {
44 static char ID;
45 PPCEarlyReturn() : MachineFunctionPass(ID) {
47 }
48
49 const TargetInstrInfo *TII;
50
51protected:
52 bool processBlock(MachineBasicBlock &ReturnMBB) {
53 bool Changed = false;
54
56 I = ReturnMBB.SkipPHIsLabelsAndDebug(I);
57
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())
62 return Changed;
63
65 for (MachineBasicBlock *Pred : ReturnMBB.predecessors()) {
66 bool OtherReference = false, BlockChanged = false;
67
68 if (Pred->empty())
69 continue;
70
71 for (MachineBasicBlock::iterator J = Pred->getLastNonDebugInstr();;) {
72 if (J == Pred->end())
73 break;
74
75 if (J->getOpcode() == PPC::B) {
76 if (J->getOperand(0).getMBB() == &ReturnMBB) {
77 // This is an unconditional branch to the return. Replace the
78 // branch with a blr.
79 MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);
80 Pred->insert(J, MI);
81
83 K->eraseFromParent();
84 BlockChanged = true;
85 ++NumBLR;
86 continue;
87 }
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
91 // with a bclr.
92 MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);
93 MI->setDesc(TII->get(PPC::BCCLR));
94 MachineInstrBuilder(*ReturnMBB.getParent(), MI)
95 .add(J->getOperand(0))
96 .add(J->getOperand(1));
97 Pred->insert(J, MI);
98
100 K->eraseFromParent();
101 BlockChanged = true;
102 ++NumBCLR;
103 continue;
104 }
105 } else if (J->getOpcode() == PPC::BC || J->getOpcode() == PPC::BCn) {
106 if (J->getOperand(1).getMBB() == &ReturnMBB) {
107 // This is a conditional branch to the return. Replace the branch
108 // with a bclr.
109 MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);
110 MI->setDesc(
111 TII->get(J->getOpcode() == PPC::BC ? PPC::BCLR : PPC::BCLRn));
112 MachineInstrBuilder(*ReturnMBB.getParent(), MI)
113 .add(J->getOperand(0));
114 Pred->insert(J, MI);
115
117 K->eraseFromParent();
118 BlockChanged = true;
119 ++NumBCLR;
120 continue;
121 }
122 } else if (J->isBranch()) {
123 if (J->isIndirectBranch()) {
124 if (ReturnMBB.hasAddressTaken())
125 OtherReference = true;
126 } else
127 for (unsigned i = 0; i < J->getNumOperands(); ++i)
128 if (J->getOperand(i).isMBB() &&
129 J->getOperand(i).getMBB() == &ReturnMBB)
130 OtherReference = true;
131 } else if (!J->isTerminator() && !J->isDebugInstr())
132 break;
133
134 if (J == Pred->begin())
135 break;
136
137 --J;
138 }
139
140 if (Pred->canFallThrough() && Pred->isLayoutSuccessor(&ReturnMBB))
141 OtherReference = true;
142
143 // Predecessors are stored in a vector and can't be removed here.
144 if (!OtherReference && BlockChanged) {
145 PredToRemove.push_back(Pred);
146 }
147
148 if (BlockChanged)
149 Changed = true;
150 }
151
152 for (MachineBasicBlock *MBB : PredToRemove)
153 MBB->removeSuccessor(&ReturnMBB, true);
154
155 if (Changed && !ReturnMBB.hasAddressTaken()) {
156 // We now might be able to merge this blr-only block into its
157 // by-layout predecessor.
158 if (ReturnMBB.pred_size() == 1) {
159 MachineBasicBlock &PrevMBB = **ReturnMBB.pred_begin();
160 if (PrevMBB.isLayoutSuccessor(&ReturnMBB) && PrevMBB.canFallThrough()) {
161 // Move the blr into the preceding block.
162 PrevMBB.splice(PrevMBB.end(), &ReturnMBB, I);
163 PrevMBB.removeSuccessor(&ReturnMBB, true);
164 }
165 }
166
167 if (ReturnMBB.pred_empty())
168 ReturnMBB.eraseFromParent();
169 }
170
171 return Changed;
172 }
173
174public:
175 bool runOnMachineFunction(MachineFunction &MF) override {
176 if (skipFunction(MF.getFunction()))
177 return false;
178
180
181 bool Changed = false;
182
183 // If the function does not have at least two blocks, then there is
184 // nothing to do.
185 if (MF.size() < 2)
186 return Changed;
187
189 Changed |= processBlock(B);
190
191 return Changed;
192 }
193
196 MachineFunctionProperties::Property::NoVRegs);
197 }
198
199 void getAnalysisUsage(AnalysisUsage &AU) const override {
201 }
202 };
203}
204
205INITIALIZE_PASS(PPCEarlyReturn, DEBUG_TYPE,
206 "PowerPC Early-Return Creation", false, false)
207
208char PPCEarlyReturn::ID = 0;
210llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
#define DEBUG_TYPE
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
This file contains some templates that are useful if you are working with the STL at all.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:166
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
Definition: Pass.cpp:178
unsigned pred_size() const
iterator SkipPHIsLabelsAndDebug(iterator I, Register Reg=Register(), bool SkipPseudoOp=true)
Return the first instruction in MBB after I that is not a PHI, label or debug.
bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
bool hasAddressTaken() const
Test whether this block is used as something other than the target of a terminator,...
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
unsigned size() const
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineInstr * CloneMachineInstr(const MachineInstr *Orig)
Create a new MachineInstr which is a copy of Orig, identical in all ways except the instruction has n...
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
void insert(mop_iterator InsertBefore, ArrayRef< MachineOperand > Ops)
Inserts Ops BEFORE It. Can untie/retie tied operands.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetInstrInfo * getInstrInfo() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:656
FunctionPass * createPPCEarlyReturnPass()
void initializePPCEarlyReturnPass(PassRegistry &)