Make ARM and Thumb2 32-bit immediate materialization into a single 32-bit pseudo
[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 static ARMCC::CondCodes getPredicate(const MachineInstr *MI, unsigned &PredReg){
44   unsigned Opc = MI->getOpcode();
45   if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
46     return ARMCC::AL;
47   return llvm::getInstrPredicate(MI, PredReg);
48 }
49
50 bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
51   bool Modified = false;
52
53   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
54   while (MBBI != E) {
55     MachineInstr *MI = &*MBBI;
56     DebugLoc dl = MI->getDebugLoc();
57     unsigned PredReg = 0;
58     ARMCC::CondCodes CC = getPredicate(MI, PredReg);
59
60     // Splitting t2MOVi32imm into a pair of t2MOVi16 + t2MOVTi16 here.
61     // The only reason it was a single instruction was so it could be
62     // re-materialized. We want to split it before this and the thumb2
63     // size reduction pass to make sure the IT mask is correct and expose
64     // width reduction opportunities. It doesn't make sense to do this in a 
65     // separate pass so here it is.
66     if (MI->getOpcode() == ARM::t2MOVi32imm) {
67       unsigned DstReg = MI->getOperand(0).getReg();
68       bool DstDead = MI->getOperand(0).isDead(); // Is this possible?
69       unsigned Imm = MI->getOperand(1).getImm();
70       unsigned Lo16 = Imm & 0xffff;
71       unsigned Hi16 = (Imm >> 16) & 0xffff;
72       BuildMI(MBB, MBBI, dl, TII->get(ARM::t2MOVi16), DstReg)
73         .addImm(Lo16).addImm(CC).addReg(PredReg);
74       BuildMI(MBB, MBBI, dl, TII->get(ARM::t2MOVTi16))
75         .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstDead))
76         .addReg(DstReg).addImm(Hi16).addImm(CC).addReg(PredReg);
77       --MBBI;
78       --MBBI;
79       MI->eraseFromParent();
80       continue;
81     }
82
83     if (CC == ARMCC::AL) {
84       ++MBBI;
85       continue;
86     }
87
88     // Insert an IT instruction.
89     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
90       .addImm(CC);
91     ++MBBI;
92
93     // Finalize IT mask.
94     ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
95     unsigned Mask = 0, Pos = 3;
96     while (MBBI != E && Pos) {
97       unsigned Dummy = 0;
98       ARMCC::CondCodes NCC = getPredicate(&*MBBI, Dummy);
99       if (NCC == OCC) {
100         Mask |= (1 << Pos);
101       } else if (NCC != CC)
102         break;
103       --Pos;
104       ++MBBI;
105     }
106     Mask |= (1 << Pos);
107     MIB.addImm(Mask);
108     Modified = true;
109     ++NumITs;
110   }
111
112   return Modified;
113 }
114
115 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
116   const TargetMachine &TM = Fn.getTarget();
117   AFI = Fn.getInfo<ARMFunctionInfo>();
118   TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo());
119
120   if (!AFI->isThumbFunction())
121     return false;
122
123   bool Modified = false;
124   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
125        ++MFI) {
126     MachineBasicBlock &MBB = *MFI;
127     Modified |= InsertITBlocks(MBB);
128   }
129
130   return Modified;
131 }
132
133 /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
134 /// insertion pass.
135 FunctionPass *llvm::createThumb2ITBlockPass() {
136   return new Thumb2ITBlockPass();
137 }