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