Remove includes of Support/Compiler.h that are no longer needed after the
[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     MachineBasicBlock::iterator
38       SplitT2MOV32imm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
39                       MachineInstr *MI, DebugLoc dl,
40                       unsigned PredReg, ARMCC::CondCodes CC);
41     bool InsertITBlocks(MachineBasicBlock &MBB);
42   };
43   char Thumb2ITBlockPass::ID = 0;
44 }
45
46 static ARMCC::CondCodes getPredicate(const MachineInstr *MI, unsigned &PredReg){
47   unsigned Opc = MI->getOpcode();
48   if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
49     return ARMCC::AL;
50   return llvm::getInstrPredicate(MI, PredReg);
51 }
52
53 MachineBasicBlock::iterator
54 Thumb2ITBlockPass::SplitT2MOV32imm(MachineBasicBlock &MBB,
55                                    MachineBasicBlock::iterator MBBI,
56                                    MachineInstr *MI,
57                                    DebugLoc dl, unsigned PredReg,
58                                    ARMCC::CondCodes CC) {
59   // Splitting t2MOVi32imm into a pair of t2MOVi16 + t2MOVTi16 here.
60   // The only reason it was a single instruction was so it could be
61   // re-materialized. We want to split it before this and the thumb2
62   // size reduction pass to make sure the IT mask is correct and expose
63   // width reduction opportunities. It doesn't make sense to do this in a 
64   // separate pass so here it is.
65   unsigned DstReg = MI->getOperand(0).getReg();
66   bool DstDead = MI->getOperand(0).isDead(); // Is this possible?
67   unsigned Imm = MI->getOperand(1).getImm();
68   unsigned Lo16 = Imm & 0xffff;
69   unsigned Hi16 = (Imm >> 16) & 0xffff;
70   BuildMI(MBB, MBBI, dl, TII->get(ARM::t2MOVi16), DstReg)
71     .addImm(Lo16).addImm(CC).addReg(PredReg);
72   BuildMI(MBB, MBBI, dl, TII->get(ARM::t2MOVTi16))
73     .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstDead))
74     .addReg(DstReg).addImm(Hi16).addImm(CC).addReg(PredReg);
75   --MBBI;
76   --MBBI;
77   MI->eraseFromParent();
78   return MBBI;
79 }
80
81 bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
82   bool Modified = false;
83
84   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
85   while (MBBI != E) {
86     MachineInstr *MI = &*MBBI;
87     DebugLoc dl = MI->getDebugLoc();
88     unsigned PredReg = 0;
89     ARMCC::CondCodes CC = getPredicate(MI, PredReg);
90
91     if (MI->getOpcode() == ARM::t2MOVi32imm) {
92       MBBI = SplitT2MOV32imm(MBB, MBBI, MI, dl, PredReg, CC);
93       continue;
94     }
95
96     if (CC == ARMCC::AL) {
97       ++MBBI;
98       continue;
99     }
100
101     // Insert an IT instruction.
102     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
103       .addImm(CC);
104     ++MBBI;
105
106     // Finalize IT mask.
107     ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
108     unsigned Mask = 0, Pos = 3;
109     // Branches, including tricky ones like LDM_RET, need to end an IT
110     // block so check the instruction we just put in the block.
111     while (MBBI != E && Pos &&
112            (!MI->getDesc().isBranch() && !MI->getDesc().isReturn())) {
113       MachineInstr *NMI = &*MBBI;
114       MI = NMI;
115       DebugLoc ndl = NMI->getDebugLoc();
116       unsigned NPredReg = 0;
117       ARMCC::CondCodes NCC = getPredicate(NMI, NPredReg);
118       if (NMI->getOpcode() == ARM::t2MOVi32imm) {
119         MBBI = SplitT2MOV32imm(MBB, MBBI, NMI, ndl, NPredReg, NCC);
120         continue;
121       }
122
123       if (NCC == OCC) {
124         Mask |= (1 << Pos);
125       } else if (NCC != CC)
126         break;
127       --Pos;
128       ++MBBI;
129     }
130     Mask |= (1 << Pos);
131     MIB.addImm(Mask);
132     Modified = true;
133     ++NumITs;
134   }
135
136   return Modified;
137 }
138
139 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
140   const TargetMachine &TM = Fn.getTarget();
141   AFI = Fn.getInfo<ARMFunctionInfo>();
142   TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo());
143
144   if (!AFI->isThumbFunction())
145     return false;
146
147   bool Modified = false;
148   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
149        ++MFI) {
150     MachineBasicBlock &MBB = *MFI;
151     Modified |= InsertITBlocks(MBB);
152   }
153
154   return Modified;
155 }
156
157 /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
158 /// insertion pass.
159 FunctionPass *llvm::createThumb2ITBlockPass() {
160   return new Thumb2ITBlockPass();
161 }