Add a thumb2 pass to insert 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 "ARMInstrInfo.h"
13 #include "ARMMachineFunctionInfo.h"
14 #include "llvm/CodeGen/MachineInstr.h"
15 #include "llvm/CodeGen/MachineInstrBuilder.h"
16 #include "llvm/CodeGen/MachineFunctionPass.h"
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/ADT/Statistic.h"
19 using namespace llvm;
20
21 STATISTIC(NumITs,     "Number of IT blocks inserted");
22
23 namespace {
24   struct VISIBILITY_HIDDEN Thumb2ITBlockPass : public MachineFunctionPass {
25     static char ID;
26     Thumb2ITBlockPass() : MachineFunctionPass(&ID) {}
27
28     const ARMBaseInstrInfo *TII;
29     ARMFunctionInfo *AFI;
30
31     virtual bool runOnMachineFunction(MachineFunction &Fn);
32
33     virtual const char *getPassName() const {
34       return "Thumb IT blocks insertion pass";
35     }
36
37   private:
38     bool InsertITBlocks(MachineBasicBlock &MBB);
39   };
40   char Thumb2ITBlockPass::ID = 0;
41 }
42
43 bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
44   bool Modified = false;
45
46   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
47   while (MBBI != E) {
48     MachineInstr *MI = &*MBBI;
49     ARMCC::CondCodes CC = TII->getPredicate(MI);
50     if (CC == ARMCC::AL) {
51       ++MBBI;
52       continue;
53     }
54
55     // Insert an IT instruction.
56     DebugLoc dl = MI->getDebugLoc();
57     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
58       .addImm(CC);
59     ++MBBI;
60
61     // Finalize IT mask. If the following instruction is not predicated or it's
62     // predicated on a condition that's not the same or the opposite of CC, then
63     // the mask is 0x8.
64     ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
65     unsigned Mask = 0x8;
66     while (MBBI != E || (Mask & 1)) {
67       ARMCC::CondCodes NCC = TII->getPredicate(&*MBBI);
68       if (NCC == CC) {
69         Mask >>= 1;
70         Mask |= 0x8;
71       } else if (NCC == OCC) {
72         Mask >>= 1;
73       } else {
74         break;
75       }
76       ++MBBI;
77     }
78     MIB.addImm(Mask);
79     Modified = true;
80     ++NumITs;
81   }
82
83   return Modified;
84 }
85
86 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
87   const TargetMachine &TM = Fn.getTarget();
88   AFI = Fn.getInfo<ARMFunctionInfo>();
89   TII = static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
90
91   if (!AFI->isThumbFunction())
92     return false;
93
94   bool Modified = false;
95   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
96        ++MFI) {
97     MachineBasicBlock &MBB = *MFI;
98     Modified |= InsertITBlocks(MBB);
99   }
100
101   return Modified;
102 }
103
104 /// createThumb2ITBlockPass - returns and instance of the Thumb IT blocks
105 /// insertion pass.
106 FunctionPass *llvm::createThumb2ITBlockPass() {
107   return new Thumb2ITBlockPass();
108 }