]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / PowerPC / PPCEarlyReturn.cpp
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
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"
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) {
46       initializePPCEarlyReturnPass(*PassRegistry::getPassRegistry());
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
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;
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);
82               MachineBasicBlock::iterator K = J--;
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);
96               MachineBasicBlock::iterator K = J--;
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);
111               MachineBasicBlock::iterator K = J--;
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 {
193       return MachineFunctionProperties().set(
194           MachineFunctionProperties::Property::NoVRegs);
195     }
196
197     void getAnalysisUsage(AnalysisUsage &AU) const override {
198       MachineFunctionPass::getAnalysisUsage(AU);
199     }
200   };
201 }
202
203 INITIALIZE_PASS(PPCEarlyReturn, DEBUG_TYPE,
204                 "PowerPC Early-Return Creation", false, false)
205
206 char PPCEarlyReturn::ID = 0;
207 FunctionPass*
208 llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }