1*f7c0b3aeSSam Parker //===--- ARMBasicBlockInfo.cpp - Utilities for block sizes ---------------===//
2*f7c0b3aeSSam Parker //
3*f7c0b3aeSSam Parker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*f7c0b3aeSSam Parker // See https://llvm.org/LICENSE.txt for license information.
5*f7c0b3aeSSam Parker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*f7c0b3aeSSam Parker //
7*f7c0b3aeSSam Parker //===----------------------------------------------------------------------===//
8*f7c0b3aeSSam Parker 
9*f7c0b3aeSSam Parker #include "ARM.h"
10*f7c0b3aeSSam Parker #include "ARMBaseInstrInfo.h"
11*f7c0b3aeSSam Parker #include "ARMBasicBlockInfo.h"
12*f7c0b3aeSSam Parker #include "ARMMachineFunctionInfo.h"
13*f7c0b3aeSSam Parker #include "llvm/CodeGen/MachineBasicBlock.h"
14*f7c0b3aeSSam Parker #include "llvm/CodeGen/MachineFunction.h"
15*f7c0b3aeSSam Parker #include "llvm/CodeGen/MachineInstr.h"
16*f7c0b3aeSSam Parker #include "llvm/CodeGen/TargetSubtargetInfo.h"
17*f7c0b3aeSSam Parker #include <vector>
18*f7c0b3aeSSam Parker 
19*f7c0b3aeSSam Parker #define DEBUG_TYPE "arm-bb-utils"
20*f7c0b3aeSSam Parker 
21*f7c0b3aeSSam Parker using namespace llvm;
22*f7c0b3aeSSam Parker 
23*f7c0b3aeSSam Parker namespace llvm {
24*f7c0b3aeSSam Parker 
25*f7c0b3aeSSam Parker // mayOptimizeThumb2Instruction - Returns true if optimizeThumb2Instructions
26*f7c0b3aeSSam Parker // below may shrink MI.
27*f7c0b3aeSSam Parker static bool
28*f7c0b3aeSSam Parker mayOptimizeThumb2Instruction(const MachineInstr *MI) {
29*f7c0b3aeSSam Parker   switch(MI->getOpcode()) {
30*f7c0b3aeSSam Parker     // optimizeThumb2Instructions.
31*f7c0b3aeSSam Parker     case ARM::t2LEApcrel:
32*f7c0b3aeSSam Parker     case ARM::t2LDRpci:
33*f7c0b3aeSSam Parker     // optimizeThumb2Branches.
34*f7c0b3aeSSam Parker     case ARM::t2B:
35*f7c0b3aeSSam Parker     case ARM::t2Bcc:
36*f7c0b3aeSSam Parker     case ARM::tBcc:
37*f7c0b3aeSSam Parker     // optimizeThumb2JumpTables.
38*f7c0b3aeSSam Parker     case ARM::t2BR_JT:
39*f7c0b3aeSSam Parker     case ARM::tBR_JTr:
40*f7c0b3aeSSam Parker       return true;
41*f7c0b3aeSSam Parker   }
42*f7c0b3aeSSam Parker   return false;
43*f7c0b3aeSSam Parker }
44*f7c0b3aeSSam Parker 
45*f7c0b3aeSSam Parker void ARMBasicBlockUtils::computeBlockSize(MachineBasicBlock *MBB) {
46*f7c0b3aeSSam Parker   LLVM_DEBUG(dbgs() << "computeBlockSize: " << MBB->getName() << "\n");
47*f7c0b3aeSSam Parker   BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];
48*f7c0b3aeSSam Parker   BBI.Size = 0;
49*f7c0b3aeSSam Parker   BBI.Unalign = 0;
50*f7c0b3aeSSam Parker   BBI.PostAlign = 0;
51*f7c0b3aeSSam Parker 
52*f7c0b3aeSSam Parker   for (MachineInstr &I : *MBB) {
53*f7c0b3aeSSam Parker     BBI.Size += TII->getInstSizeInBytes(I);
54*f7c0b3aeSSam Parker     // For inline asm, getInstSizeInBytes returns a conservative estimate.
55*f7c0b3aeSSam Parker     // The actual size may be smaller, but still a multiple of the instr size.
56*f7c0b3aeSSam Parker     if (I.isInlineAsm())
57*f7c0b3aeSSam Parker       BBI.Unalign = isThumb ? 1 : 2;
58*f7c0b3aeSSam Parker     // Also consider instructions that may be shrunk later.
59*f7c0b3aeSSam Parker     else if (isThumb && mayOptimizeThumb2Instruction(&I))
60*f7c0b3aeSSam Parker       BBI.Unalign = 1;
61*f7c0b3aeSSam Parker   }
62*f7c0b3aeSSam Parker 
63*f7c0b3aeSSam Parker   // tBR_JTr contains a .align 2 directive.
64*f7c0b3aeSSam Parker   if (!MBB->empty() && MBB->back().getOpcode() == ARM::tBR_JTr) {
65*f7c0b3aeSSam Parker     BBI.PostAlign = 2;
66*f7c0b3aeSSam Parker     MBB->getParent()->ensureAlignment(2);
67*f7c0b3aeSSam Parker   }
68*f7c0b3aeSSam Parker }
69*f7c0b3aeSSam Parker 
70*f7c0b3aeSSam Parker /// getOffsetOf - Return the current offset of the specified machine instruction
71*f7c0b3aeSSam Parker /// from the start of the function.  This offset changes as stuff is moved
72*f7c0b3aeSSam Parker /// around inside the function.
73*f7c0b3aeSSam Parker unsigned ARMBasicBlockUtils::getOffsetOf(MachineInstr *MI) const {
74*f7c0b3aeSSam Parker   const MachineBasicBlock *MBB = MI->getParent();
75*f7c0b3aeSSam Parker 
76*f7c0b3aeSSam Parker   // The offset is composed of two things: the sum of the sizes of all MBB's
77*f7c0b3aeSSam Parker   // before this instruction's block, and the offset from the start of the block
78*f7c0b3aeSSam Parker   // it is in.
79*f7c0b3aeSSam Parker   unsigned Offset = BBInfo[MBB->getNumber()].Offset;
80*f7c0b3aeSSam Parker 
81*f7c0b3aeSSam Parker   // Sum instructions before MI in MBB.
82*f7c0b3aeSSam Parker   for (MachineBasicBlock::const_iterator I = MBB->begin(); &*I != MI; ++I) {
83*f7c0b3aeSSam Parker     assert(I != MBB->end() && "Didn't find MI in its own basic block?");
84*f7c0b3aeSSam Parker     Offset += TII->getInstSizeInBytes(*I);
85*f7c0b3aeSSam Parker   }
86*f7c0b3aeSSam Parker   return Offset;
87*f7c0b3aeSSam Parker }
88*f7c0b3aeSSam Parker 
89*f7c0b3aeSSam Parker /// isBBInRange - Returns true if the distance between specific MI and
90*f7c0b3aeSSam Parker /// specific BB can fit in MI's displacement field.
91*f7c0b3aeSSam Parker bool ARMBasicBlockUtils::isBBInRange(MachineInstr *MI,
92*f7c0b3aeSSam Parker                                      MachineBasicBlock *DestBB,
93*f7c0b3aeSSam Parker                                      unsigned MaxDisp) const {
94*f7c0b3aeSSam Parker   unsigned PCAdj      = isThumb ? 4 : 8;
95*f7c0b3aeSSam Parker   unsigned BrOffset   = getOffsetOf(MI) + PCAdj;
96*f7c0b3aeSSam Parker   unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
97*f7c0b3aeSSam Parker 
98*f7c0b3aeSSam Parker   LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB)
99*f7c0b3aeSSam Parker                     << " from " << printMBBReference(*MI->getParent())
100*f7c0b3aeSSam Parker                     << " max delta=" << MaxDisp << " from " << getOffsetOf(MI)
101*f7c0b3aeSSam Parker                     << " to " << DestOffset << " offset "
102*f7c0b3aeSSam Parker                     << int(DestOffset - BrOffset) << "\t" << *MI);
103*f7c0b3aeSSam Parker 
104*f7c0b3aeSSam Parker   if (BrOffset <= DestOffset) {
105*f7c0b3aeSSam Parker     // Branch before the Dest.
106*f7c0b3aeSSam Parker     if (DestOffset-BrOffset <= MaxDisp)
107*f7c0b3aeSSam Parker       return true;
108*f7c0b3aeSSam Parker   } else {
109*f7c0b3aeSSam Parker     if (BrOffset-DestOffset <= MaxDisp)
110*f7c0b3aeSSam Parker       return true;
111*f7c0b3aeSSam Parker   }
112*f7c0b3aeSSam Parker   return false;
113*f7c0b3aeSSam Parker }
114*f7c0b3aeSSam Parker 
115*f7c0b3aeSSam Parker void ARMBasicBlockUtils::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
116*f7c0b3aeSSam Parker   assert(BB->getParent() == &MF &&
117*f7c0b3aeSSam Parker          "Basic block is not a child of the current function.\n");
118*f7c0b3aeSSam Parker 
119*f7c0b3aeSSam Parker   unsigned BBNum = BB->getNumber();
120*f7c0b3aeSSam Parker   LLVM_DEBUG(dbgs() << "Adjust block:\n"
121*f7c0b3aeSSam Parker              << " - name: " << BB->getName() << "\n"
122*f7c0b3aeSSam Parker              << " - number: " << BB->getNumber() << "\n"
123*f7c0b3aeSSam Parker              << " - function: " << MF.getName() << "\n"
124*f7c0b3aeSSam Parker              << "   - blocks: " << MF.getNumBlockIDs() << "\n");
125*f7c0b3aeSSam Parker 
126*f7c0b3aeSSam Parker   for(unsigned i = BBNum + 1, e = MF.getNumBlockIDs(); i < e; ++i) {
127*f7c0b3aeSSam Parker     // Get the offset and known bits at the end of the layout predecessor.
128*f7c0b3aeSSam Parker     // Include the alignment of the current block.
129*f7c0b3aeSSam Parker     unsigned LogAlign = MF.getBlockNumbered(i)->getAlignment();
130*f7c0b3aeSSam Parker     unsigned Offset = BBInfo[i - 1].postOffset(LogAlign);
131*f7c0b3aeSSam Parker     unsigned KnownBits = BBInfo[i - 1].postKnownBits(LogAlign);
132*f7c0b3aeSSam Parker 
133*f7c0b3aeSSam Parker     // This is where block i begins.  Stop if the offset is already correct,
134*f7c0b3aeSSam Parker     // and we have updated 2 blocks.  This is the maximum number of blocks
135*f7c0b3aeSSam Parker     // changed before calling this function.
136*f7c0b3aeSSam Parker     if (i > BBNum + 2 &&
137*f7c0b3aeSSam Parker         BBInfo[i].Offset == Offset &&
138*f7c0b3aeSSam Parker         BBInfo[i].KnownBits == KnownBits)
139*f7c0b3aeSSam Parker       break;
140*f7c0b3aeSSam Parker 
141*f7c0b3aeSSam Parker     BBInfo[i].Offset = Offset;
142*f7c0b3aeSSam Parker     BBInfo[i].KnownBits = KnownBits;
143*f7c0b3aeSSam Parker   }
144*f7c0b3aeSSam Parker }
145*f7c0b3aeSSam Parker 
146*f7c0b3aeSSam Parker } // end namespace llvm
147