- Add pseudo instructions tLDRpci_pic and t2LDRpci_pic which does a pc-relative
[oota-llvm.git] / lib / Target / ARM / Thumb2ITBlockPass.cpp
1 //===-- Thumb2ITBlockPass.cpp - Insert Thumb IT blocks -----------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #define DEBUG_TYPE "thumb2-it"
11 #include "ARM.h"
12 #include "ARMMachineFunctionInfo.h"
13 #include "Thumb2InstrInfo.h"
14 #include "llvm/CodeGen/MachineInstr.h"
15 #include "llvm/CodeGen/MachineInstrBuilder.h"
16 #include "llvm/CodeGen/MachineFunctionPass.h"
17 #include "llvm/ADT/Statistic.h"
18 using namespace llvm;
19
20 STATISTIC(NumITs,     "Number of IT blocks inserted");
21
22 namespace {
23   struct Thumb2ITBlockPass : public MachineFunctionPass {
24     static char ID;
25     Thumb2ITBlockPass() : MachineFunctionPass(&ID) {}
26
27     const Thumb2InstrInfo *TII;
28     ARMFunctionInfo *AFI;
29
30     virtual bool runOnMachineFunction(MachineFunction &Fn);
31
32     virtual const char *getPassName() const {
33       return "Thumb IT blocks insertion pass";
34     }
35
36   private:
37     bool InsertITBlocks(MachineBasicBlock &MBB);
38   };
39   char Thumb2ITBlockPass::ID = 0;
40 }
41
42 static ARMCC::CondCodes getPredicate(const MachineInstr *MI, unsigned &PredReg){
43   unsigned Opc = MI->getOpcode();
44   if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
45     return ARMCC::AL;
46   return llvm::getInstrPredicate(MI, PredReg);
47 }
48
49 bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
50   bool Modified = false;
51
52   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
53   while (MBBI != E) {
54     MachineInstr *MI = &*MBBI;
55     DebugLoc dl = MI->getDebugLoc();
56     unsigned PredReg = 0;
57     ARMCC::CondCodes CC = getPredicate(MI, PredReg);
58
59     if (CC == ARMCC::AL) {
60       ++MBBI;
61       continue;
62     }
63
64     // Insert an IT instruction.
65     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
66       .addImm(CC);
67     ++MBBI;
68
69     // Finalize IT mask.
70     ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
71     unsigned Mask = 0, Pos = 3;
72     // Branches, including tricky ones like LDM_RET, need to end an IT
73     // block so check the instruction we just put in the block.
74     while (MBBI != E && Pos &&
75            (!MI->getDesc().isBranch() && !MI->getDesc().isReturn())) {
76       MachineInstr *NMI = &*MBBI;
77       MI = NMI;
78       DebugLoc ndl = NMI->getDebugLoc();
79       unsigned NPredReg = 0;
80       ARMCC::CondCodes NCC = getPredicate(NMI, NPredReg);
81       if (NCC == OCC) {
82         Mask |= (1 << Pos);
83       } else if (NCC != CC)
84         break;
85       --Pos;
86       ++MBBI;
87     }
88     Mask |= (1 << Pos);
89     MIB.addImm(Mask);
90     Modified = true;
91     ++NumITs;
92   }
93
94   return Modified;
95 }
96
97 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
98   const TargetMachine &TM = Fn.getTarget();
99   AFI = Fn.getInfo<ARMFunctionInfo>();
100   TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo());
101
102   if (!AFI->isThumbFunction())
103     return false;
104
105   bool Modified = false;
106   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
107        ++MFI) {
108     MachineBasicBlock &MBB = *MFI;
109     Modified |= InsertITBlocks(MBB);
110   }
111
112   return Modified;
113 }
114
115 /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
116 /// insertion pass.
117 FunctionPass *llvm::createThumb2ITBlockPass() {
118   return new Thumb2ITBlockPass();
119 }