Don't use PassInfo* as a type identifier for passes. Instead, use the address of...
[oota-llvm.git] / lib / Target / ARM / ARMExpandPseudoInsts.cpp
1 //===-- ARMExpandPseudoInsts.cpp - Expand pseudo instructions -----*- 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 // This file contains a pass that expand pseudo instructions into target
11 // instructions to allow proper scheduling, if-conversion, and other late
12 // optimizations. This pass should be run after register allocation but before
13 // post- regalloc scheduling pass.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #define DEBUG_TYPE "arm-pseudo"
18 #include "ARM.h"
19 #include "ARMBaseInstrInfo.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/Target/TargetRegisterInfo.h"
23 using namespace llvm;
24
25 namespace {
26   class ARMExpandPseudo : public MachineFunctionPass {
27   public:
28     static char ID;
29     ARMExpandPseudo() : MachineFunctionPass(ID) {}
30
31     const TargetInstrInfo *TII;
32     const TargetRegisterInfo *TRI;
33
34     virtual bool runOnMachineFunction(MachineFunction &Fn);
35
36     virtual const char *getPassName() const {
37       return "ARM pseudo instruction expansion pass";
38     }
39
40   private:
41     void TransferImpOps(MachineInstr &OldMI,
42                         MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI);
43     bool ExpandMBB(MachineBasicBlock &MBB);
44   };
45   char ARMExpandPseudo::ID = 0;
46 }
47
48 /// TransferImpOps - Transfer implicit operands on the pseudo instruction to
49 /// the instructions created from the expansion.
50 void ARMExpandPseudo::TransferImpOps(MachineInstr &OldMI,
51                                      MachineInstrBuilder &UseMI,
52                                      MachineInstrBuilder &DefMI) {
53   const TargetInstrDesc &Desc = OldMI.getDesc();
54   for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands();
55        i != e; ++i) {
56     const MachineOperand &MO = OldMI.getOperand(i);
57     assert(MO.isReg() && MO.getReg());
58     if (MO.isUse())
59       UseMI.addReg(MO.getReg(), getKillRegState(MO.isKill()));
60     else
61       DefMI.addReg(MO.getReg(),
62                    getDefRegState(true) | getDeadRegState(MO.isDead()));
63   }
64 }
65
66 bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
67   bool Modified = false;
68
69   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
70   while (MBBI != E) {
71     MachineInstr &MI = *MBBI;
72     MachineBasicBlock::iterator NMBBI = llvm::next(MBBI);
73
74     unsigned Opcode = MI.getOpcode();
75     switch (Opcode) {
76     default: break;
77     case ARM::tLDRpci_pic: 
78     case ARM::t2LDRpci_pic: {
79       unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)
80         ? ARM::tLDRpci : ARM::t2LDRpci;
81       unsigned DstReg = MI.getOperand(0).getReg();
82       bool DstIsDead = MI.getOperand(0).isDead();
83       MachineInstrBuilder MIB1 =
84         AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
85                                TII->get(NewLdOpc), DstReg)
86                        .addOperand(MI.getOperand(1)));
87       (*MIB1).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
88       MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
89                                          TII->get(ARM::tPICADD))
90         .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
91         .addReg(DstReg)
92         .addOperand(MI.getOperand(2));
93       TransferImpOps(MI, MIB1, MIB2);
94       MI.eraseFromParent();
95       Modified = true;
96       break;
97     }
98
99     case ARM::t2MOVi32imm: {
100       unsigned PredReg = 0;
101       ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
102       unsigned DstReg = MI.getOperand(0).getReg();
103       bool DstIsDead = MI.getOperand(0).isDead();
104       const MachineOperand &MO = MI.getOperand(1);
105       MachineInstrBuilder LO16, HI16;
106
107       LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVi16),
108                      DstReg);
109       HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVTi16))
110         .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
111         .addReg(DstReg);
112
113       if (MO.isImm()) {
114         unsigned Imm = MO.getImm();
115         unsigned Lo16 = Imm & 0xffff;
116         unsigned Hi16 = (Imm >> 16) & 0xffff;
117         LO16 = LO16.addImm(Lo16);
118         HI16 = HI16.addImm(Hi16);
119       } else {
120         const GlobalValue *GV = MO.getGlobal();
121         unsigned TF = MO.getTargetFlags();
122         LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16);
123         HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16);
124       }
125       (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
126       (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
127       LO16.addImm(Pred).addReg(PredReg);
128       HI16.addImm(Pred).addReg(PredReg);
129       TransferImpOps(MI, LO16, HI16);
130       MI.eraseFromParent();
131       Modified = true;
132       break;
133     }
134
135     case ARM::VMOVQQ: {
136       unsigned DstReg = MI.getOperand(0).getReg();
137       bool DstIsDead = MI.getOperand(0).isDead();
138       unsigned EvenDst = TRI->getSubReg(DstReg, ARM::qsub_0);
139       unsigned OddDst  = TRI->getSubReg(DstReg, ARM::qsub_1);
140       unsigned SrcReg = MI.getOperand(1).getReg();
141       bool SrcIsKill = MI.getOperand(1).isKill();
142       unsigned EvenSrc = TRI->getSubReg(SrcReg, ARM::qsub_0);
143       unsigned OddSrc  = TRI->getSubReg(SrcReg, ARM::qsub_1);
144       MachineInstrBuilder Even =
145         AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
146                                TII->get(ARM::VMOVQ))
147                      .addReg(EvenDst,
148                              getDefRegState(true) | getDeadRegState(DstIsDead))
149                      .addReg(EvenSrc, getKillRegState(SrcIsKill)));
150       MachineInstrBuilder Odd =
151         AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
152                                TII->get(ARM::VMOVQ))
153                      .addReg(OddDst,
154                              getDefRegState(true) | getDeadRegState(DstIsDead))
155                      .addReg(OddSrc, getKillRegState(SrcIsKill)));
156       TransferImpOps(MI, Even, Odd);
157       MI.eraseFromParent();
158       Modified = true;
159     }
160     }
161     MBBI = NMBBI;
162   }
163
164   return Modified;
165 }
166
167 bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
168   TII = MF.getTarget().getInstrInfo();
169   TRI = MF.getTarget().getRegisterInfo();
170
171   bool Modified = false;
172   for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;
173        ++MFI)
174     Modified |= ExpandMBB(*MFI);
175   return Modified;
176 }
177
178 /// createARMExpandPseudoPass - returns an instance of the pseudo instruction
179 /// expansion pass.
180 FunctionPass *llvm::createARMExpandPseudoPass() {
181   return new ARMExpandPseudo();
182 }