Don't put IT instruction before conditional branches.
[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/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 Thumb2InstrInfo *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 ARMCC::CondCodes getPredicate(const MachineInstr *MI,
44                               const Thumb2InstrInfo *TII) {
45   unsigned Opc = MI->getOpcode();
46   if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
47     return ARMCC::AL;
48   return TII->getPredicate(MI);
49 }
50
51 bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
52   bool Modified = false;
53
54   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
55   while (MBBI != E) {
56     MachineInstr *MI = &*MBBI;
57     ARMCC::CondCodes CC = getPredicate(MI, TII);
58     if (CC == ARMCC::AL) {
59       ++MBBI;
60       continue;
61     }
62
63     // Insert an IT instruction.
64     DebugLoc dl = MI->getDebugLoc();
65     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
66       .addImm(CC);
67     ++MBBI;
68
69     // Finalize IT mask. If the following instruction is not predicated or it's
70     // predicated on a condition that's not the same or the opposite of CC, then
71     // the mask is 0x8.
72     ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
73     unsigned Mask = 0x8;
74     while (MBBI != E || (Mask & 1)) {
75       ARMCC::CondCodes NCC = getPredicate(&*MBBI, TII);
76       if (NCC == CC) {
77         Mask >>= 1;
78         Mask |= 0x8;
79       } else if (NCC == OCC) {
80         Mask >>= 1;
81       } else {
82         break;
83       }
84       ++MBBI;
85     }
86     MIB.addImm(Mask);
87     Modified = true;
88     ++NumITs;
89   }
90
91   return Modified;
92 }
93
94 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
95   const TargetMachine &TM = Fn.getTarget();
96   AFI = Fn.getInfo<ARMFunctionInfo>();
97   TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo());
98
99   if (!AFI->isThumbFunction())
100     return false;
101
102   bool Modified = false;
103   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
104        ++MFI) {
105     MachineBasicBlock &MBB = *MFI;
106     Modified |= InsertITBlocks(MBB);
107   }
108
109   return Modified;
110 }
111
112 /// createThumb2ITBlockPass - returns and instance of the Thumb IT blocks
113 /// insertion pass.
114 FunctionPass *llvm::createThumb2ITBlockPass() {
115   return new Thumb2ITBlockPass();
116 }