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