[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / PowerPC / PPCEarlyReturn.cpp
blob08b7bdb3ac1e2632cd62bc799c7ddb410fa88f3e
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.
12 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/PPCPredicates.h"
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"
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"
33 using namespace llvm;
35 #define DEBUG_TYPE "ppc-early-ret"
36 STATISTIC(NumBCLR, "Number of early conditional returns");
37 STATISTIC(NumBLR, "Number of early returns");
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) {
46 initializePPCEarlyReturnPass(*PassRegistry::getPassRegistry());
49 const TargetInstrInfo *TII;
51 protected:
52 bool processBlock(MachineBasicBlock &ReturnMBB) {
53 bool Changed = false;
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())
62 return Changed;
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;
69 if ((*PI)->empty())
70 continue;
72 for (MachineBasicBlock::iterator J = (*PI)->getLastNonDebugInstr();;) {
73 if (J == (*PI)->end())
74 break;
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 MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);
81 (*PI)->insert(J, MI);
83 MachineBasicBlock::iterator K = J--;
84 K->eraseFromParent();
85 BlockChanged = true;
86 ++NumBLR;
87 continue;
89 } else if (J->getOpcode() == PPC::BCC) {
90 if (J->getOperand(2).getMBB() == &ReturnMBB) {
91 // This is a conditional branch to the return. Replace the branch
92 // with a bclr.
93 MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);
94 MI->setDesc(TII->get(PPC::BCCLR));
95 MachineInstrBuilder(*ReturnMBB.getParent(), MI)
96 .add(J->getOperand(0))
97 .add(J->getOperand(1));
98 (*PI)->insert(J, MI);
100 MachineBasicBlock::iterator K = J--;
101 K->eraseFromParent();
102 BlockChanged = true;
103 ++NumBCLR;
104 continue;
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
109 // with a bclr.
110 MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I);
111 MI->setDesc(
112 TII->get(J->getOpcode() == PPC::BC ? PPC::BCLR : PPC::BCLRn));
113 MachineInstrBuilder(*ReturnMBB.getParent(), MI)
114 .add(J->getOperand(0));
115 (*PI)->insert(J, MI);
117 MachineBasicBlock::iterator K = J--;
118 K->eraseFromParent();
119 BlockChanged = true;
120 ++NumBCLR;
121 continue;
123 } else if (J->isBranch()) {
124 if (J->isIndirectBranch()) {
125 if (ReturnMBB.hasAddressTaken())
126 OtherReference = true;
127 } else
128 for (unsigned i = 0; i < J->getNumOperands(); ++i)
129 if (J->getOperand(i).isMBB() &&
130 J->getOperand(i).getMBB() == &ReturnMBB)
131 OtherReference = true;
132 } else if (!J->isTerminator() && !J->isDebugInstr())
133 break;
135 if (J == (*PI)->begin())
136 break;
138 --J;
141 if ((*PI)->canFallThrough() && (*PI)->isLayoutSuccessor(&ReturnMBB))
142 OtherReference = true;
144 // Predecessors are stored in a vector and can't be removed here.
145 if (!OtherReference && BlockChanged) {
146 PredToRemove.push_back(*PI);
149 if (BlockChanged)
150 Changed = true;
153 for (unsigned i = 0, ie = PredToRemove.size(); i != ie; ++i)
154 PredToRemove[i]->removeSuccessor(&ReturnMBB, true);
156 if (Changed && !ReturnMBB.hasAddressTaken()) {
157 // We now might be able to merge this blr-only block into its
158 // by-layout predecessor.
159 if (ReturnMBB.pred_size() == 1) {
160 MachineBasicBlock &PrevMBB = **ReturnMBB.pred_begin();
161 if (PrevMBB.isLayoutSuccessor(&ReturnMBB) && PrevMBB.canFallThrough()) {
162 // Move the blr into the preceding block.
163 PrevMBB.splice(PrevMBB.end(), &ReturnMBB, I);
164 PrevMBB.removeSuccessor(&ReturnMBB, true);
168 if (ReturnMBB.pred_empty())
169 ReturnMBB.eraseFromParent();
172 return Changed;
175 public:
176 bool runOnMachineFunction(MachineFunction &MF) override {
177 if (skipFunction(MF.getFunction()))
178 return false;
180 TII = MF.getSubtarget().getInstrInfo();
182 bool Changed = false;
184 // If the function does not have at least two blocks, then there is
185 // nothing to do.
186 if (MF.size() < 2)
187 return Changed;
189 // We can't use a range-based for loop due to clobbering the iterator.
190 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E;) {
191 MachineBasicBlock &B = *I++;
192 Changed |= processBlock(B);
195 return Changed;
198 MachineFunctionProperties getRequiredProperties() const override {
199 return MachineFunctionProperties().set(
200 MachineFunctionProperties::Property::NoVRegs);
203 void getAnalysisUsage(AnalysisUsage &AU) const override {
204 MachineFunctionPass::getAnalysisUsage(AU);
209 INITIALIZE_PASS(PPCEarlyReturn, DEBUG_TYPE,
210 "PowerPC Early-Return Creation", false, false)
212 char PPCEarlyReturn::ID = 0;
213 FunctionPass*
214 llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }