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