xref: /aosp_15_r20/external/llvm/lib/Target/AArch64/AArch64BranchRelaxation.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- AArch64BranchRelaxation.cpp - AArch64 branch relaxation -----------===//
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 //===----------------------------------------------------------------------===//
11*9880d681SAndroid Build Coastguard Worker 
12*9880d681SAndroid Build Coastguard Worker #include "AArch64.h"
13*9880d681SAndroid Build Coastguard Worker #include "AArch64InstrInfo.h"
14*9880d681SAndroid Build Coastguard Worker #include "AArch64MachineFunctionInfo.h"
15*9880d681SAndroid Build Coastguard Worker #include "AArch64Subtarget.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
25*9880d681SAndroid Build Coastguard Worker using namespace llvm;
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "aarch64-branch-relax"
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
30*9880d681SAndroid Build Coastguard Worker BranchRelaxation("aarch64-branch-relax", cl::Hidden, cl::init(true),
31*9880d681SAndroid Build Coastguard Worker                  cl::desc("Relax out of range conditional branches"));
32*9880d681SAndroid Build Coastguard Worker 
33*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned>
34*9880d681SAndroid Build Coastguard Worker TBZDisplacementBits("aarch64-tbz-offset-bits", cl::Hidden, cl::init(14),
35*9880d681SAndroid Build Coastguard Worker                     cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"));
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned>
38*9880d681SAndroid Build Coastguard Worker CBZDisplacementBits("aarch64-cbz-offset-bits", cl::Hidden, cl::init(19),
39*9880d681SAndroid Build Coastguard Worker                     cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"));
40*9880d681SAndroid Build Coastguard Worker 
41*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned>
42*9880d681SAndroid Build Coastguard Worker BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19),
43*9880d681SAndroid Build Coastguard Worker                     cl::desc("Restrict range of Bcc instructions (DEBUG)"));
44*9880d681SAndroid Build Coastguard Worker 
45*9880d681SAndroid Build Coastguard Worker STATISTIC(NumSplit, "Number of basic blocks split");
46*9880d681SAndroid Build Coastguard Worker STATISTIC(NumRelaxed, "Number of conditional branches relaxed");
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker namespace llvm {
49*9880d681SAndroid Build Coastguard Worker void initializeAArch64BranchRelaxationPass(PassRegistry &);
50*9880d681SAndroid Build Coastguard Worker }
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker #define AARCH64_BR_RELAX_NAME "AArch64 branch relaxation pass"
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker namespace {
55*9880d681SAndroid Build Coastguard Worker class AArch64BranchRelaxation : public MachineFunctionPass {
56*9880d681SAndroid Build Coastguard Worker   /// BasicBlockInfo - Information about the offset and size of a single
57*9880d681SAndroid Build Coastguard Worker   /// basic block.
58*9880d681SAndroid Build Coastguard Worker   struct BasicBlockInfo {
59*9880d681SAndroid Build Coastguard Worker     /// Offset - Distance from the beginning of the function to the beginning
60*9880d681SAndroid Build Coastguard Worker     /// of this basic block.
61*9880d681SAndroid Build Coastguard Worker     ///
62*9880d681SAndroid Build Coastguard Worker     /// The offset is always aligned as required by the basic block.
63*9880d681SAndroid Build Coastguard Worker     unsigned Offset;
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker     /// Size - Size of the basic block in bytes.  If the block contains
66*9880d681SAndroid Build Coastguard Worker     /// inline assembly, this is a worst case estimate.
67*9880d681SAndroid Build Coastguard Worker     ///
68*9880d681SAndroid Build Coastguard Worker     /// The size does not include any alignment padding whether from the
69*9880d681SAndroid Build Coastguard Worker     /// beginning of the block, or from an aligned jump table at the end.
70*9880d681SAndroid Build Coastguard Worker     unsigned Size;
71*9880d681SAndroid Build Coastguard Worker 
BasicBlockInfo__anon8862e7c40111::AArch64BranchRelaxation::BasicBlockInfo72*9880d681SAndroid Build Coastguard Worker     BasicBlockInfo() : Offset(0), Size(0) {}
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker     /// Compute the offset immediately following this block.  If LogAlign is
75*9880d681SAndroid Build Coastguard Worker     /// specified, return the offset the successor block will get if it has
76*9880d681SAndroid Build Coastguard Worker     /// this alignment.
postOffset__anon8862e7c40111::AArch64BranchRelaxation::BasicBlockInfo77*9880d681SAndroid Build Coastguard Worker     unsigned postOffset(unsigned LogAlign = 0) const {
78*9880d681SAndroid Build Coastguard Worker       unsigned PO = Offset + Size;
79*9880d681SAndroid Build Coastguard Worker       unsigned Align = 1 << LogAlign;
80*9880d681SAndroid Build Coastguard Worker       return (PO + Align - 1) / Align * Align;
81*9880d681SAndroid Build Coastguard Worker     }
82*9880d681SAndroid Build Coastguard Worker   };
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker   SmallVector<BasicBlockInfo, 16> BlockInfo;
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF;
87*9880d681SAndroid Build Coastguard Worker   const AArch64InstrInfo *TII;
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker   bool relaxBranchInstructions();
90*9880d681SAndroid Build Coastguard Worker   void scanFunction();
91*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI);
92*9880d681SAndroid Build Coastguard Worker   void adjustBlockOffsets(MachineBasicBlock &MBB);
93*9880d681SAndroid Build Coastguard Worker   bool isBlockInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);
94*9880d681SAndroid Build Coastguard Worker   bool fixupConditionalBranch(MachineInstr *MI);
95*9880d681SAndroid Build Coastguard Worker   void computeBlockSize(const MachineBasicBlock &MBB);
96*9880d681SAndroid Build Coastguard Worker   unsigned getInstrOffset(MachineInstr *MI) const;
97*9880d681SAndroid Build Coastguard Worker   void dumpBBs();
98*9880d681SAndroid Build Coastguard Worker   void verify();
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker public:
101*9880d681SAndroid Build Coastguard Worker   static char ID;
AArch64BranchRelaxation()102*9880d681SAndroid Build Coastguard Worker   AArch64BranchRelaxation() : MachineFunctionPass(ID) {
103*9880d681SAndroid Build Coastguard Worker     initializeAArch64BranchRelaxationPass(*PassRegistry::getPassRegistry());
104*9880d681SAndroid Build Coastguard Worker   }
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker   bool runOnMachineFunction(MachineFunction &MF) override;
107*9880d681SAndroid Build Coastguard Worker 
getPassName() const108*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override {
109*9880d681SAndroid Build Coastguard Worker     return AARCH64_BR_RELAX_NAME;
110*9880d681SAndroid Build Coastguard Worker   }
111*9880d681SAndroid Build Coastguard Worker };
112*9880d681SAndroid Build Coastguard Worker char AArch64BranchRelaxation::ID = 0;
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(AArch64BranchRelaxation, "aarch64-branch-relax",
116*9880d681SAndroid Build Coastguard Worker                 AARCH64_BR_RELAX_NAME, false, false)
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker /// verify - check BBOffsets, BBSizes, alignment of islands
verify()119*9880d681SAndroid Build Coastguard Worker void AArch64BranchRelaxation::verify() {
120*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
121*9880d681SAndroid Build Coastguard Worker   unsigned PrevNum = MF->begin()->getNumber();
122*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock &MBB : *MF) {
123*9880d681SAndroid Build Coastguard Worker     unsigned Align = MBB.getAlignment();
124*9880d681SAndroid Build Coastguard Worker     unsigned Num = MBB.getNumber();
125*9880d681SAndroid Build Coastguard Worker     assert(BlockInfo[Num].Offset % (1u << Align) == 0);
126*9880d681SAndroid Build Coastguard Worker     assert(!Num || BlockInfo[PrevNum].postOffset() <= BlockInfo[Num].Offset);
127*9880d681SAndroid Build Coastguard Worker     PrevNum = Num;
128*9880d681SAndroid Build Coastguard Worker   }
129*9880d681SAndroid Build Coastguard Worker #endif
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker /// print block size and offset information - debugging
dumpBBs()133*9880d681SAndroid Build Coastguard Worker void AArch64BranchRelaxation::dumpBBs() {
134*9880d681SAndroid Build Coastguard Worker   for (auto &MBB : *MF) {
135*9880d681SAndroid Build Coastguard Worker     const BasicBlockInfo &BBI = BlockInfo[MBB.getNumber()];
136*9880d681SAndroid Build Coastguard Worker     dbgs() << format("BB#%u\toffset=%08x\t", MBB.getNumber(), BBI.Offset)
137*9880d681SAndroid Build Coastguard Worker            << format("size=%#x\n", BBI.Size);
138*9880d681SAndroid Build Coastguard Worker   }
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker 
141*9880d681SAndroid Build Coastguard Worker /// BBHasFallthrough - Return true if the specified basic block can fallthrough
142*9880d681SAndroid Build Coastguard Worker /// into the block immediately after it.
BBHasFallthrough(MachineBasicBlock * MBB)143*9880d681SAndroid Build Coastguard Worker static bool BBHasFallthrough(MachineBasicBlock *MBB) {
144*9880d681SAndroid Build Coastguard Worker   // Get the next machine basic block in the function.
145*9880d681SAndroid Build Coastguard Worker   MachineFunction::iterator MBBI(MBB);
146*9880d681SAndroid Build Coastguard Worker   // Can't fall off end of function.
147*9880d681SAndroid Build Coastguard Worker   auto NextBB = std::next(MBBI);
148*9880d681SAndroid Build Coastguard Worker   if (NextBB == MBB->getParent()->end())
149*9880d681SAndroid Build Coastguard Worker     return false;
150*9880d681SAndroid Build Coastguard Worker 
151*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock *S : MBB->successors())
152*9880d681SAndroid Build Coastguard Worker     if (S == &*NextBB)
153*9880d681SAndroid Build Coastguard Worker       return true;
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker   return false;
156*9880d681SAndroid Build Coastguard Worker }
157*9880d681SAndroid Build Coastguard Worker 
158*9880d681SAndroid Build Coastguard Worker /// scanFunction - Do the initial scan of the function, building up
159*9880d681SAndroid Build Coastguard Worker /// information about each block.
scanFunction()160*9880d681SAndroid Build Coastguard Worker void AArch64BranchRelaxation::scanFunction() {
161*9880d681SAndroid Build Coastguard Worker   BlockInfo.clear();
162*9880d681SAndroid Build Coastguard Worker   BlockInfo.resize(MF->getNumBlockIDs());
163*9880d681SAndroid Build Coastguard Worker 
164*9880d681SAndroid Build Coastguard Worker   // First thing, compute the size of all basic blocks, and see if the function
165*9880d681SAndroid Build Coastguard Worker   // has any inline assembly in it. If so, we have to be conservative about
166*9880d681SAndroid Build Coastguard Worker   // alignment assumptions, as we don't know for sure the size of any
167*9880d681SAndroid Build Coastguard Worker   // instructions in the inline assembly.
168*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock &MBB : *MF)
169*9880d681SAndroid Build Coastguard Worker     computeBlockSize(MBB);
170*9880d681SAndroid Build Coastguard Worker 
171*9880d681SAndroid Build Coastguard Worker   // Compute block offsets and known bits.
172*9880d681SAndroid Build Coastguard Worker   adjustBlockOffsets(*MF->begin());
173*9880d681SAndroid Build Coastguard Worker }
174*9880d681SAndroid Build Coastguard Worker 
175*9880d681SAndroid Build Coastguard Worker /// computeBlockSize - Compute the size for MBB.
176*9880d681SAndroid Build Coastguard Worker /// This function updates BlockInfo directly.
computeBlockSize(const MachineBasicBlock & MBB)177*9880d681SAndroid Build Coastguard Worker void AArch64BranchRelaxation::computeBlockSize(const MachineBasicBlock &MBB) {
178*9880d681SAndroid Build Coastguard Worker   unsigned Size = 0;
179*9880d681SAndroid Build Coastguard Worker   for (const MachineInstr &MI : MBB)
180*9880d681SAndroid Build Coastguard Worker     Size += TII->GetInstSizeInBytes(MI);
181*9880d681SAndroid Build Coastguard Worker   BlockInfo[MBB.getNumber()].Size = Size;
182*9880d681SAndroid Build Coastguard Worker }
183*9880d681SAndroid Build Coastguard Worker 
184*9880d681SAndroid Build Coastguard Worker /// getInstrOffset - Return the current offset of the specified machine
185*9880d681SAndroid Build Coastguard Worker /// instruction from the start of the function.  This offset changes as stuff is
186*9880d681SAndroid Build Coastguard Worker /// moved around inside the function.
getInstrOffset(MachineInstr * MI) const187*9880d681SAndroid Build Coastguard Worker unsigned AArch64BranchRelaxation::getInstrOffset(MachineInstr *MI) const {
188*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB = MI->getParent();
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker   // The offset is composed of two things: the sum of the sizes of all MBB's
191*9880d681SAndroid Build Coastguard Worker   // before this instruction's block, and the offset from the start of the block
192*9880d681SAndroid Build Coastguard Worker   // it is in.
193*9880d681SAndroid Build Coastguard Worker   unsigned Offset = BlockInfo[MBB->getNumber()].Offset;
194*9880d681SAndroid Build Coastguard Worker 
195*9880d681SAndroid Build Coastguard Worker   // Sum instructions before MI in MBB.
196*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) {
197*9880d681SAndroid Build Coastguard Worker     assert(I != MBB->end() && "Didn't find MI in its own basic block?");
198*9880d681SAndroid Build Coastguard Worker     Offset += TII->GetInstSizeInBytes(*I);
199*9880d681SAndroid Build Coastguard Worker   }
200*9880d681SAndroid Build Coastguard Worker   return Offset;
201*9880d681SAndroid Build Coastguard Worker }
202*9880d681SAndroid Build Coastguard Worker 
adjustBlockOffsets(MachineBasicBlock & Start)203*9880d681SAndroid Build Coastguard Worker void AArch64BranchRelaxation::adjustBlockOffsets(MachineBasicBlock &Start) {
204*9880d681SAndroid Build Coastguard Worker   unsigned PrevNum = Start.getNumber();
205*9880d681SAndroid Build Coastguard Worker   for (auto &MBB : make_range(MachineFunction::iterator(Start), MF->end())) {
206*9880d681SAndroid Build Coastguard Worker     unsigned Num = MBB.getNumber();
207*9880d681SAndroid Build Coastguard Worker     if (!Num) // block zero is never changed from offset zero.
208*9880d681SAndroid Build Coastguard Worker       continue;
209*9880d681SAndroid Build Coastguard Worker     // Get the offset and known bits at the end of the layout predecessor.
210*9880d681SAndroid Build Coastguard Worker     // Include the alignment of the current block.
211*9880d681SAndroid Build Coastguard Worker     unsigned LogAlign = MBB.getAlignment();
212*9880d681SAndroid Build Coastguard Worker     BlockInfo[Num].Offset = BlockInfo[PrevNum].postOffset(LogAlign);
213*9880d681SAndroid Build Coastguard Worker     PrevNum = Num;
214*9880d681SAndroid Build Coastguard Worker   }
215*9880d681SAndroid Build Coastguard Worker }
216*9880d681SAndroid Build Coastguard Worker 
217*9880d681SAndroid Build Coastguard Worker /// Split the basic block containing MI into two blocks, which are joined by
218*9880d681SAndroid Build Coastguard Worker /// an unconditional branch.  Update data structures and renumber blocks to
219*9880d681SAndroid Build Coastguard Worker /// account for this change and returns the newly created block.
220*9880d681SAndroid Build Coastguard Worker /// NOTE: Successor list of the original BB is out of date after this function,
221*9880d681SAndroid Build Coastguard Worker /// and must be updated by the caller! Other transforms follow using this
222*9880d681SAndroid Build Coastguard Worker /// utility function, so no point updating now rather than waiting.
223*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *
splitBlockBeforeInstr(MachineInstr * MI)224*9880d681SAndroid Build Coastguard Worker AArch64BranchRelaxation::splitBlockBeforeInstr(MachineInstr *MI) {
225*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *OrigBB = MI->getParent();
226*9880d681SAndroid Build Coastguard Worker 
227*9880d681SAndroid Build Coastguard Worker   // Create a new MBB for the code after the OrigBB.
228*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *NewBB =
229*9880d681SAndroid Build Coastguard Worker       MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());
230*9880d681SAndroid Build Coastguard Worker   MF->insert(++OrigBB->getIterator(), NewBB);
231*9880d681SAndroid Build Coastguard Worker 
232*9880d681SAndroid Build Coastguard Worker   // Splice the instructions starting with MI over to NewBB.
233*9880d681SAndroid Build Coastguard Worker   NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());
234*9880d681SAndroid Build Coastguard Worker 
235*9880d681SAndroid Build Coastguard Worker   // Add an unconditional branch from OrigBB to NewBB.
236*9880d681SAndroid Build Coastguard Worker   // Note the new unconditional branch is not being recorded.
237*9880d681SAndroid Build Coastguard Worker   // There doesn't seem to be meaningful DebugInfo available; this doesn't
238*9880d681SAndroid Build Coastguard Worker   // correspond to anything in the source.
239*9880d681SAndroid Build Coastguard Worker   BuildMI(OrigBB, DebugLoc(), TII->get(AArch64::B)).addMBB(NewBB);
240*9880d681SAndroid Build Coastguard Worker 
241*9880d681SAndroid Build Coastguard Worker   // Insert an entry into BlockInfo to align it properly with the block numbers.
242*9880d681SAndroid Build Coastguard Worker   BlockInfo.insert(BlockInfo.begin() + NewBB->getNumber(), BasicBlockInfo());
243*9880d681SAndroid Build Coastguard Worker 
244*9880d681SAndroid Build Coastguard Worker   // Figure out how large the OrigBB is.  As the first half of the original
245*9880d681SAndroid Build Coastguard Worker   // block, it cannot contain a tablejump.  The size includes
246*9880d681SAndroid Build Coastguard Worker   // the new jump we added.  (It should be possible to do this without
247*9880d681SAndroid Build Coastguard Worker   // recounting everything, but it's very confusing, and this is rarely
248*9880d681SAndroid Build Coastguard Worker   // executed.)
249*9880d681SAndroid Build Coastguard Worker   computeBlockSize(*OrigBB);
250*9880d681SAndroid Build Coastguard Worker 
251*9880d681SAndroid Build Coastguard Worker   // Figure out how large the NewMBB is.  As the second half of the original
252*9880d681SAndroid Build Coastguard Worker   // block, it may contain a tablejump.
253*9880d681SAndroid Build Coastguard Worker   computeBlockSize(*NewBB);
254*9880d681SAndroid Build Coastguard Worker 
255*9880d681SAndroid Build Coastguard Worker   // All BBOffsets following these blocks must be modified.
256*9880d681SAndroid Build Coastguard Worker   adjustBlockOffsets(*OrigBB);
257*9880d681SAndroid Build Coastguard Worker 
258*9880d681SAndroid Build Coastguard Worker   ++NumSplit;
259*9880d681SAndroid Build Coastguard Worker 
260*9880d681SAndroid Build Coastguard Worker   return NewBB;
261*9880d681SAndroid Build Coastguard Worker }
262*9880d681SAndroid Build Coastguard Worker 
263*9880d681SAndroid Build Coastguard Worker /// isBlockInRange - Returns true if the distance between specific MI and
264*9880d681SAndroid Build Coastguard Worker /// specific BB can fit in MI's displacement field.
isBlockInRange(MachineInstr * MI,MachineBasicBlock * DestBB,unsigned Bits)265*9880d681SAndroid Build Coastguard Worker bool AArch64BranchRelaxation::isBlockInRange(MachineInstr *MI,
266*9880d681SAndroid Build Coastguard Worker                                              MachineBasicBlock *DestBB,
267*9880d681SAndroid Build Coastguard Worker                                              unsigned Bits) {
268*9880d681SAndroid Build Coastguard Worker   unsigned MaxOffs = ((1 << (Bits - 1)) - 1) << 2;
269*9880d681SAndroid Build Coastguard Worker   unsigned BrOffset = getInstrOffset(MI);
270*9880d681SAndroid Build Coastguard Worker   unsigned DestOffset = BlockInfo[DestBB->getNumber()].Offset;
271*9880d681SAndroid Build Coastguard Worker 
272*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "Branch of destination BB#" << DestBB->getNumber()
273*9880d681SAndroid Build Coastguard Worker                << " from BB#" << MI->getParent()->getNumber()
274*9880d681SAndroid Build Coastguard Worker                << " max delta=" << MaxOffs << " from " << getInstrOffset(MI)
275*9880d681SAndroid Build Coastguard Worker                << " to " << DestOffset << " offset "
276*9880d681SAndroid Build Coastguard Worker                << int(DestOffset - BrOffset) << "\t" << *MI);
277*9880d681SAndroid Build Coastguard Worker 
278*9880d681SAndroid Build Coastguard Worker   // Branch before the Dest.
279*9880d681SAndroid Build Coastguard Worker   if (BrOffset <= DestOffset)
280*9880d681SAndroid Build Coastguard Worker     return (DestOffset - BrOffset <= MaxOffs);
281*9880d681SAndroid Build Coastguard Worker   return (BrOffset - DestOffset <= MaxOffs);
282*9880d681SAndroid Build Coastguard Worker }
283*9880d681SAndroid Build Coastguard Worker 
isConditionalBranch(unsigned Opc)284*9880d681SAndroid Build Coastguard Worker static bool isConditionalBranch(unsigned Opc) {
285*9880d681SAndroid Build Coastguard Worker   switch (Opc) {
286*9880d681SAndroid Build Coastguard Worker   default:
287*9880d681SAndroid Build Coastguard Worker     return false;
288*9880d681SAndroid Build Coastguard Worker   case AArch64::TBZW:
289*9880d681SAndroid Build Coastguard Worker   case AArch64::TBNZW:
290*9880d681SAndroid Build Coastguard Worker   case AArch64::TBZX:
291*9880d681SAndroid Build Coastguard Worker   case AArch64::TBNZX:
292*9880d681SAndroid Build Coastguard Worker   case AArch64::CBZW:
293*9880d681SAndroid Build Coastguard Worker   case AArch64::CBNZW:
294*9880d681SAndroid Build Coastguard Worker   case AArch64::CBZX:
295*9880d681SAndroid Build Coastguard Worker   case AArch64::CBNZX:
296*9880d681SAndroid Build Coastguard Worker   case AArch64::Bcc:
297*9880d681SAndroid Build Coastguard Worker     return true;
298*9880d681SAndroid Build Coastguard Worker   }
299*9880d681SAndroid Build Coastguard Worker }
300*9880d681SAndroid Build Coastguard Worker 
getDestBlock(MachineInstr * MI)301*9880d681SAndroid Build Coastguard Worker static MachineBasicBlock *getDestBlock(MachineInstr *MI) {
302*9880d681SAndroid Build Coastguard Worker   switch (MI->getOpcode()) {
303*9880d681SAndroid Build Coastguard Worker   default:
304*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("unexpected opcode!");
305*9880d681SAndroid Build Coastguard Worker   case AArch64::TBZW:
306*9880d681SAndroid Build Coastguard Worker   case AArch64::TBNZW:
307*9880d681SAndroid Build Coastguard Worker   case AArch64::TBZX:
308*9880d681SAndroid Build Coastguard Worker   case AArch64::TBNZX:
309*9880d681SAndroid Build Coastguard Worker     return MI->getOperand(2).getMBB();
310*9880d681SAndroid Build Coastguard Worker   case AArch64::CBZW:
311*9880d681SAndroid Build Coastguard Worker   case AArch64::CBNZW:
312*9880d681SAndroid Build Coastguard Worker   case AArch64::CBZX:
313*9880d681SAndroid Build Coastguard Worker   case AArch64::CBNZX:
314*9880d681SAndroid Build Coastguard Worker   case AArch64::Bcc:
315*9880d681SAndroid Build Coastguard Worker     return MI->getOperand(1).getMBB();
316*9880d681SAndroid Build Coastguard Worker   }
317*9880d681SAndroid Build Coastguard Worker }
318*9880d681SAndroid Build Coastguard Worker 
getOppositeConditionOpcode(unsigned Opc)319*9880d681SAndroid Build Coastguard Worker static unsigned getOppositeConditionOpcode(unsigned Opc) {
320*9880d681SAndroid Build Coastguard Worker   switch (Opc) {
321*9880d681SAndroid Build Coastguard Worker   default:
322*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("unexpected opcode!");
323*9880d681SAndroid Build Coastguard Worker   case AArch64::TBNZW:   return AArch64::TBZW;
324*9880d681SAndroid Build Coastguard Worker   case AArch64::TBNZX:   return AArch64::TBZX;
325*9880d681SAndroid Build Coastguard Worker   case AArch64::TBZW:    return AArch64::TBNZW;
326*9880d681SAndroid Build Coastguard Worker   case AArch64::TBZX:    return AArch64::TBNZX;
327*9880d681SAndroid Build Coastguard Worker   case AArch64::CBNZW:   return AArch64::CBZW;
328*9880d681SAndroid Build Coastguard Worker   case AArch64::CBNZX:   return AArch64::CBZX;
329*9880d681SAndroid Build Coastguard Worker   case AArch64::CBZW:    return AArch64::CBNZW;
330*9880d681SAndroid Build Coastguard Worker   case AArch64::CBZX:    return AArch64::CBNZX;
331*9880d681SAndroid Build Coastguard Worker   case AArch64::Bcc:     return AArch64::Bcc; // Condition is an operand for Bcc.
332*9880d681SAndroid Build Coastguard Worker   }
333*9880d681SAndroid Build Coastguard Worker }
334*9880d681SAndroid Build Coastguard Worker 
getBranchDisplacementBits(unsigned Opc)335*9880d681SAndroid Build Coastguard Worker static unsigned getBranchDisplacementBits(unsigned Opc) {
336*9880d681SAndroid Build Coastguard Worker   switch (Opc) {
337*9880d681SAndroid Build Coastguard Worker   default:
338*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("unexpected opcode!");
339*9880d681SAndroid Build Coastguard Worker   case AArch64::TBNZW:
340*9880d681SAndroid Build Coastguard Worker   case AArch64::TBZW:
341*9880d681SAndroid Build Coastguard Worker   case AArch64::TBNZX:
342*9880d681SAndroid Build Coastguard Worker   case AArch64::TBZX:
343*9880d681SAndroid Build Coastguard Worker     return TBZDisplacementBits;
344*9880d681SAndroid Build Coastguard Worker   case AArch64::CBNZW:
345*9880d681SAndroid Build Coastguard Worker   case AArch64::CBZW:
346*9880d681SAndroid Build Coastguard Worker   case AArch64::CBNZX:
347*9880d681SAndroid Build Coastguard Worker   case AArch64::CBZX:
348*9880d681SAndroid Build Coastguard Worker     return CBZDisplacementBits;
349*9880d681SAndroid Build Coastguard Worker   case AArch64::Bcc:
350*9880d681SAndroid Build Coastguard Worker     return BCCDisplacementBits;
351*9880d681SAndroid Build Coastguard Worker   }
352*9880d681SAndroid Build Coastguard Worker }
353*9880d681SAndroid Build Coastguard Worker 
invertBccCondition(MachineInstr * MI)354*9880d681SAndroid Build Coastguard Worker static inline void invertBccCondition(MachineInstr *MI) {
355*9880d681SAndroid Build Coastguard Worker   assert(MI->getOpcode() == AArch64::Bcc && "Unexpected opcode!");
356*9880d681SAndroid Build Coastguard Worker   AArch64CC::CondCode CC = (AArch64CC::CondCode)MI->getOperand(0).getImm();
357*9880d681SAndroid Build Coastguard Worker   CC = AArch64CC::getInvertedCondCode(CC);
358*9880d681SAndroid Build Coastguard Worker   MI->getOperand(0).setImm((int64_t)CC);
359*9880d681SAndroid Build Coastguard Worker }
360*9880d681SAndroid Build Coastguard Worker 
361*9880d681SAndroid Build Coastguard Worker /// fixupConditionalBranch - Fix up a conditional branch whose destination is
362*9880d681SAndroid Build Coastguard Worker /// too far away to fit in its displacement field. It is converted to an inverse
363*9880d681SAndroid Build Coastguard Worker /// conditional branch + an unconditional branch to the destination.
fixupConditionalBranch(MachineInstr * MI)364*9880d681SAndroid Build Coastguard Worker bool AArch64BranchRelaxation::fixupConditionalBranch(MachineInstr *MI) {
365*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *DestBB = getDestBlock(MI);
366*9880d681SAndroid Build Coastguard Worker 
367*9880d681SAndroid Build Coastguard Worker   // Add an unconditional branch to the destination and invert the branch
368*9880d681SAndroid Build Coastguard Worker   // condition to jump over it:
369*9880d681SAndroid Build Coastguard Worker   // tbz L1
370*9880d681SAndroid Build Coastguard Worker   // =>
371*9880d681SAndroid Build Coastguard Worker   // tbnz L2
372*9880d681SAndroid Build Coastguard Worker   // b   L1
373*9880d681SAndroid Build Coastguard Worker   // L2:
374*9880d681SAndroid Build Coastguard Worker 
375*9880d681SAndroid Build Coastguard Worker   // If the branch is at the end of its MBB and that has a fall-through block,
376*9880d681SAndroid Build Coastguard Worker   // direct the updated conditional branch to the fall-through block. Otherwise,
377*9880d681SAndroid Build Coastguard Worker   // split the MBB before the next instruction.
378*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB = MI->getParent();
379*9880d681SAndroid Build Coastguard Worker   MachineInstr *BMI = &MBB->back();
380*9880d681SAndroid Build Coastguard Worker   bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB);
381*9880d681SAndroid Build Coastguard Worker 
382*9880d681SAndroid Build Coastguard Worker   if (BMI != MI) {
383*9880d681SAndroid Build Coastguard Worker     if (std::next(MachineBasicBlock::iterator(MI)) ==
384*9880d681SAndroid Build Coastguard Worker             std::prev(MBB->getLastNonDebugInstr()) &&
385*9880d681SAndroid Build Coastguard Worker         BMI->getOpcode() == AArch64::B) {
386*9880d681SAndroid Build Coastguard Worker       // Last MI in the BB is an unconditional branch. Can we simply invert the
387*9880d681SAndroid Build Coastguard Worker       // condition and swap destinations:
388*9880d681SAndroid Build Coastguard Worker       // beq L1
389*9880d681SAndroid Build Coastguard Worker       // b   L2
390*9880d681SAndroid Build Coastguard Worker       // =>
391*9880d681SAndroid Build Coastguard Worker       // bne L2
392*9880d681SAndroid Build Coastguard Worker       // b   L1
393*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB();
394*9880d681SAndroid Build Coastguard Worker       if (isBlockInRange(MI, NewDest,
395*9880d681SAndroid Build Coastguard Worker                          getBranchDisplacementBits(MI->getOpcode()))) {
396*9880d681SAndroid Build Coastguard Worker         DEBUG(dbgs() << "  Invert condition and swap its destination with "
397*9880d681SAndroid Build Coastguard Worker                      << *BMI);
398*9880d681SAndroid Build Coastguard Worker         BMI->getOperand(0).setMBB(DestBB);
399*9880d681SAndroid Build Coastguard Worker         unsigned OpNum = (MI->getOpcode() == AArch64::TBZW ||
400*9880d681SAndroid Build Coastguard Worker                           MI->getOpcode() == AArch64::TBNZW ||
401*9880d681SAndroid Build Coastguard Worker                           MI->getOpcode() == AArch64::TBZX ||
402*9880d681SAndroid Build Coastguard Worker                           MI->getOpcode() == AArch64::TBNZX)
403*9880d681SAndroid Build Coastguard Worker                              ? 2
404*9880d681SAndroid Build Coastguard Worker                              : 1;
405*9880d681SAndroid Build Coastguard Worker         MI->getOperand(OpNum).setMBB(NewDest);
406*9880d681SAndroid Build Coastguard Worker         MI->setDesc(TII->get(getOppositeConditionOpcode(MI->getOpcode())));
407*9880d681SAndroid Build Coastguard Worker         if (MI->getOpcode() == AArch64::Bcc)
408*9880d681SAndroid Build Coastguard Worker           invertBccCondition(MI);
409*9880d681SAndroid Build Coastguard Worker         return true;
410*9880d681SAndroid Build Coastguard Worker       }
411*9880d681SAndroid Build Coastguard Worker     }
412*9880d681SAndroid Build Coastguard Worker   }
413*9880d681SAndroid Build Coastguard Worker 
414*9880d681SAndroid Build Coastguard Worker   if (NeedSplit) {
415*9880d681SAndroid Build Coastguard Worker     // Analyze the branch so we know how to update the successor lists.
416*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *TBB, *FBB;
417*9880d681SAndroid Build Coastguard Worker     SmallVector<MachineOperand, 2> Cond;
418*9880d681SAndroid Build Coastguard Worker     TII->analyzeBranch(*MBB, TBB, FBB, Cond, false);
419*9880d681SAndroid Build Coastguard Worker 
420*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *NewBB = splitBlockBeforeInstr(MI);
421*9880d681SAndroid Build Coastguard Worker     // No need for the branch to the next block. We're adding an unconditional
422*9880d681SAndroid Build Coastguard Worker     // branch to the destination.
423*9880d681SAndroid Build Coastguard Worker     int delta = TII->GetInstSizeInBytes(MBB->back());
424*9880d681SAndroid Build Coastguard Worker     BlockInfo[MBB->getNumber()].Size -= delta;
425*9880d681SAndroid Build Coastguard Worker     MBB->back().eraseFromParent();
426*9880d681SAndroid Build Coastguard Worker     // BlockInfo[SplitBB].Offset is wrong temporarily, fixed below
427*9880d681SAndroid Build Coastguard Worker 
428*9880d681SAndroid Build Coastguard Worker     // Update the successor lists according to the transformation to follow.
429*9880d681SAndroid Build Coastguard Worker     // Do it here since if there's no split, no update is needed.
430*9880d681SAndroid Build Coastguard Worker     MBB->replaceSuccessor(FBB, NewBB);
431*9880d681SAndroid Build Coastguard Worker     NewBB->addSuccessor(FBB);
432*9880d681SAndroid Build Coastguard Worker   }
433*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *NextBB = &*std::next(MachineFunction::iterator(MBB));
434*9880d681SAndroid Build Coastguard Worker 
435*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "  Insert B to BB#" << DestBB->getNumber()
436*9880d681SAndroid Build Coastguard Worker                << ", invert condition and change dest. to BB#"
437*9880d681SAndroid Build Coastguard Worker                << NextBB->getNumber() << "\n");
438*9880d681SAndroid Build Coastguard Worker 
439*9880d681SAndroid Build Coastguard Worker   // Insert a new conditional branch and a new unconditional branch.
440*9880d681SAndroid Build Coastguard Worker   MachineInstrBuilder MIB = BuildMI(
441*9880d681SAndroid Build Coastguard Worker       MBB, DebugLoc(), TII->get(getOppositeConditionOpcode(MI->getOpcode())))
442*9880d681SAndroid Build Coastguard Worker                                 .addOperand(MI->getOperand(0));
443*9880d681SAndroid Build Coastguard Worker   if (MI->getOpcode() == AArch64::TBZW || MI->getOpcode() == AArch64::TBNZW ||
444*9880d681SAndroid Build Coastguard Worker       MI->getOpcode() == AArch64::TBZX || MI->getOpcode() == AArch64::TBNZX)
445*9880d681SAndroid Build Coastguard Worker     MIB.addOperand(MI->getOperand(1));
446*9880d681SAndroid Build Coastguard Worker   if (MI->getOpcode() == AArch64::Bcc)
447*9880d681SAndroid Build Coastguard Worker     invertBccCondition(MIB);
448*9880d681SAndroid Build Coastguard Worker   MIB.addMBB(NextBB);
449*9880d681SAndroid Build Coastguard Worker   BlockInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(MBB->back());
450*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, DebugLoc(), TII->get(AArch64::B)).addMBB(DestBB);
451*9880d681SAndroid Build Coastguard Worker   BlockInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(MBB->back());
452*9880d681SAndroid Build Coastguard Worker 
453*9880d681SAndroid Build Coastguard Worker   // Remove the old conditional branch.  It may or may not still be in MBB.
454*9880d681SAndroid Build Coastguard Worker   BlockInfo[MI->getParent()->getNumber()].Size -= TII->GetInstSizeInBytes(*MI);
455*9880d681SAndroid Build Coastguard Worker   MI->eraseFromParent();
456*9880d681SAndroid Build Coastguard Worker 
457*9880d681SAndroid Build Coastguard Worker   // Finally, keep the block offsets up to date.
458*9880d681SAndroid Build Coastguard Worker   adjustBlockOffsets(*MBB);
459*9880d681SAndroid Build Coastguard Worker   return true;
460*9880d681SAndroid Build Coastguard Worker }
461*9880d681SAndroid Build Coastguard Worker 
relaxBranchInstructions()462*9880d681SAndroid Build Coastguard Worker bool AArch64BranchRelaxation::relaxBranchInstructions() {
463*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
464*9880d681SAndroid Build Coastguard Worker   // Relaxing branches involves creating new basic blocks, so re-eval
465*9880d681SAndroid Build Coastguard Worker   // end() for termination.
466*9880d681SAndroid Build Coastguard Worker   for (MachineFunction::iterator I = MF->begin(); I != MF->end(); ++I) {
467*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock &MBB = *I;
468*9880d681SAndroid Build Coastguard Worker     MachineInstr &MI = *MBB.getFirstTerminator();
469*9880d681SAndroid Build Coastguard Worker     if (isConditionalBranch(MI.getOpcode()) &&
470*9880d681SAndroid Build Coastguard Worker         !isBlockInRange(&MI, getDestBlock(&MI),
471*9880d681SAndroid Build Coastguard Worker                         getBranchDisplacementBits(MI.getOpcode()))) {
472*9880d681SAndroid Build Coastguard Worker       fixupConditionalBranch(&MI);
473*9880d681SAndroid Build Coastguard Worker       ++NumRelaxed;
474*9880d681SAndroid Build Coastguard Worker       Changed = true;
475*9880d681SAndroid Build Coastguard Worker     }
476*9880d681SAndroid Build Coastguard Worker   }
477*9880d681SAndroid Build Coastguard Worker   return Changed;
478*9880d681SAndroid Build Coastguard Worker }
479*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & mf)480*9880d681SAndroid Build Coastguard Worker bool AArch64BranchRelaxation::runOnMachineFunction(MachineFunction &mf) {
481*9880d681SAndroid Build Coastguard Worker   MF = &mf;
482*9880d681SAndroid Build Coastguard Worker 
483*9880d681SAndroid Build Coastguard Worker   // If the pass is disabled, just bail early.
484*9880d681SAndroid Build Coastguard Worker   if (!BranchRelaxation)
485*9880d681SAndroid Build Coastguard Worker     return false;
486*9880d681SAndroid Build Coastguard Worker 
487*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "***** AArch64BranchRelaxation *****\n");
488*9880d681SAndroid Build Coastguard Worker 
489*9880d681SAndroid Build Coastguard Worker   TII = (const AArch64InstrInfo *)MF->getSubtarget().getInstrInfo();
490*9880d681SAndroid Build Coastguard Worker 
491*9880d681SAndroid Build Coastguard Worker   // Renumber all of the machine basic blocks in the function, guaranteeing that
492*9880d681SAndroid Build Coastguard Worker   // the numbers agree with the position of the block in the function.
493*9880d681SAndroid Build Coastguard Worker   MF->RenumberBlocks();
494*9880d681SAndroid Build Coastguard Worker 
495*9880d681SAndroid Build Coastguard Worker   // Do the initial scan of the function, building up information about the
496*9880d681SAndroid Build Coastguard Worker   // sizes of each block.
497*9880d681SAndroid Build Coastguard Worker   scanFunction();
498*9880d681SAndroid Build Coastguard Worker 
499*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "  Basic blocks before relaxation\n");
500*9880d681SAndroid Build Coastguard Worker   DEBUG(dumpBBs());
501*9880d681SAndroid Build Coastguard Worker 
502*9880d681SAndroid Build Coastguard Worker   bool MadeChange = false;
503*9880d681SAndroid Build Coastguard Worker   while (relaxBranchInstructions())
504*9880d681SAndroid Build Coastguard Worker     MadeChange = true;
505*9880d681SAndroid Build Coastguard Worker 
506*9880d681SAndroid Build Coastguard Worker   // After a while, this might be made debug-only, but it is not expensive.
507*9880d681SAndroid Build Coastguard Worker   verify();
508*9880d681SAndroid Build Coastguard Worker 
509*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "  Basic blocks after relaxation\n");
510*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << '\n'; dumpBBs());
511*9880d681SAndroid Build Coastguard Worker 
512*9880d681SAndroid Build Coastguard Worker   BlockInfo.clear();
513*9880d681SAndroid Build Coastguard Worker 
514*9880d681SAndroid Build Coastguard Worker   return MadeChange;
515*9880d681SAndroid Build Coastguard Worker }
516*9880d681SAndroid Build Coastguard Worker 
517*9880d681SAndroid Build Coastguard Worker /// Returns an instance of the AArch64 Branch Relaxation pass.
createAArch64BranchRelaxation()518*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createAArch64BranchRelaxation() {
519*9880d681SAndroid Build Coastguard Worker   return new AArch64BranchRelaxation();
520*9880d681SAndroid Build Coastguard Worker }
521