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