Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARM/ARMBasicBlockInfo.cpp
35269 views
//===--- ARMBasicBlockInfo.cpp - Utilities for block sizes ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "ARMBasicBlockInfo.h"9#include "ARM.h"10#include "ARMBaseInstrInfo.h"11#include "ARMMachineFunctionInfo.h"12#include "llvm/CodeGen/MachineBasicBlock.h"13#include "llvm/CodeGen/MachineFunction.h"14#include "llvm/CodeGen/MachineInstr.h"15#include "llvm/CodeGen/TargetSubtargetInfo.h"16#include "llvm/IR/GlobalVariable.h"17#include "llvm/Support/Debug.h"1819#define DEBUG_TYPE "arm-bb-utils"2021using namespace llvm;2223namespace llvm {2425// mayOptimizeThumb2Instruction - Returns true if optimizeThumb2Instructions26// below may shrink MI.27static bool28mayOptimizeThumb2Instruction(const MachineInstr *MI) {29switch(MI->getOpcode()) {30// optimizeThumb2Instructions.31case ARM::t2LEApcrel:32case ARM::t2LDRpci:33// optimizeThumb2Branches.34case ARM::t2B:35case ARM::t2Bcc:36case ARM::tBcc:37// optimizeThumb2JumpTables.38case ARM::t2BR_JT:39case ARM::tBR_JTr:40return true;41}42return false;43}4445void ARMBasicBlockUtils::computeBlockSize(MachineBasicBlock *MBB) {46LLVM_DEBUG(dbgs() << "computeBlockSize: " << MBB->getName() << "\n");47BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];48BBI.Size = 0;49BBI.Unalign = 0;50BBI.PostAlign = Align(1);5152for (MachineInstr &I : *MBB) {53BBI.Size += TII->getInstSizeInBytes(I);54// For inline asm, getInstSizeInBytes returns a conservative estimate.55// The actual size may be smaller, but still a multiple of the instr size.56if (I.isInlineAsm())57BBI.Unalign = isThumb ? 1 : 2;58// Also consider instructions that may be shrunk later.59else if (isThumb && mayOptimizeThumb2Instruction(&I))60BBI.Unalign = 1;61}6263// tBR_JTr contains a .align 2 directive.64if (!MBB->empty() && MBB->back().getOpcode() == ARM::tBR_JTr) {65BBI.PostAlign = Align(4);66MBB->getParent()->ensureAlignment(Align(4));67}68}6970/// getOffsetOf - Return the current offset of the specified machine instruction71/// from the start of the function. This offset changes as stuff is moved72/// around inside the function.73unsigned ARMBasicBlockUtils::getOffsetOf(MachineInstr *MI) const {74const MachineBasicBlock *MBB = MI->getParent();7576// The offset is composed of two things: the sum of the sizes of all MBB's77// before this instruction's block, and the offset from the start of the block78// it is in.79unsigned Offset = BBInfo[MBB->getNumber()].Offset;8081// Sum instructions before MI in MBB.82for (MachineBasicBlock::const_iterator I = MBB->begin(); &*I != MI; ++I) {83assert(I != MBB->end() && "Didn't find MI in its own basic block?");84Offset += TII->getInstSizeInBytes(*I);85}86return Offset;87}8889/// isBBInRange - Returns true if the distance between specific MI and90/// specific BB can fit in MI's displacement field.91bool ARMBasicBlockUtils::isBBInRange(MachineInstr *MI,92MachineBasicBlock *DestBB,93unsigned MaxDisp) const {94unsigned PCAdj = isThumb ? 4 : 8;95unsigned BrOffset = getOffsetOf(MI) + PCAdj;96unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;9798LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB)99<< " from " << printMBBReference(*MI->getParent())100<< " max delta=" << MaxDisp << " from " << getOffsetOf(MI)101<< " to " << DestOffset << " offset "102<< int(DestOffset - BrOffset) << "\t" << *MI);103104if (BrOffset <= DestOffset) {105// Branch before the Dest.106if (DestOffset-BrOffset <= MaxDisp)107return true;108} else {109if (BrOffset-DestOffset <= MaxDisp)110return true;111}112return false;113}114115void ARMBasicBlockUtils::adjustBBOffsetsAfter(MachineBasicBlock *BB) {116assert(BB->getParent() == &MF &&117"Basic block is not a child of the current function.\n");118119unsigned BBNum = BB->getNumber();120LLVM_DEBUG(dbgs() << "Adjust block:\n"121<< " - name: " << BB->getName() << "\n"122<< " - number: " << BB->getNumber() << "\n"123<< " - function: " << MF.getName() << "\n"124<< " - blocks: " << MF.getNumBlockIDs() << "\n");125126for(unsigned i = BBNum + 1, e = MF.getNumBlockIDs(); i < e; ++i) {127// Get the offset and known bits at the end of the layout predecessor.128// Include the alignment of the current block.129const Align Align = MF.getBlockNumbered(i)->getAlignment();130const unsigned Offset = BBInfo[i - 1].postOffset(Align);131const unsigned KnownBits = BBInfo[i - 1].postKnownBits(Align);132133// This is where block i begins. Stop if the offset is already correct,134// and we have updated 2 blocks. This is the maximum number of blocks135// changed before calling this function.136if (i > BBNum + 2 &&137BBInfo[i].Offset == Offset &&138BBInfo[i].KnownBits == KnownBits)139break;140141BBInfo[i].Offset = Offset;142BBInfo[i].KnownBits = KnownBits;143}144}145146} // end namespace llvm147148149