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