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 23 using namespace llvm; 24 25 namespace llvm { 26 27 // mayOptimizeThumb2Instruction - Returns true if optimizeThumb2Instructions 28 // below may shrink MI. 29 static bool 30 mayOptimizeThumb2Instruction(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 47 void 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. 75 unsigned 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. 93 bool 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 117 void 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