xref: /aosp_15_r20/external/llvm/lib/Target/MSP430/MSP430BranchSelector.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- MSP430BranchSelector.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 10 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 "MSP430.h"
19*9880d681SAndroid Build Coastguard Worker #include "MSP430InstrInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "MSP430Subtarget.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.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 using namespace llvm;
27*9880d681SAndroid Build Coastguard Worker 
28*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "msp430-branch-select"
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker STATISTIC(NumExpanded, "Number of branches expanded to long format");
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker namespace {
33*9880d681SAndroid Build Coastguard Worker   struct MSP430BSel : public MachineFunctionPass {
34*9880d681SAndroid Build Coastguard Worker     static char ID;
MSP430BSel__anon707adaea0111::MSP430BSel35*9880d681SAndroid Build Coastguard Worker     MSP430BSel() : MachineFunctionPass(ID) {}
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker     /// BlockSizes - The sizes of the basic blocks in the function.
38*9880d681SAndroid Build Coastguard Worker     std::vector<unsigned> BlockSizes;
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker     bool runOnMachineFunction(MachineFunction &Fn) override;
41*9880d681SAndroid Build Coastguard Worker 
getRequiredProperties__anon707adaea0111::MSP430BSel42*9880d681SAndroid Build Coastguard Worker     MachineFunctionProperties getRequiredProperties() const override {
43*9880d681SAndroid Build Coastguard Worker       return MachineFunctionProperties().set(
44*9880d681SAndroid Build Coastguard Worker           MachineFunctionProperties::Property::AllVRegsAllocated);
45*9880d681SAndroid Build Coastguard Worker     }
46*9880d681SAndroid Build Coastguard Worker 
getPassName__anon707adaea0111::MSP430BSel47*9880d681SAndroid Build Coastguard Worker     const char *getPassName() const override {
48*9880d681SAndroid Build Coastguard Worker       return "MSP430 Branch Selector";
49*9880d681SAndroid Build Coastguard Worker     }
50*9880d681SAndroid Build Coastguard Worker   };
51*9880d681SAndroid Build Coastguard Worker   char MSP430BSel::ID = 0;
52*9880d681SAndroid Build Coastguard Worker }
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker /// createMSP430BranchSelectionPass - returns an instance of the Branch
55*9880d681SAndroid Build Coastguard Worker /// Selection Pass
56*9880d681SAndroid Build Coastguard Worker ///
createMSP430BranchSelectionPass()57*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createMSP430BranchSelectionPass() {
58*9880d681SAndroid Build Coastguard Worker   return new MSP430BSel();
59*9880d681SAndroid Build Coastguard Worker }
60*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & Fn)61*9880d681SAndroid Build Coastguard Worker bool MSP430BSel::runOnMachineFunction(MachineFunction &Fn) {
62*9880d681SAndroid Build Coastguard Worker   const MSP430InstrInfo *TII =
63*9880d681SAndroid Build Coastguard Worker       static_cast<const MSP430InstrInfo *>(Fn.getSubtarget().getInstrInfo());
64*9880d681SAndroid Build Coastguard Worker   // Give the blocks of the function a dense, in-order, numbering.
65*9880d681SAndroid Build Coastguard Worker   Fn.RenumberBlocks();
66*9880d681SAndroid Build Coastguard Worker   BlockSizes.resize(Fn.getNumBlockIDs());
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker   // Measure each MBB and compute a size for the entire function.
69*9880d681SAndroid Build Coastguard Worker   unsigned FuncSize = 0;
70*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock &MBB : Fn) {
71*9880d681SAndroid Build Coastguard Worker     unsigned BlockSize = 0;
72*9880d681SAndroid Build Coastguard Worker     for (MachineInstr &MI : MBB)
73*9880d681SAndroid Build Coastguard Worker       BlockSize += TII->GetInstSizeInBytes(MI);
74*9880d681SAndroid Build Coastguard Worker 
75*9880d681SAndroid Build Coastguard Worker     BlockSizes[MBB.getNumber()] = BlockSize;
76*9880d681SAndroid Build Coastguard Worker     FuncSize += BlockSize;
77*9880d681SAndroid Build Coastguard Worker   }
78*9880d681SAndroid Build Coastguard Worker 
79*9880d681SAndroid Build Coastguard Worker   // If the entire function is smaller than the displacement of a branch field,
80*9880d681SAndroid Build Coastguard Worker   // we know we don't need to shrink any branches in this function.  This is a
81*9880d681SAndroid Build Coastguard Worker   // common case.
82*9880d681SAndroid Build Coastguard Worker   if (FuncSize < (1 << 9)) {
83*9880d681SAndroid Build Coastguard Worker     BlockSizes.clear();
84*9880d681SAndroid Build Coastguard Worker     return false;
85*9880d681SAndroid Build Coastguard Worker   }
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker   // For each conditional branch, if the offset to its destination is larger
88*9880d681SAndroid Build Coastguard Worker   // than the offset field allows, transform it into a long branch sequence
89*9880d681SAndroid Build Coastguard Worker   // like this:
90*9880d681SAndroid Build Coastguard Worker   //   short branch:
91*9880d681SAndroid Build Coastguard Worker   //     bCC MBB
92*9880d681SAndroid Build Coastguard Worker   //   long branch:
93*9880d681SAndroid Build Coastguard Worker   //     b!CC $PC+6
94*9880d681SAndroid Build Coastguard Worker   //     b MBB
95*9880d681SAndroid Build Coastguard Worker   //
96*9880d681SAndroid Build Coastguard Worker   bool MadeChange = true;
97*9880d681SAndroid Build Coastguard Worker   bool EverMadeChange = false;
98*9880d681SAndroid Build Coastguard Worker   while (MadeChange) {
99*9880d681SAndroid Build Coastguard Worker     // Iteratively expand branches until we reach a fixed point.
100*9880d681SAndroid Build Coastguard Worker     MadeChange = false;
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker     for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
103*9880d681SAndroid Build Coastguard Worker          ++MFI) {
104*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock &MBB = *MFI;
105*9880d681SAndroid Build Coastguard Worker       unsigned MBBStartOffset = 0;
106*9880d681SAndroid Build Coastguard Worker       for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
107*9880d681SAndroid Build Coastguard Worker            I != E; ++I) {
108*9880d681SAndroid Build Coastguard Worker         if ((I->getOpcode() != MSP430::JCC || I->getOperand(0).isImm()) &&
109*9880d681SAndroid Build Coastguard Worker             I->getOpcode() != MSP430::JMP) {
110*9880d681SAndroid Build Coastguard Worker           MBBStartOffset += TII->GetInstSizeInBytes(*I);
111*9880d681SAndroid Build Coastguard Worker           continue;
112*9880d681SAndroid Build Coastguard Worker         }
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker         // Determine the offset from the current branch to the destination
115*9880d681SAndroid Build Coastguard Worker         // block.
116*9880d681SAndroid Build Coastguard Worker         MachineBasicBlock *Dest = I->getOperand(0).getMBB();
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker         int BranchSize;
119*9880d681SAndroid Build Coastguard Worker         if (Dest->getNumber() <= MBB.getNumber()) {
120*9880d681SAndroid Build Coastguard Worker           // If this is a backwards branch, the delta is the offset from the
121*9880d681SAndroid Build Coastguard Worker           // start of this block to this branch, plus the sizes of all blocks
122*9880d681SAndroid Build Coastguard Worker           // from this block to the dest.
123*9880d681SAndroid Build Coastguard Worker           BranchSize = MBBStartOffset;
124*9880d681SAndroid Build Coastguard Worker 
125*9880d681SAndroid Build Coastguard Worker           for (unsigned i = Dest->getNumber(), e = MBB.getNumber(); i != e; ++i)
126*9880d681SAndroid Build Coastguard Worker             BranchSize += BlockSizes[i];
127*9880d681SAndroid Build Coastguard Worker         } else {
128*9880d681SAndroid Build Coastguard Worker           // Otherwise, add the size of the blocks between this block and the
129*9880d681SAndroid Build Coastguard Worker           // dest to the number of bytes left in this block.
130*9880d681SAndroid Build Coastguard Worker           BranchSize = -MBBStartOffset;
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker           for (unsigned i = MBB.getNumber(), e = Dest->getNumber(); i != e; ++i)
133*9880d681SAndroid Build Coastguard Worker             BranchSize += BlockSizes[i];
134*9880d681SAndroid Build Coastguard Worker         }
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker         // If this branch is in range, ignore it.
137*9880d681SAndroid Build Coastguard Worker         if (isInt<10>(BranchSize)) {
138*9880d681SAndroid Build Coastguard Worker           MBBStartOffset += 2;
139*9880d681SAndroid Build Coastguard Worker           continue;
140*9880d681SAndroid Build Coastguard Worker         }
141*9880d681SAndroid Build Coastguard Worker 
142*9880d681SAndroid Build Coastguard Worker         // Otherwise, we have to expand it to a long branch.
143*9880d681SAndroid Build Coastguard Worker         unsigned NewSize;
144*9880d681SAndroid Build Coastguard Worker         MachineInstr &OldBranch = *I;
145*9880d681SAndroid Build Coastguard Worker         DebugLoc dl = OldBranch.getDebugLoc();
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker         if (I->getOpcode() == MSP430::JMP) {
148*9880d681SAndroid Build Coastguard Worker           NewSize = 4;
149*9880d681SAndroid Build Coastguard Worker         } else {
150*9880d681SAndroid Build Coastguard Worker           // The BCC operands are:
151*9880d681SAndroid Build Coastguard Worker           // 0. MSP430 branch predicate
152*9880d681SAndroid Build Coastguard Worker           // 1. Target MBB
153*9880d681SAndroid Build Coastguard Worker           SmallVector<MachineOperand, 1> Cond;
154*9880d681SAndroid Build Coastguard Worker           Cond.push_back(I->getOperand(1));
155*9880d681SAndroid Build Coastguard Worker 
156*9880d681SAndroid Build Coastguard Worker           // Jump over the uncond branch inst (i.e. $+6) on opposite condition.
157*9880d681SAndroid Build Coastguard Worker           TII->ReverseBranchCondition(Cond);
158*9880d681SAndroid Build Coastguard Worker           BuildMI(MBB, I, dl, TII->get(MSP430::JCC))
159*9880d681SAndroid Build Coastguard Worker             .addImm(4).addOperand(Cond[0]);
160*9880d681SAndroid Build Coastguard Worker 
161*9880d681SAndroid Build Coastguard Worker           NewSize = 6;
162*9880d681SAndroid Build Coastguard Worker         }
163*9880d681SAndroid Build Coastguard Worker         // Uncond branch to the real destination.
164*9880d681SAndroid Build Coastguard Worker         I = BuildMI(MBB, I, dl, TII->get(MSP430::Bi)).addMBB(Dest);
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker         // Remove the old branch from the function.
167*9880d681SAndroid Build Coastguard Worker         OldBranch.eraseFromParent();
168*9880d681SAndroid Build Coastguard Worker 
169*9880d681SAndroid Build Coastguard Worker         // Remember that this instruction is NewSize bytes, increase the size of the
170*9880d681SAndroid Build Coastguard Worker         // block by NewSize-2, remember to iterate.
171*9880d681SAndroid Build Coastguard Worker         BlockSizes[MBB.getNumber()] += NewSize-2;
172*9880d681SAndroid Build Coastguard Worker         MBBStartOffset += NewSize;
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker         ++NumExpanded;
175*9880d681SAndroid Build Coastguard Worker         MadeChange = true;
176*9880d681SAndroid Build Coastguard Worker       }
177*9880d681SAndroid Build Coastguard Worker     }
178*9880d681SAndroid Build Coastguard Worker     EverMadeChange |= MadeChange;
179*9880d681SAndroid Build Coastguard Worker   }
180*9880d681SAndroid Build Coastguard Worker 
181*9880d681SAndroid Build Coastguard Worker   BlockSizes.clear();
182*9880d681SAndroid Build Coastguard Worker   return true;
183*9880d681SAndroid Build Coastguard Worker }
184