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