10b57cec5SDimitry Andric //===--- ARMBasicBlockInfo.cpp - Utilities for block sizes ---------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 98bcb0991SDimitry Andric #include "ARMBasicBlockInfo.h" 100b57cec5SDimitry Andric #include "ARM.h" 110b57cec5SDimitry Andric #include "ARMBaseInstrInfo.h" 120b57cec5SDimitry Andric #include "ARMMachineFunctionInfo.h" 130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 160b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 178bcb0991SDimitry Andric #include "llvm/IR/GlobalVariable.h" 188bcb0991SDimitry Andric #include "llvm/Support/Debug.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #define DEBUG_TYPE "arm-bb-utils" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace llvm; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric // mayOptimizeThumb2Instruction - Returns true if optimizeThumb2Instructions 270b57cec5SDimitry Andric // below may shrink MI. 280b57cec5SDimitry Andric static bool 290b57cec5SDimitry Andric mayOptimizeThumb2Instruction(const MachineInstr *MI) { 300b57cec5SDimitry Andric switch(MI->getOpcode()) { 310b57cec5SDimitry Andric // optimizeThumb2Instructions. 320b57cec5SDimitry Andric case ARM::t2LEApcrel: 330b57cec5SDimitry Andric case ARM::t2LDRpci: 340b57cec5SDimitry Andric // optimizeThumb2Branches. 350b57cec5SDimitry Andric case ARM::t2B: 360b57cec5SDimitry Andric case ARM::t2Bcc: 370b57cec5SDimitry Andric case ARM::tBcc: 380b57cec5SDimitry Andric // optimizeThumb2JumpTables. 390b57cec5SDimitry Andric case ARM::t2BR_JT: 400b57cec5SDimitry Andric case ARM::tBR_JTr: 410b57cec5SDimitry Andric return true; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric return false; 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric void ARMBasicBlockUtils::computeBlockSize(MachineBasicBlock *MBB) { 470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "computeBlockSize: " << MBB->getName() << "\n"); 480b57cec5SDimitry Andric BasicBlockInfo &BBI = BBInfo[MBB->getNumber()]; 490b57cec5SDimitry Andric BBI.Size = 0; 500b57cec5SDimitry Andric BBI.Unalign = 0; 51*5ffd83dbSDimitry Andric BBI.PostAlign = Align(1); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric for (MachineInstr &I : *MBB) { 540b57cec5SDimitry Andric BBI.Size += TII->getInstSizeInBytes(I); 550b57cec5SDimitry Andric // For inline asm, getInstSizeInBytes returns a conservative estimate. 560b57cec5SDimitry Andric // The actual size may be smaller, but still a multiple of the instr size. 570b57cec5SDimitry Andric if (I.isInlineAsm()) 580b57cec5SDimitry Andric BBI.Unalign = isThumb ? 1 : 2; 590b57cec5SDimitry Andric // Also consider instructions that may be shrunk later. 600b57cec5SDimitry Andric else if (isThumb && mayOptimizeThumb2Instruction(&I)) 610b57cec5SDimitry Andric BBI.Unalign = 1; 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric // tBR_JTr contains a .align 2 directive. 650b57cec5SDimitry Andric if (!MBB->empty() && MBB->back().getOpcode() == ARM::tBR_JTr) { 668bcb0991SDimitry Andric BBI.PostAlign = Align(4); 678bcb0991SDimitry Andric MBB->getParent()->ensureAlignment(Align(4)); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric /// getOffsetOf - Return the current offset of the specified machine instruction 720b57cec5SDimitry Andric /// from the start of the function. This offset changes as stuff is moved 730b57cec5SDimitry Andric /// around inside the function. 740b57cec5SDimitry Andric unsigned ARMBasicBlockUtils::getOffsetOf(MachineInstr *MI) const { 750b57cec5SDimitry Andric const MachineBasicBlock *MBB = MI->getParent(); 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric // The offset is composed of two things: the sum of the sizes of all MBB's 780b57cec5SDimitry Andric // before this instruction's block, and the offset from the start of the block 790b57cec5SDimitry Andric // it is in. 800b57cec5SDimitry Andric unsigned Offset = BBInfo[MBB->getNumber()].Offset; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric // Sum instructions before MI in MBB. 830b57cec5SDimitry Andric for (MachineBasicBlock::const_iterator I = MBB->begin(); &*I != MI; ++I) { 840b57cec5SDimitry Andric assert(I != MBB->end() && "Didn't find MI in its own basic block?"); 850b57cec5SDimitry Andric Offset += TII->getInstSizeInBytes(*I); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric return Offset; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric /// isBBInRange - Returns true if the distance between specific MI and 910b57cec5SDimitry Andric /// specific BB can fit in MI's displacement field. 920b57cec5SDimitry Andric bool ARMBasicBlockUtils::isBBInRange(MachineInstr *MI, 930b57cec5SDimitry Andric MachineBasicBlock *DestBB, 940b57cec5SDimitry Andric unsigned MaxDisp) const { 950b57cec5SDimitry Andric unsigned PCAdj = isThumb ? 4 : 8; 960b57cec5SDimitry Andric unsigned BrOffset = getOffsetOf(MI) + PCAdj; 970b57cec5SDimitry Andric unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB) 1000b57cec5SDimitry Andric << " from " << printMBBReference(*MI->getParent()) 1010b57cec5SDimitry Andric << " max delta=" << MaxDisp << " from " << getOffsetOf(MI) 1020b57cec5SDimitry Andric << " to " << DestOffset << " offset " 1030b57cec5SDimitry Andric << int(DestOffset - BrOffset) << "\t" << *MI); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric if (BrOffset <= DestOffset) { 1060b57cec5SDimitry Andric // Branch before the Dest. 1070b57cec5SDimitry Andric if (DestOffset-BrOffset <= MaxDisp) 1080b57cec5SDimitry Andric return true; 1090b57cec5SDimitry Andric } else { 1100b57cec5SDimitry Andric if (BrOffset-DestOffset <= MaxDisp) 1110b57cec5SDimitry Andric return true; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric return false; 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric void ARMBasicBlockUtils::adjustBBOffsetsAfter(MachineBasicBlock *BB) { 1170b57cec5SDimitry Andric assert(BB->getParent() == &MF && 1180b57cec5SDimitry Andric "Basic block is not a child of the current function.\n"); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric unsigned BBNum = BB->getNumber(); 1210b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Adjust block:\n" 1220b57cec5SDimitry Andric << " - name: " << BB->getName() << "\n" 1230b57cec5SDimitry Andric << " - number: " << BB->getNumber() << "\n" 1240b57cec5SDimitry Andric << " - function: " << MF.getName() << "\n" 1250b57cec5SDimitry Andric << " - blocks: " << MF.getNumBlockIDs() << "\n"); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric for(unsigned i = BBNum + 1, e = MF.getNumBlockIDs(); i < e; ++i) { 1280b57cec5SDimitry Andric // Get the offset and known bits at the end of the layout predecessor. 1290b57cec5SDimitry Andric // Include the alignment of the current block. 1308bcb0991SDimitry Andric const Align Align = MF.getBlockNumbered(i)->getAlignment(); 1318bcb0991SDimitry Andric const unsigned Offset = BBInfo[i - 1].postOffset(Align); 1328bcb0991SDimitry Andric const unsigned KnownBits = BBInfo[i - 1].postKnownBits(Align); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric // This is where block i begins. Stop if the offset is already correct, 1350b57cec5SDimitry Andric // and we have updated 2 blocks. This is the maximum number of blocks 1360b57cec5SDimitry Andric // changed before calling this function. 1370b57cec5SDimitry Andric if (i > BBNum + 2 && 1380b57cec5SDimitry Andric BBInfo[i].Offset == Offset && 1390b57cec5SDimitry Andric BBInfo[i].KnownBits == KnownBits) 1400b57cec5SDimitry Andric break; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric BBInfo[i].Offset = Offset; 1430b57cec5SDimitry Andric BBInfo[i].KnownBits = KnownBits; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric } // end namespace llvm 148