xref: /aosp_15_r20/external/llvm/lib/Target/PowerPC/PPCBranchSelector.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- PPCBranchSelector.cpp - Emit long conditional branches ------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains a pass that scans a machine function to determine which
11*9880d681SAndroid Build Coastguard Worker // conditional branches need more than 16 bits of displacement to reach their
12*9880d681SAndroid Build Coastguard Worker // target basic block.  It does this in two passes; a calculation of basic block
13*9880d681SAndroid Build Coastguard Worker // positions pass, and a branch pseudo op to machine branch opcode pass.  This
14*9880d681SAndroid Build Coastguard Worker // pass should be run last, just before the assembly printer.
15*9880d681SAndroid Build Coastguard Worker //
16*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
17*9880d681SAndroid Build Coastguard Worker 
18*9880d681SAndroid Build Coastguard Worker #include "PPC.h"
19*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/PPCPredicates.h"
20*9880d681SAndroid Build Coastguard Worker #include "PPCInstrBuilder.h"
21*9880d681SAndroid Build Coastguard Worker #include "PPCInstrInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "ppc-branch-select"
30*9880d681SAndroid Build Coastguard Worker 
31*9880d681SAndroid Build Coastguard Worker STATISTIC(NumExpanded, "Number of branches expanded to long format");
32*9880d681SAndroid Build Coastguard Worker 
33*9880d681SAndroid Build Coastguard Worker namespace llvm {
34*9880d681SAndroid Build Coastguard Worker   void initializePPCBSelPass(PassRegistry&);
35*9880d681SAndroid Build Coastguard Worker }
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker namespace {
38*9880d681SAndroid Build Coastguard Worker   struct PPCBSel : public MachineFunctionPass {
39*9880d681SAndroid Build Coastguard Worker     static char ID;
PPCBSel__anon508a48df0111::PPCBSel40*9880d681SAndroid Build Coastguard Worker     PPCBSel() : MachineFunctionPass(ID) {
41*9880d681SAndroid Build Coastguard Worker       initializePPCBSelPass(*PassRegistry::getPassRegistry());
42*9880d681SAndroid Build Coastguard Worker     }
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker     /// BlockSizes - The sizes of the basic blocks in the function.
45*9880d681SAndroid Build Coastguard Worker     std::vector<unsigned> BlockSizes;
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker     bool runOnMachineFunction(MachineFunction &Fn) override;
48*9880d681SAndroid Build Coastguard Worker 
getRequiredProperties__anon508a48df0111::PPCBSel49*9880d681SAndroid Build Coastguard Worker     MachineFunctionProperties getRequiredProperties() const override {
50*9880d681SAndroid Build Coastguard Worker       return MachineFunctionProperties().set(
51*9880d681SAndroid Build Coastguard Worker           MachineFunctionProperties::Property::AllVRegsAllocated);
52*9880d681SAndroid Build Coastguard Worker     }
53*9880d681SAndroid Build Coastguard Worker 
getPassName__anon508a48df0111::PPCBSel54*9880d681SAndroid Build Coastguard Worker     const char *getPassName() const override {
55*9880d681SAndroid Build Coastguard Worker       return "PowerPC Branch Selector";
56*9880d681SAndroid Build Coastguard Worker     }
57*9880d681SAndroid Build Coastguard Worker   };
58*9880d681SAndroid Build Coastguard Worker   char PPCBSel::ID = 0;
59*9880d681SAndroid Build Coastguard Worker }
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(PPCBSel, "ppc-branch-select", "PowerPC Branch Selector",
62*9880d681SAndroid Build Coastguard Worker                 false, false)
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker /// createPPCBranchSelectionPass - returns an instance of the Branch Selection
65*9880d681SAndroid Build Coastguard Worker /// Pass
66*9880d681SAndroid Build Coastguard Worker ///
createPPCBranchSelectionPass()67*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createPPCBranchSelectionPass() {
68*9880d681SAndroid Build Coastguard Worker   return new PPCBSel();
69*9880d681SAndroid Build Coastguard Worker }
70*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & Fn)71*9880d681SAndroid Build Coastguard Worker bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
72*9880d681SAndroid Build Coastguard Worker   const PPCInstrInfo *TII =
73*9880d681SAndroid Build Coastguard Worker       static_cast<const PPCInstrInfo *>(Fn.getSubtarget().getInstrInfo());
74*9880d681SAndroid Build Coastguard Worker   // Give the blocks of the function a dense, in-order, numbering.
75*9880d681SAndroid Build Coastguard Worker   Fn.RenumberBlocks();
76*9880d681SAndroid Build Coastguard Worker   BlockSizes.resize(Fn.getNumBlockIDs());
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker   auto GetAlignmentAdjustment =
79*9880d681SAndroid Build Coastguard Worker     [TII](MachineBasicBlock &MBB, unsigned Offset) -> unsigned {
80*9880d681SAndroid Build Coastguard Worker     unsigned Align = MBB.getAlignment();
81*9880d681SAndroid Build Coastguard Worker     if (!Align)
82*9880d681SAndroid Build Coastguard Worker       return 0;
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker     unsigned AlignAmt = 1 << Align;
85*9880d681SAndroid Build Coastguard Worker     unsigned ParentAlign = MBB.getParent()->getAlignment();
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker     if (Align <= ParentAlign)
88*9880d681SAndroid Build Coastguard Worker       return OffsetToAlignment(Offset, AlignAmt);
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker     // The alignment of this MBB is larger than the function's alignment, so we
91*9880d681SAndroid Build Coastguard Worker     // can't tell whether or not it will insert nops. Assume that it will.
92*9880d681SAndroid Build Coastguard Worker     return AlignAmt + OffsetToAlignment(Offset, AlignAmt);
93*9880d681SAndroid Build Coastguard Worker   };
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker   // Measure each MBB and compute a size for the entire function.
96*9880d681SAndroid Build Coastguard Worker   unsigned FuncSize = 0;
97*9880d681SAndroid Build Coastguard Worker   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
98*9880d681SAndroid Build Coastguard Worker        ++MFI) {
99*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB = &*MFI;
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker     // The end of the previous block may have extra nops if this block has an
102*9880d681SAndroid Build Coastguard Worker     // alignment requirement.
103*9880d681SAndroid Build Coastguard Worker     if (MBB->getNumber() > 0) {
104*9880d681SAndroid Build Coastguard Worker       unsigned AlignExtra = GetAlignmentAdjustment(*MBB, FuncSize);
105*9880d681SAndroid Build Coastguard Worker       BlockSizes[MBB->getNumber()-1] += AlignExtra;
106*9880d681SAndroid Build Coastguard Worker       FuncSize += AlignExtra;
107*9880d681SAndroid Build Coastguard Worker     }
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker     unsigned BlockSize = 0;
110*9880d681SAndroid Build Coastguard Worker     for (MachineInstr &MI : *MBB)
111*9880d681SAndroid Build Coastguard Worker       BlockSize += TII->GetInstSizeInBytes(MI);
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker     BlockSizes[MBB->getNumber()] = BlockSize;
114*9880d681SAndroid Build Coastguard Worker     FuncSize += BlockSize;
115*9880d681SAndroid Build Coastguard Worker   }
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker   // If the entire function is smaller than the displacement of a branch field,
118*9880d681SAndroid Build Coastguard Worker   // we know we don't need to shrink any branches in this function.  This is a
119*9880d681SAndroid Build Coastguard Worker   // common case.
120*9880d681SAndroid Build Coastguard Worker   if (FuncSize < (1 << 15)) {
121*9880d681SAndroid Build Coastguard Worker     BlockSizes.clear();
122*9880d681SAndroid Build Coastguard Worker     return false;
123*9880d681SAndroid Build Coastguard Worker   }
124*9880d681SAndroid Build Coastguard Worker 
125*9880d681SAndroid Build Coastguard Worker   // For each conditional branch, if the offset to its destination is larger
126*9880d681SAndroid Build Coastguard Worker   // than the offset field allows, transform it into a long branch sequence
127*9880d681SAndroid Build Coastguard Worker   // like this:
128*9880d681SAndroid Build Coastguard Worker   //   short branch:
129*9880d681SAndroid Build Coastguard Worker   //     bCC MBB
130*9880d681SAndroid Build Coastguard Worker   //   long branch:
131*9880d681SAndroid Build Coastguard Worker   //     b!CC $PC+8
132*9880d681SAndroid Build Coastguard Worker   //     b MBB
133*9880d681SAndroid Build Coastguard Worker   //
134*9880d681SAndroid Build Coastguard Worker   bool MadeChange = true;
135*9880d681SAndroid Build Coastguard Worker   bool EverMadeChange = false;
136*9880d681SAndroid Build Coastguard Worker   while (MadeChange) {
137*9880d681SAndroid Build Coastguard Worker     // Iteratively expand branches until we reach a fixed point.
138*9880d681SAndroid Build Coastguard Worker     MadeChange = false;
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker     for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
141*9880d681SAndroid Build Coastguard Worker          ++MFI) {
142*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock &MBB = *MFI;
143*9880d681SAndroid Build Coastguard Worker       unsigned MBBStartOffset = 0;
144*9880d681SAndroid Build Coastguard Worker       for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
145*9880d681SAndroid Build Coastguard Worker            I != E; ++I) {
146*9880d681SAndroid Build Coastguard Worker         MachineBasicBlock *Dest = nullptr;
147*9880d681SAndroid Build Coastguard Worker         if (I->getOpcode() == PPC::BCC && !I->getOperand(2).isImm())
148*9880d681SAndroid Build Coastguard Worker           Dest = I->getOperand(2).getMBB();
149*9880d681SAndroid Build Coastguard Worker         else if ((I->getOpcode() == PPC::BC || I->getOpcode() == PPC::BCn) &&
150*9880d681SAndroid Build Coastguard Worker                  !I->getOperand(1).isImm())
151*9880d681SAndroid Build Coastguard Worker           Dest = I->getOperand(1).getMBB();
152*9880d681SAndroid Build Coastguard Worker         else if ((I->getOpcode() == PPC::BDNZ8 || I->getOpcode() == PPC::BDNZ ||
153*9880d681SAndroid Build Coastguard Worker                   I->getOpcode() == PPC::BDZ8  || I->getOpcode() == PPC::BDZ) &&
154*9880d681SAndroid Build Coastguard Worker                  !I->getOperand(0).isImm())
155*9880d681SAndroid Build Coastguard Worker           Dest = I->getOperand(0).getMBB();
156*9880d681SAndroid Build Coastguard Worker 
157*9880d681SAndroid Build Coastguard Worker         if (!Dest) {
158*9880d681SAndroid Build Coastguard Worker           MBBStartOffset += TII->GetInstSizeInBytes(*I);
159*9880d681SAndroid Build Coastguard Worker           continue;
160*9880d681SAndroid Build Coastguard Worker         }
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker         // Determine the offset from the current branch to the destination
163*9880d681SAndroid Build Coastguard Worker         // block.
164*9880d681SAndroid Build Coastguard Worker         int BranchSize;
165*9880d681SAndroid Build Coastguard Worker         if (Dest->getNumber() <= MBB.getNumber()) {
166*9880d681SAndroid Build Coastguard Worker           // If this is a backwards branch, the delta is the offset from the
167*9880d681SAndroid Build Coastguard Worker           // start of this block to this branch, plus the sizes of all blocks
168*9880d681SAndroid Build Coastguard Worker           // from this block to the dest.
169*9880d681SAndroid Build Coastguard Worker           BranchSize = MBBStartOffset;
170*9880d681SAndroid Build Coastguard Worker 
171*9880d681SAndroid Build Coastguard Worker           for (unsigned i = Dest->getNumber(), e = MBB.getNumber(); i != e; ++i)
172*9880d681SAndroid Build Coastguard Worker             BranchSize += BlockSizes[i];
173*9880d681SAndroid Build Coastguard Worker         } else {
174*9880d681SAndroid Build Coastguard Worker           // Otherwise, add the size of the blocks between this block and the
175*9880d681SAndroid Build Coastguard Worker           // dest to the number of bytes left in this block.
176*9880d681SAndroid Build Coastguard Worker           BranchSize = -MBBStartOffset;
177*9880d681SAndroid Build Coastguard Worker 
178*9880d681SAndroid Build Coastguard Worker           for (unsigned i = MBB.getNumber(), e = Dest->getNumber(); i != e; ++i)
179*9880d681SAndroid Build Coastguard Worker             BranchSize += BlockSizes[i];
180*9880d681SAndroid Build Coastguard Worker         }
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker         // If this branch is in range, ignore it.
183*9880d681SAndroid Build Coastguard Worker         if (isInt<16>(BranchSize)) {
184*9880d681SAndroid Build Coastguard Worker           MBBStartOffset += 4;
185*9880d681SAndroid Build Coastguard Worker           continue;
186*9880d681SAndroid Build Coastguard Worker         }
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker         // Otherwise, we have to expand it to a long branch.
189*9880d681SAndroid Build Coastguard Worker         MachineInstr *OldBranch = I;
190*9880d681SAndroid Build Coastguard Worker         DebugLoc dl = OldBranch->getDebugLoc();
191*9880d681SAndroid Build Coastguard Worker 
192*9880d681SAndroid Build Coastguard Worker         if (I->getOpcode() == PPC::BCC) {
193*9880d681SAndroid Build Coastguard Worker           // The BCC operands are:
194*9880d681SAndroid Build Coastguard Worker           // 0. PPC branch predicate
195*9880d681SAndroid Build Coastguard Worker           // 1. CR register
196*9880d681SAndroid Build Coastguard Worker           // 2. Target MBB
197*9880d681SAndroid Build Coastguard Worker           PPC::Predicate Pred = (PPC::Predicate)I->getOperand(0).getImm();
198*9880d681SAndroid Build Coastguard Worker           unsigned CRReg = I->getOperand(1).getReg();
199*9880d681SAndroid Build Coastguard Worker 
200*9880d681SAndroid Build Coastguard Worker           // Jump over the uncond branch inst (i.e. $PC+8) on opposite condition.
201*9880d681SAndroid Build Coastguard Worker           BuildMI(MBB, I, dl, TII->get(PPC::BCC))
202*9880d681SAndroid Build Coastguard Worker             .addImm(PPC::InvertPredicate(Pred)).addReg(CRReg).addImm(2);
203*9880d681SAndroid Build Coastguard Worker         } else if (I->getOpcode() == PPC::BC) {
204*9880d681SAndroid Build Coastguard Worker           unsigned CRBit = I->getOperand(0).getReg();
205*9880d681SAndroid Build Coastguard Worker           BuildMI(MBB, I, dl, TII->get(PPC::BCn)).addReg(CRBit).addImm(2);
206*9880d681SAndroid Build Coastguard Worker         } else if (I->getOpcode() == PPC::BCn) {
207*9880d681SAndroid Build Coastguard Worker           unsigned CRBit = I->getOperand(0).getReg();
208*9880d681SAndroid Build Coastguard Worker           BuildMI(MBB, I, dl, TII->get(PPC::BC)).addReg(CRBit).addImm(2);
209*9880d681SAndroid Build Coastguard Worker         } else if (I->getOpcode() == PPC::BDNZ) {
210*9880d681SAndroid Build Coastguard Worker           BuildMI(MBB, I, dl, TII->get(PPC::BDZ)).addImm(2);
211*9880d681SAndroid Build Coastguard Worker         } else if (I->getOpcode() == PPC::BDNZ8) {
212*9880d681SAndroid Build Coastguard Worker           BuildMI(MBB, I, dl, TII->get(PPC::BDZ8)).addImm(2);
213*9880d681SAndroid Build Coastguard Worker         } else if (I->getOpcode() == PPC::BDZ) {
214*9880d681SAndroid Build Coastguard Worker           BuildMI(MBB, I, dl, TII->get(PPC::BDNZ)).addImm(2);
215*9880d681SAndroid Build Coastguard Worker         } else if (I->getOpcode() == PPC::BDZ8) {
216*9880d681SAndroid Build Coastguard Worker           BuildMI(MBB, I, dl, TII->get(PPC::BDNZ8)).addImm(2);
217*9880d681SAndroid Build Coastguard Worker         } else {
218*9880d681SAndroid Build Coastguard Worker            llvm_unreachable("Unhandled branch type!");
219*9880d681SAndroid Build Coastguard Worker         }
220*9880d681SAndroid Build Coastguard Worker 
221*9880d681SAndroid Build Coastguard Worker         // Uncond branch to the real destination.
222*9880d681SAndroid Build Coastguard Worker         I = BuildMI(MBB, I, dl, TII->get(PPC::B)).addMBB(Dest);
223*9880d681SAndroid Build Coastguard Worker 
224*9880d681SAndroid Build Coastguard Worker         // Remove the old branch from the function.
225*9880d681SAndroid Build Coastguard Worker         OldBranch->eraseFromParent();
226*9880d681SAndroid Build Coastguard Worker 
227*9880d681SAndroid Build Coastguard Worker         // Remember that this instruction is 8-bytes, increase the size of the
228*9880d681SAndroid Build Coastguard Worker         // block by 4, remember to iterate.
229*9880d681SAndroid Build Coastguard Worker         BlockSizes[MBB.getNumber()] += 4;
230*9880d681SAndroid Build Coastguard Worker         MBBStartOffset += 8;
231*9880d681SAndroid Build Coastguard Worker         ++NumExpanded;
232*9880d681SAndroid Build Coastguard Worker         MadeChange = true;
233*9880d681SAndroid Build Coastguard Worker       }
234*9880d681SAndroid Build Coastguard Worker     }
235*9880d681SAndroid Build Coastguard Worker     EverMadeChange |= MadeChange;
236*9880d681SAndroid Build Coastguard Worker   }
237*9880d681SAndroid Build Coastguard Worker 
238*9880d681SAndroid Build Coastguard Worker   BlockSizes.clear();
239*9880d681SAndroid Build Coastguard Worker   return true;
240*9880d681SAndroid Build Coastguard Worker }
241