1 //===-- ARMExpandPseudoInsts.cpp - Expand pseudo instructions -----*- C++ -*-=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
15 //===----------------------------------------------------------------------===//
17 #define DEBUG_TYPE "arm-pseudo"
19 #include "ARMBaseInstrInfo.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/Target/TargetRegisterInfo.h"
26 class ARMExpandPseudo : public MachineFunctionPass {
27 // Constants for register spacing in NEON load/store instructions.
36 ARMExpandPseudo() : MachineFunctionPass(ID) {}
38 const TargetInstrInfo *TII;
39 const TargetRegisterInfo *TRI;
41 virtual bool runOnMachineFunction(MachineFunction &Fn);
43 virtual const char *getPassName() const {
44 return "ARM pseudo instruction expansion pass";
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);
54 char ARMExpandPseudo::ID = 0;
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();
65 const MachineOperand &MO = OldMI.getOperand(i);
66 assert(MO.isReg() && MO.getReg());
68 UseMI.addReg(MO.getReg(), getKillRegState(MO.isKill()));
70 DefMI.addReg(MO.getReg(),
71 getDefRegState(true) | getDeadRegState(MO.isDead()));
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();
83 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc));
86 bool DstIsDead = MI.getOperand(OpIdx).isDead();
87 unsigned DstReg = MI.getOperand(OpIdx++).getReg();
88 MIB.addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead));
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());
95 // Copy the am6offset operand.
96 bool OffsetIsKill = MI.getOperand(OpIdx).isKill();
97 MIB.addReg(MI.getOperand(OpIdx++).getReg(), getKillRegState(OffsetIsKill));
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);
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);
121 MIB.addReg(D0, getKillRegState(SrcIsKill))
122 .addReg(D1, getKillRegState(SrcIsKill))
123 .addReg(D2, getKillRegState(SrcIsKill));
125 MIB.addReg(D3, getKillRegState(SrcIsKill));
126 MIB = AddDefaultPred(MIB);
127 TransferImpOps(MI, MIB, MIB);
128 MI.eraseFromParent();
131 bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
132 bool Modified = false;
134 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
136 MachineInstr &MI = *MBBI;
137 MachineBasicBlock::iterator NMBBI = llvm::next(MBBI);
139 bool ModifiedOp = true;
140 unsigned Opcode = MI.getOpcode();
146 case ARM::tLDRpci_pic:
147 case ARM::t2LDRpci_pic: {
148 unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)
149 ? ARM::tLDRpci : ARM::t2LDRpci;
150 unsigned DstReg = MI.getOperand(0).getReg();
151 bool DstIsDead = MI.getOperand(0).isDead();
152 MachineInstrBuilder MIB1 =
153 AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
154 TII->get(NewLdOpc), DstReg)
155 .addOperand(MI.getOperand(1)));
156 (*MIB1).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
157 MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
158 TII->get(ARM::tPICADD))
159 .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
161 .addOperand(MI.getOperand(2));
162 TransferImpOps(MI, MIB1, MIB2);
163 MI.eraseFromParent();
167 case ARM::t2MOVi32imm: {
168 unsigned PredReg = 0;
169 ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
170 unsigned DstReg = MI.getOperand(0).getReg();
171 bool DstIsDead = MI.getOperand(0).isDead();
172 const MachineOperand &MO = MI.getOperand(1);
173 MachineInstrBuilder LO16, HI16;
175 LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVi16),
177 HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVTi16))
178 .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
182 unsigned Imm = MO.getImm();
183 unsigned Lo16 = Imm & 0xffff;
184 unsigned Hi16 = (Imm >> 16) & 0xffff;
185 LO16 = LO16.addImm(Lo16);
186 HI16 = HI16.addImm(Hi16);
188 const GlobalValue *GV = MO.getGlobal();
189 unsigned TF = MO.getTargetFlags();
190 LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16);
191 HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16);
193 (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
194 (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
195 LO16.addImm(Pred).addReg(PredReg);
196 HI16.addImm(Pred).addReg(PredReg);
197 TransferImpOps(MI, LO16, HI16);
198 MI.eraseFromParent();
203 unsigned DstReg = MI.getOperand(0).getReg();
204 bool DstIsDead = MI.getOperand(0).isDead();
205 unsigned EvenDst = TRI->getSubReg(DstReg, ARM::qsub_0);
206 unsigned OddDst = TRI->getSubReg(DstReg, ARM::qsub_1);
207 unsigned SrcReg = MI.getOperand(1).getReg();
208 bool SrcIsKill = MI.getOperand(1).isKill();
209 unsigned EvenSrc = TRI->getSubReg(SrcReg, ARM::qsub_0);
210 unsigned OddSrc = TRI->getSubReg(SrcReg, ARM::qsub_1);
211 MachineInstrBuilder Even =
212 AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
213 TII->get(ARM::VMOVQ))
215 getDefRegState(true) | getDeadRegState(DstIsDead))
216 .addReg(EvenSrc, getKillRegState(SrcIsKill)));
217 MachineInstrBuilder Odd =
218 AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
219 TII->get(ARM::VMOVQ))
221 getDefRegState(true) | getDeadRegState(DstIsDead))
222 .addReg(OddSrc, getKillRegState(SrcIsKill)));
223 TransferImpOps(MI, Even, Odd);
224 MI.eraseFromParent();
227 case ARM::VST3d8Pseudo:
228 ExpandVST(MBBI, ARM::VST3d8, false, SingleSpc, 3); break;
229 case ARM::VST3d16Pseudo:
230 ExpandVST(MBBI, ARM::VST3d16, false, SingleSpc, 3); break;
231 case ARM::VST3d32Pseudo:
232 ExpandVST(MBBI, ARM::VST3d32, false, SingleSpc, 3); break;
233 case ARM::VST1d64TPseudo:
234 ExpandVST(MBBI, ARM::VST1d64T, false, SingleSpc, 3); break;
235 case ARM::VST3d8Pseudo_UPD:
236 ExpandVST(MBBI, ARM::VST3d8_UPD, true, SingleSpc, 3); break;
237 case ARM::VST3d16Pseudo_UPD:
238 ExpandVST(MBBI, ARM::VST3d16_UPD, true, SingleSpc, 3); break;
239 case ARM::VST3d32Pseudo_UPD:
240 ExpandVST(MBBI, ARM::VST3d32_UPD, true, SingleSpc, 3); break;
241 case ARM::VST1d64TPseudo_UPD:
242 ExpandVST(MBBI, ARM::VST1d64T_UPD, true, SingleSpc, 3); break;
243 case ARM::VST3q8Pseudo_UPD:
244 ExpandVST(MBBI, ARM::VST3q8_UPD, true, EvenDblSpc, 3); break;
245 case ARM::VST3q16Pseudo_UPD:
246 ExpandVST(MBBI, ARM::VST3q16_UPD, true, EvenDblSpc, 3); break;
247 case ARM::VST3q32Pseudo_UPD:
248 ExpandVST(MBBI, ARM::VST3q32_UPD, true, EvenDblSpc, 3); break;
249 case ARM::VST3q8oddPseudo_UPD:
250 ExpandVST(MBBI, ARM::VST3q8_UPD, true, OddDblSpc, 3); break;
251 case ARM::VST3q16oddPseudo_UPD:
252 ExpandVST(MBBI, ARM::VST3q16_UPD, true, OddDblSpc, 3); break;
253 case ARM::VST3q32oddPseudo_UPD:
254 ExpandVST(MBBI, ARM::VST3q32_UPD, true, OddDblSpc, 3); break;
256 case ARM::VST4d8Pseudo:
257 ExpandVST(MBBI, ARM::VST4d8, false, SingleSpc, 4); break;
258 case ARM::VST4d16Pseudo:
259 ExpandVST(MBBI, ARM::VST4d16, false, SingleSpc, 4); break;
260 case ARM::VST4d32Pseudo:
261 ExpandVST(MBBI, ARM::VST4d32, false, SingleSpc, 4); break;
262 case ARM::VST1d64QPseudo:
263 ExpandVST(MBBI, ARM::VST1d64Q, false, SingleSpc, 4); break;
264 case ARM::VST4d8Pseudo_UPD:
265 ExpandVST(MBBI, ARM::VST4d8_UPD, true, SingleSpc, 4); break;
266 case ARM::VST4d16Pseudo_UPD:
267 ExpandVST(MBBI, ARM::VST4d16_UPD, true, SingleSpc, 4); break;
268 case ARM::VST4d32Pseudo_UPD:
269 ExpandVST(MBBI, ARM::VST4d32_UPD, true, SingleSpc, 4); break;
270 case ARM::VST1d64QPseudo_UPD:
271 ExpandVST(MBBI, ARM::VST1d64Q_UPD, true, SingleSpc, 4); break;
272 case ARM::VST4q8Pseudo_UPD:
273 ExpandVST(MBBI, ARM::VST4q8_UPD, true, EvenDblSpc, 4); break;
274 case ARM::VST4q16Pseudo_UPD:
275 ExpandVST(MBBI, ARM::VST4q16_UPD, true, EvenDblSpc, 4); break;
276 case ARM::VST4q32Pseudo_UPD:
277 ExpandVST(MBBI, ARM::VST4q32_UPD, true, EvenDblSpc, 4); break;
278 case ARM::VST4q8oddPseudo_UPD:
279 ExpandVST(MBBI, ARM::VST4q8_UPD, true, OddDblSpc, 4); break;
280 case ARM::VST4q16oddPseudo_UPD:
281 ExpandVST(MBBI, ARM::VST4q16_UPD, true, OddDblSpc, 4); break;
282 case ARM::VST4q32oddPseudo_UPD:
283 ExpandVST(MBBI, ARM::VST4q32_UPD, true, OddDblSpc, 4); break;
294 bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
295 TII = MF.getTarget().getInstrInfo();
296 TRI = MF.getTarget().getRegisterInfo();
298 bool Modified = false;
299 for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;
301 Modified |= ExpandMBB(*MFI);
305 /// createARMExpandPseudoPass - returns an instance of the pseudo instruction
307 FunctionPass *llvm::createARMExpandPseudoPass() {
308 return new ARMExpandPseudo();