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