When expanding NEON VST pseudo instructions, if the original super-register
[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     // Constants for register spacing in NEON load/store instructions.
28     enum NEONRegSpacing {
29       SingleSpc,
30       EvenDblSpc,
31       OddDblSpc
32     };
33
34   public:
35     static char ID;
36     ARMExpandPseudo() : MachineFunctionPass(ID) {}
37
38     const TargetInstrInfo *TII;
39     const TargetRegisterInfo *TRI;
40
41     virtual bool runOnMachineFunction(MachineFunction &Fn);
42
43     virtual const char *getPassName() const {
44       return "ARM pseudo instruction expansion pass";
45     }
46
47   private:
48     void TransferImpOps(MachineInstr &OldMI,
49                         MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI);
50     bool ExpandMBB(MachineBasicBlock &MBB);
51     void ExpandVST(MachineBasicBlock::iterator &MBBI, unsigned Opc,
52                    bool hasWriteBack, NEONRegSpacing RegSpc, unsigned NumRegs);
53   };
54   char ARMExpandPseudo::ID = 0;
55 }
56
57 /// TransferImpOps - Transfer implicit operands on the pseudo instruction to
58 /// the instructions created from the expansion.
59 void ARMExpandPseudo::TransferImpOps(MachineInstr &OldMI,
60                                      MachineInstrBuilder &UseMI,
61                                      MachineInstrBuilder &DefMI) {
62   const TargetInstrDesc &Desc = OldMI.getDesc();
63   for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands();
64        i != e; ++i) {
65     const MachineOperand &MO = OldMI.getOperand(i);
66     assert(MO.isReg() && MO.getReg());
67     if (MO.isUse())
68       UseMI.addReg(MO.getReg(), getKillRegState(MO.isKill()));
69     else
70       DefMI.addReg(MO.getReg(),
71                    getDefRegState(true) | getDeadRegState(MO.isDead()));
72   }
73 }
74
75 /// ExpandVST - Translate VST pseudo instructions with Q, QQ or QQQQ register
76 /// operands to real VST instructions with D register operands.
77 void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI,
78                                 unsigned Opc, bool hasWriteBack,
79                                 NEONRegSpacing RegSpc, unsigned NumRegs) {
80   MachineInstr &MI = *MBBI;
81   MachineBasicBlock &MBB = *MI.getParent();
82
83   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc));
84   unsigned OpIdx = 0;
85   if (hasWriteBack) {
86     bool DstIsDead = MI.getOperand(OpIdx).isDead();
87     unsigned DstReg = MI.getOperand(OpIdx++).getReg();
88     MIB.addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead));
89   }
90   // Copy the addrmode6 operands.
91   bool AddrIsKill = MI.getOperand(OpIdx).isKill();
92   MIB.addReg(MI.getOperand(OpIdx++).getReg(), getKillRegState(AddrIsKill));
93   MIB.addImm(MI.getOperand(OpIdx++).getImm());
94   if (hasWriteBack) {
95     // Copy the am6offset operand.
96     bool OffsetIsKill = MI.getOperand(OpIdx).isKill();
97     MIB.addReg(MI.getOperand(OpIdx++).getReg(), getKillRegState(OffsetIsKill));
98   }
99
100   bool SrcIsKill = MI.getOperand(OpIdx).isKill();
101   unsigned SrcReg = MI.getOperand(OpIdx).getReg();
102   unsigned D0, D1, D2, D3;
103   if (RegSpc == SingleSpc) {
104     D0 = TRI->getSubReg(SrcReg, ARM::dsub_0);
105     D1 = TRI->getSubReg(SrcReg, ARM::dsub_1);
106     D2 = TRI->getSubReg(SrcReg, ARM::dsub_2);
107     D3 = TRI->getSubReg(SrcReg, ARM::dsub_3);
108   } else if (RegSpc == EvenDblSpc) {
109     D0 = TRI->getSubReg(SrcReg, ARM::dsub_0);
110     D1 = TRI->getSubReg(SrcReg, ARM::dsub_2);
111     D2 = TRI->getSubReg(SrcReg, ARM::dsub_4);
112     D3 = TRI->getSubReg(SrcReg, ARM::dsub_6);
113   } else {
114     assert(RegSpc == OddDblSpc && "unknown register spacing for VST");
115     D0 = TRI->getSubReg(SrcReg, ARM::dsub_1);
116     D1 = TRI->getSubReg(SrcReg, ARM::dsub_3);
117     D2 = TRI->getSubReg(SrcReg, ARM::dsub_5);
118     D3 = TRI->getSubReg(SrcReg, ARM::dsub_7);
119   } 
120
121   MIB.addReg(D0).addReg(D1);
122   if (NumRegs > 2)
123     MIB.addReg(D2);
124   if (NumRegs > 3)
125     MIB.addReg(D3);
126   MIB = AddDefaultPred(MIB);
127   TransferImpOps(MI, MIB, MIB);
128   if (SrcIsKill)
129     // Add an implicit kill for the super-reg.
130     (*MIB).addRegisterKilled(SrcReg, TRI, true);
131   MI.eraseFromParent();
132 }
133
134 bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
135   bool Modified = false;
136
137   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
138   while (MBBI != E) {
139     MachineInstr &MI = *MBBI;
140     MachineBasicBlock::iterator NMBBI = llvm::next(MBBI);
141
142     bool ModifiedOp = true;
143     unsigned Opcode = MI.getOpcode();
144     switch (Opcode) {
145     default:
146       ModifiedOp = false;
147       break;
148
149     case ARM::tLDRpci_pic: 
150     case ARM::t2LDRpci_pic: {
151       unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)
152         ? ARM::tLDRpci : ARM::t2LDRpci;
153       unsigned DstReg = MI.getOperand(0).getReg();
154       bool DstIsDead = MI.getOperand(0).isDead();
155       MachineInstrBuilder MIB1 =
156         AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
157                                TII->get(NewLdOpc), DstReg)
158                        .addOperand(MI.getOperand(1)));
159       (*MIB1).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
160       MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
161                                          TII->get(ARM::tPICADD))
162         .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
163         .addReg(DstReg)
164         .addOperand(MI.getOperand(2));
165       TransferImpOps(MI, MIB1, MIB2);
166       MI.eraseFromParent();
167       break;
168     }
169
170     case ARM::t2MOVi32imm: {
171       unsigned PredReg = 0;
172       ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
173       unsigned DstReg = MI.getOperand(0).getReg();
174       bool DstIsDead = MI.getOperand(0).isDead();
175       const MachineOperand &MO = MI.getOperand(1);
176       MachineInstrBuilder LO16, HI16;
177
178       LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVi16),
179                      DstReg);
180       HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVTi16))
181         .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
182         .addReg(DstReg);
183
184       if (MO.isImm()) {
185         unsigned Imm = MO.getImm();
186         unsigned Lo16 = Imm & 0xffff;
187         unsigned Hi16 = (Imm >> 16) & 0xffff;
188         LO16 = LO16.addImm(Lo16);
189         HI16 = HI16.addImm(Hi16);
190       } else {
191         const GlobalValue *GV = MO.getGlobal();
192         unsigned TF = MO.getTargetFlags();
193         LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16);
194         HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16);
195       }
196       (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
197       (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
198       LO16.addImm(Pred).addReg(PredReg);
199       HI16.addImm(Pred).addReg(PredReg);
200       TransferImpOps(MI, LO16, HI16);
201       MI.eraseFromParent();
202       break;
203     }
204
205     case ARM::VMOVQQ: {
206       unsigned DstReg = MI.getOperand(0).getReg();
207       bool DstIsDead = MI.getOperand(0).isDead();
208       unsigned EvenDst = TRI->getSubReg(DstReg, ARM::qsub_0);
209       unsigned OddDst  = TRI->getSubReg(DstReg, ARM::qsub_1);
210       unsigned SrcReg = MI.getOperand(1).getReg();
211       bool SrcIsKill = MI.getOperand(1).isKill();
212       unsigned EvenSrc = TRI->getSubReg(SrcReg, ARM::qsub_0);
213       unsigned OddSrc  = TRI->getSubReg(SrcReg, ARM::qsub_1);
214       MachineInstrBuilder Even =
215         AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
216                                TII->get(ARM::VMOVQ))
217                      .addReg(EvenDst,
218                              getDefRegState(true) | getDeadRegState(DstIsDead))
219                      .addReg(EvenSrc, getKillRegState(SrcIsKill)));
220       MachineInstrBuilder Odd =
221         AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
222                                TII->get(ARM::VMOVQ))
223                      .addReg(OddDst,
224                              getDefRegState(true) | getDeadRegState(DstIsDead))
225                      .addReg(OddSrc, getKillRegState(SrcIsKill)));
226       TransferImpOps(MI, Even, Odd);
227       MI.eraseFromParent();
228     }
229
230     case ARM::VST1q8Pseudo:
231       ExpandVST(MBBI, ARM::VST1q8, false, SingleSpc, 2); break;
232     case ARM::VST1q16Pseudo:
233       ExpandVST(MBBI, ARM::VST1q16, false, SingleSpc, 2); break;
234     case ARM::VST1q32Pseudo:
235       ExpandVST(MBBI, ARM::VST1q32, false, SingleSpc, 2); break;
236     case ARM::VST1q64Pseudo:
237       ExpandVST(MBBI, ARM::VST1q64, false, SingleSpc, 2); break;
238     case ARM::VST1q8Pseudo_UPD:
239       ExpandVST(MBBI, ARM::VST1q8_UPD, true, SingleSpc, 2); break;
240     case ARM::VST1q16Pseudo_UPD:
241       ExpandVST(MBBI, ARM::VST1q16_UPD, true, SingleSpc, 2); break;
242     case ARM::VST1q32Pseudo_UPD:
243       ExpandVST(MBBI, ARM::VST1q32_UPD, true, SingleSpc, 2); break;
244     case ARM::VST1q64Pseudo_UPD:
245       ExpandVST(MBBI, ARM::VST1q64_UPD, true, SingleSpc, 2); break;
246
247     case ARM::VST2d8Pseudo:
248       ExpandVST(MBBI, ARM::VST2d8, false, SingleSpc, 2); break;
249     case ARM::VST2d16Pseudo:
250       ExpandVST(MBBI, ARM::VST2d16, false, SingleSpc, 2); break;
251     case ARM::VST2d32Pseudo:
252       ExpandVST(MBBI, ARM::VST2d32, false, SingleSpc, 2); break;
253     case ARM::VST2q8Pseudo:
254       ExpandVST(MBBI, ARM::VST2q8, false, SingleSpc, 4); break;
255     case ARM::VST2q16Pseudo:
256       ExpandVST(MBBI, ARM::VST2q16, false, SingleSpc, 4); break;
257     case ARM::VST2q32Pseudo:
258       ExpandVST(MBBI, ARM::VST2q32, false, SingleSpc, 4); break;
259     case ARM::VST2d8Pseudo_UPD:
260       ExpandVST(MBBI, ARM::VST2d8_UPD, true, SingleSpc, 2); break;
261     case ARM::VST2d16Pseudo_UPD:
262       ExpandVST(MBBI, ARM::VST2d16_UPD, true, SingleSpc, 2); break;
263     case ARM::VST2d32Pseudo_UPD:
264       ExpandVST(MBBI, ARM::VST2d32_UPD, true, SingleSpc, 2); break;
265     case ARM::VST2q8Pseudo_UPD:
266       ExpandVST(MBBI, ARM::VST2q8_UPD, true, SingleSpc, 4); break;
267     case ARM::VST2q16Pseudo_UPD:
268       ExpandVST(MBBI, ARM::VST2q16_UPD, true, SingleSpc, 4); break;
269     case ARM::VST2q32Pseudo_UPD:
270       ExpandVST(MBBI, ARM::VST2q32_UPD, true, SingleSpc, 4); break;
271
272     case ARM::VST3d8Pseudo:
273       ExpandVST(MBBI, ARM::VST3d8, false, SingleSpc, 3); break;
274     case ARM::VST3d16Pseudo:
275       ExpandVST(MBBI, ARM::VST3d16, false, SingleSpc, 3); break;
276     case ARM::VST3d32Pseudo:
277       ExpandVST(MBBI, ARM::VST3d32, false, SingleSpc, 3); break;
278     case ARM::VST1d64TPseudo:
279       ExpandVST(MBBI, ARM::VST1d64T, false, SingleSpc, 3); break;
280     case ARM::VST3d8Pseudo_UPD:
281       ExpandVST(MBBI, ARM::VST3d8_UPD, true, SingleSpc, 3); break;
282     case ARM::VST3d16Pseudo_UPD:
283       ExpandVST(MBBI, ARM::VST3d16_UPD, true, SingleSpc, 3); break;
284     case ARM::VST3d32Pseudo_UPD:
285       ExpandVST(MBBI, ARM::VST3d32_UPD, true, SingleSpc, 3); break;
286     case ARM::VST1d64TPseudo_UPD:
287       ExpandVST(MBBI, ARM::VST1d64T_UPD, true, SingleSpc, 3); break;
288     case ARM::VST3q8Pseudo_UPD:
289       ExpandVST(MBBI, ARM::VST3q8_UPD, true, EvenDblSpc, 3); break;
290     case ARM::VST3q16Pseudo_UPD:
291       ExpandVST(MBBI, ARM::VST3q16_UPD, true, EvenDblSpc, 3); break;
292     case ARM::VST3q32Pseudo_UPD:
293       ExpandVST(MBBI, ARM::VST3q32_UPD, true, EvenDblSpc, 3); break;
294     case ARM::VST3q8oddPseudo_UPD:
295       ExpandVST(MBBI, ARM::VST3q8_UPD, true, OddDblSpc, 3); break;
296     case ARM::VST3q16oddPseudo_UPD:
297       ExpandVST(MBBI, ARM::VST3q16_UPD, true, OddDblSpc, 3); break;
298     case ARM::VST3q32oddPseudo_UPD:
299       ExpandVST(MBBI, ARM::VST3q32_UPD, true, OddDblSpc, 3); break;
300
301     case ARM::VST4d8Pseudo:
302       ExpandVST(MBBI, ARM::VST4d8, false, SingleSpc, 4); break;
303     case ARM::VST4d16Pseudo:
304       ExpandVST(MBBI, ARM::VST4d16, false, SingleSpc, 4); break;
305     case ARM::VST4d32Pseudo:
306       ExpandVST(MBBI, ARM::VST4d32, false, SingleSpc, 4); break;
307     case ARM::VST1d64QPseudo:
308       ExpandVST(MBBI, ARM::VST1d64Q, false, SingleSpc, 4); break;
309     case ARM::VST4d8Pseudo_UPD:
310       ExpandVST(MBBI, ARM::VST4d8_UPD, true, SingleSpc, 4); break;
311     case ARM::VST4d16Pseudo_UPD:
312       ExpandVST(MBBI, ARM::VST4d16_UPD, true, SingleSpc, 4); break;
313     case ARM::VST4d32Pseudo_UPD:
314       ExpandVST(MBBI, ARM::VST4d32_UPD, true, SingleSpc, 4); break;
315     case ARM::VST1d64QPseudo_UPD:
316       ExpandVST(MBBI, ARM::VST1d64Q_UPD, true, SingleSpc, 4); break;
317     case ARM::VST4q8Pseudo_UPD:
318       ExpandVST(MBBI, ARM::VST4q8_UPD, true, EvenDblSpc, 4); break;
319     case ARM::VST4q16Pseudo_UPD:
320       ExpandVST(MBBI, ARM::VST4q16_UPD, true, EvenDblSpc, 4); break;
321     case ARM::VST4q32Pseudo_UPD:
322       ExpandVST(MBBI, ARM::VST4q32_UPD, true, EvenDblSpc, 4); break;
323     case ARM::VST4q8oddPseudo_UPD:
324       ExpandVST(MBBI, ARM::VST4q8_UPD, true, OddDblSpc, 4); break;
325     case ARM::VST4q16oddPseudo_UPD:
326       ExpandVST(MBBI, ARM::VST4q16_UPD, true, OddDblSpc, 4); break;
327     case ARM::VST4q32oddPseudo_UPD:
328       ExpandVST(MBBI, ARM::VST4q32_UPD, true, OddDblSpc, 4); break;
329     }
330
331     if (ModifiedOp)
332       Modified = true;
333     MBBI = NMBBI;
334   }
335
336   return Modified;
337 }
338
339 bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
340   TII = MF.getTarget().getInstrInfo();
341   TRI = MF.getTarget().getRegisterInfo();
342
343   bool Modified = false;
344   for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;
345        ++MFI)
346     Modified |= ExpandMBB(*MFI);
347   return Modified;
348 }
349
350 /// createARMExpandPseudoPass - returns an instance of the pseudo instruction
351 /// expansion pass.
352 FunctionPass *llvm::createARMExpandPseudoPass() {
353   return new ARMExpandPseudo();
354 }