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