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