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