LLVM  10.0.0svn
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"
18 #include "PPCMachineFunctionInfo.h"
19 #include "PPCTargetMachine.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/Statistic.h"
27 #include "llvm/MC/MCAsmInfo.h"
28 #include "llvm/Support/Debug.h"
32 
33 using namespace llvm;
34 
35 #define DEBUG_TYPE "ppc-early-ret"
36 STATISTIC(NumBCLR, "Number of early conditional returns");
37 STATISTIC(NumBLR, "Number of early returns");
38 
39 namespace {
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 
51 protected:
52  bool processBlock(MachineBasicBlock &ReturnMBB) {
53  bool Changed = false;
54 
55  MachineBasicBlock::iterator I = ReturnMBB.begin();
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_iterator PI = ReturnMBB.pred_begin(),
66  PIE = ReturnMBB.pred_end(); PI != PIE; ++PI) {
67  bool OtherReference = false, BlockChanged = false;
68 
69  if ((*PI)->empty())
70  continue;
71 
72  for (MachineBasicBlock::iterator J = (*PI)->getLastNonDebugInstr();;) {
73  if (J == (*PI)->end())
74  break;
75 
76  if (J->getOpcode() == PPC::B) {
77  if (J->getOperand(0).getMBB() == &ReturnMBB) {
78  // This is an unconditional branch to the return. Replace the
79  // branch with a blr.
80  BuildMI(**PI, J, J->getDebugLoc(), TII->get(I->getOpcode()))
81  .copyImplicitOps(*I);
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  BuildMI(**PI, J, J->getDebugLoc(), TII->get(PPC::BCCLR))
93  .addImm(J->getOperand(0).getImm())
94  .addReg(J->getOperand(1).getReg())
95  .copyImplicitOps(*I);
97  K->eraseFromParent();
98  BlockChanged = true;
99  ++NumBCLR;
100  continue;
101  }
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
105  // with a bclr.
106  BuildMI(
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);
112  K->eraseFromParent();
113  BlockChanged = true;
114  ++NumBCLR;
115  continue;
116  }
117  } else if (J->isBranch()) {
118  if (J->isIndirectBranch()) {
119  if (ReturnMBB.hasAddressTaken())
120  OtherReference = true;
121  } else
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())
127  break;
128 
129  if (J == (*PI)->begin())
130  break;
131 
132  --J;
133  }
134 
135  if ((*PI)->canFallThrough() && (*PI)->isLayoutSuccessor(&ReturnMBB))
136  OtherReference = true;
137 
138  // Predecessors are stored in a vector and can't be removed here.
139  if (!OtherReference && BlockChanged) {
140  PredToRemove.push_back(*PI);
141  }
142 
143  if (BlockChanged)
144  Changed = true;
145  }
146 
147  for (unsigned i = 0, ie = PredToRemove.size(); i != ie; ++i)
148  PredToRemove[i]->removeSuccessor(&ReturnMBB, true);
149 
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);
159  }
160  }
161 
162  if (ReturnMBB.pred_empty())
163  ReturnMBB.eraseFromParent();
164  }
165 
166  return Changed;
167  }
168 
169 public:
170  bool runOnMachineFunction(MachineFunction &MF) override {
171  if (skipFunction(MF.getFunction()))
172  return false;
173 
174  TII = MF.getSubtarget().getInstrInfo();
175 
176  bool Changed = false;
177 
178  // If the function does not have at least two blocks, then there is
179  // nothing to do.
180  if (MF.size() < 2)
181  return Changed;
182 
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);
187  }
188 
189  return Changed;
190  }
191 
192  MachineFunctionProperties getRequiredProperties() const override {
195  }
196 
197  void getAnalysisUsage(AnalysisUsage &AU) const override {
199  }
200  };
201 }
202 
203 INITIALIZE_PASS(PPCEarlyReturn, DEBUG_TYPE,
204  "PowerPC Early-Return Creation", false, false)
205 
206 char PPCEarlyReturn::ID = 0;
208 llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
#define DEBUG_TYPE
unsigned size() const
STATISTIC(NumFunctions, "Total number of functions")
void eraseFromParent()
This method unlinks &#39;this&#39; from the containing function and deletes it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
iterator getLastNonDebugInstr()
Returns an iterator to the last non-debug instruction in the basic block, or end().
virtual const TargetInstrInfo * getInstrInfo() const
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
FunctionPass * createPPCEarlyReturnPass()
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
std::vector< MachineBasicBlock * >::iterator pred_iterator
bool hasAddressTaken() const
Test whether this block is potentially the target of an indirect branch.
size_t size() const
Definition: SmallVector.h:52
void initializePPCEarlyReturnPass(PassRegistry &)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:33
Iterator for intrusive lists based on ilist_node.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
unsigned pred_size() const
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
const Function & getFunction() const
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
MachineFunctionProperties & set(Property P)
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB &#39;Other&#39; at the position From, and insert it into this MBB right before &#39;...
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:44
#define I(x, y, z)
Definition: MD5.cpp:58
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
iterator SkipPHIsLabelsAndDebug(iterator I)
Return the first instruction in MBB after I that is not a PHI, label or debug.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Properties which a MachineFunction may have at a given point in time.