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