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
9904cd3e0SReid 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"
17904cd3e0SReid Kleckner #include "llvm/IR/GlobalVariable.h"
18904cd3e0SReid 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
mayOptimizeThumb2Instruction(const MachineInstr * MI)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
computeBlockSize(MachineBasicBlock * MBB)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;
52*805c157eSGuillaume Chatelet BBI.PostAlign = Align(1);
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.
getOffsetOf(MachineInstr * MI) const75f7c0b3aeSSam 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.
isBBInRange(MachineInstr * MI,MachineBasicBlock * DestBB,unsigned MaxDisp) const93f7c0b3aeSSam 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
adjustBBOffsetsAfter(MachineBasicBlock * BB)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