1d88c1a5aSDimitry Andric //===--- ARMComputeBlockSize.cpp - Compute machine block sizes ------------===//
2d88c1a5aSDimitry Andric //
3d88c1a5aSDimitry Andric //                     The LLVM Compiler Infrastructure
4d88c1a5aSDimitry Andric //
5d88c1a5aSDimitry Andric // This file is distributed under the University of Illinois Open Source
6d88c1a5aSDimitry Andric // License. See LICENSE.TXT for details.
7d88c1a5aSDimitry Andric //
8d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
9d88c1a5aSDimitry Andric 
10d88c1a5aSDimitry Andric #include "ARM.h"
117a7e6055SDimitry Andric #include "ARMBaseInstrInfo.h"
12d88c1a5aSDimitry Andric #include "ARMBasicBlockInfo.h"
137a7e6055SDimitry Andric #include "ARMMachineFunctionInfo.h"
147a7e6055SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
157a7e6055SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
167a7e6055SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
172cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
187a7e6055SDimitry Andric #include <vector>
197a7e6055SDimitry Andric 
20d88c1a5aSDimitry Andric using namespace llvm;
21d88c1a5aSDimitry Andric 
22d88c1a5aSDimitry Andric namespace llvm {
23d88c1a5aSDimitry Andric 
24d88c1a5aSDimitry Andric // mayOptimizeThumb2Instruction - Returns true if optimizeThumb2Instructions
25d88c1a5aSDimitry Andric // below may shrink MI.
26d88c1a5aSDimitry Andric static bool
mayOptimizeThumb2Instruction(const MachineInstr * MI)27d88c1a5aSDimitry Andric mayOptimizeThumb2Instruction(const MachineInstr *MI) {
28d88c1a5aSDimitry Andric   switch(MI->getOpcode()) {
29d88c1a5aSDimitry Andric     // optimizeThumb2Instructions.
30d88c1a5aSDimitry Andric     case ARM::t2LEApcrel:
31d88c1a5aSDimitry Andric     case ARM::t2LDRpci:
32d88c1a5aSDimitry Andric     // optimizeThumb2Branches.
33d88c1a5aSDimitry Andric     case ARM::t2B:
34d88c1a5aSDimitry Andric     case ARM::t2Bcc:
35d88c1a5aSDimitry Andric     case ARM::tBcc:
36d88c1a5aSDimitry Andric     // optimizeThumb2JumpTables.
37d88c1a5aSDimitry Andric     case ARM::t2BR_JT:
38*6ccc06f6SDimitry Andric     case ARM::tBR_JTr:
39d88c1a5aSDimitry Andric       return true;
40d88c1a5aSDimitry Andric   }
41d88c1a5aSDimitry Andric   return false;
42d88c1a5aSDimitry Andric }
43d88c1a5aSDimitry Andric 
computeBlockSize(MachineFunction * MF,MachineBasicBlock * MBB,BasicBlockInfo & BBI)44d88c1a5aSDimitry Andric void computeBlockSize(MachineFunction *MF, MachineBasicBlock *MBB,
45d88c1a5aSDimitry Andric                       BasicBlockInfo &BBI) {
46d88c1a5aSDimitry Andric   const ARMBaseInstrInfo *TII =
47d88c1a5aSDimitry Andric     static_cast<const ARMBaseInstrInfo *>(MF->getSubtarget().getInstrInfo());
48d88c1a5aSDimitry Andric   bool isThumb = MF->getInfo<ARMFunctionInfo>()->isThumbFunction();
49d88c1a5aSDimitry Andric   BBI.Size = 0;
50d88c1a5aSDimitry Andric   BBI.Unalign = 0;
51d88c1a5aSDimitry Andric   BBI.PostAlign = 0;
52d88c1a5aSDimitry Andric 
53d88c1a5aSDimitry Andric   for (MachineInstr &I : *MBB) {
54d88c1a5aSDimitry Andric     BBI.Size += TII->getInstSizeInBytes(I);
55d88c1a5aSDimitry Andric     // For inline asm, getInstSizeInBytes returns a conservative estimate.
56d88c1a5aSDimitry Andric     // The actual size may be smaller, but still a multiple of the instr size.
57d88c1a5aSDimitry Andric     if (I.isInlineAsm())
58d88c1a5aSDimitry Andric       BBI.Unalign = isThumb ? 1 : 2;
59d88c1a5aSDimitry Andric     // Also consider instructions that may be shrunk later.
60d88c1a5aSDimitry Andric     else if (isThumb && mayOptimizeThumb2Instruction(&I))
61d88c1a5aSDimitry Andric       BBI.Unalign = 1;
62d88c1a5aSDimitry Andric   }
63d88c1a5aSDimitry Andric 
64d88c1a5aSDimitry Andric   // tBR_JTr contains a .align 2 directive.
65d88c1a5aSDimitry Andric   if (!MBB->empty() && MBB->back().getOpcode() == ARM::tBR_JTr) {
66d88c1a5aSDimitry Andric     BBI.PostAlign = 2;
67d88c1a5aSDimitry Andric     MBB->getParent()->ensureAlignment(2);
68d88c1a5aSDimitry Andric   }
69d88c1a5aSDimitry Andric }
70d88c1a5aSDimitry Andric 
computeAllBlockSizes(MachineFunction * MF)71d88c1a5aSDimitry Andric std::vector<BasicBlockInfo> computeAllBlockSizes(MachineFunction *MF) {
72d88c1a5aSDimitry Andric   std::vector<BasicBlockInfo> BBInfo;
73d88c1a5aSDimitry Andric   BBInfo.resize(MF->getNumBlockIDs());
74d88c1a5aSDimitry Andric 
75d88c1a5aSDimitry Andric   for (MachineBasicBlock &MBB : *MF)
76d88c1a5aSDimitry Andric     computeBlockSize(MF, &MBB, BBInfo[MBB.getNumber()]);
77d88c1a5aSDimitry Andric 
78d88c1a5aSDimitry Andric   return BBInfo;
79d88c1a5aSDimitry Andric }
80d88c1a5aSDimitry Andric 
817a7e6055SDimitry Andric } // end namespace llvm
82