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