Handle dbg_value instructions (i.e., skip them) when generating IT blocks.
[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     for (; MBBI != E && Pos &&
75            (!MI->getDesc().isBranch() && !MI->getDesc().isReturn()) ; ++MBBI) {
76       if (MBBI->isDebugValue())
77         continue;
78       MachineInstr *NMI = &*MBBI;
79       MI = NMI;
80       DebugLoc ndl = NMI->getDebugLoc();
81       unsigned NPredReg = 0;
82       ARMCC::CondCodes NCC = getPredicate(NMI, NPredReg);
83       if (NCC == CC || NCC == OCC)
84         Mask |= (NCC & 1) << Pos;
85       else
86         break;
87       --Pos;
88     }
89     Mask |= (1 << Pos);
90     // Tag along (firstcond[0] << 4) with the mask.
91     Mask |= (CC & 1) << 4;
92     MIB.addImm(Mask);
93     Modified = true;
94     ++NumITs;
95   }
96
97   return Modified;
98 }
99
100 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
101   const TargetMachine &TM = Fn.getTarget();
102   AFI = Fn.getInfo<ARMFunctionInfo>();
103   TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo());
104
105   if (!AFI->isThumbFunction())
106     return false;
107
108   bool Modified = false;
109   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
110        ++MFI) {
111     MachineBasicBlock &MBB = *MFI;
112     Modified |= InsertITBlocks(MBB);
113   }
114
115   return Modified;
116 }
117
118 /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
119 /// insertion pass.
120 FunctionPass *llvm::createThumb2ITBlockPass() {
121   return new Thumb2ITBlockPass();
122 }