blob: 70ed67713e2648a5b1bba31b80482fbde739a04f [file] [log] [blame]
Evan Chengb9803a82009-11-06 23:52:48 +00001//===-- 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"
Chris Lattner4dbbe342010-07-20 21:17:29 +000022#include "llvm/Target/TargetRegisterInfo.h"
Evan Chengb9803a82009-11-06 23:52:48 +000023using namespace llvm;
24
25namespace {
26 class ARMExpandPseudo : public MachineFunctionPass {
27 public:
28 static char ID;
29 ARMExpandPseudo() : MachineFunctionPass(&ID) {}
30
31 const TargetInstrInfo *TII;
Evan Chengd929f772010-05-13 00:17:02 +000032 const TargetRegisterInfo *TRI;
Evan Chengb9803a82009-11-06 23:52:48 +000033
34 virtual bool runOnMachineFunction(MachineFunction &Fn);
35
36 virtual const char *getPassName() const {
37 return "ARM pseudo instruction expansion pass";
38 }
39
40 private:
Evan Cheng43130072010-05-12 23:13:12 +000041 void TransferImpOps(MachineInstr &OldMI,
42 MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI);
Evan Chengb9803a82009-11-06 23:52:48 +000043 bool ExpandMBB(MachineBasicBlock &MBB);
44 };
45 char ARMExpandPseudo::ID = 0;
46}
47
Evan Cheng43130072010-05-12 23:13:12 +000048/// TransferImpOps - Transfer implicit operands on the pseudo instruction to
49/// the instructions created from the expansion.
50void 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
Evan Chengb9803a82009-11-06 23:52:48 +000066bool 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;
Chris Lattner7896c9f2009-12-03 00:50:42 +000072 MachineBasicBlock::iterator NMBBI = llvm::next(MBBI);
Evan Chengb9803a82009-11-06 23:52:48 +000073
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();
Evan Cheng43130072010-05-12 23:13:12 +000082 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);
Evan Chengb9803a82009-11-06 23:52:48 +000094 MI.eraseFromParent();
95 Modified = true;
96 break;
97 }
Evan Cheng43130072010-05-12 23:13:12 +000098
Evan Chengb9803a82009-11-06 23:52:48 +000099 case ARM::t2MOVi32imm: {
Evan Cheng43130072010-05-12 23:13:12 +0000100 unsigned PredReg = 0;
101 ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
Evan Chengb9803a82009-11-06 23:52:48 +0000102 unsigned DstReg = MI.getOperand(0).getReg();
Evan Cheng43130072010-05-12 23:13:12 +0000103 bool DstIsDead = MI.getOperand(0).isDead();
104 const MachineOperand &MO = MI.getOperand(1);
105 MachineInstrBuilder LO16, HI16;
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000106
Evan Cheng43130072010-05-12 23:13:12 +0000107 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);
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000112
Evan Cheng43130072010-05-12 23:13:12 +0000113 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);
Evan Chengb9803a82009-11-06 23:52:48 +0000124 }
Evan Cheng43130072010-05-12 23:13:12 +0000125 (*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);
Evan Chengb9803a82009-11-06 23:52:48 +0000130 MI.eraseFromParent();
131 Modified = true;
Evan Chengd929f772010-05-13 00:17:02 +0000132 break;
133 }
134
135 case ARM::VMOVQQ: {
136 unsigned DstReg = MI.getOperand(0).getReg();
137 bool DstIsDead = MI.getOperand(0).isDead();
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +0000138 unsigned EvenDst = TRI->getSubReg(DstReg, ARM::qsub_0);
139 unsigned OddDst = TRI->getSubReg(DstReg, ARM::qsub_1);
Evan Chengd929f772010-05-13 00:17:02 +0000140 unsigned SrcReg = MI.getOperand(1).getReg();
141 bool SrcIsKill = MI.getOperand(1).isKill();
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +0000142 unsigned EvenSrc = TRI->getSubReg(SrcReg, ARM::qsub_0);
143 unsigned OddSrc = TRI->getSubReg(SrcReg, ARM::qsub_1);
Evan Chengd929f772010-05-13 00:17:02 +0000144 MachineInstrBuilder Even =
145 AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
146 TII->get(ARM::VMOVQ))
Jim Grosbach18f30e62010-06-02 21:53:11 +0000147 .addReg(EvenDst,
148 getDefRegState(true) | getDeadRegState(DstIsDead))
149 .addReg(EvenSrc, getKillRegState(SrcIsKill)));
Evan Chengd929f772010-05-13 00:17:02 +0000150 MachineInstrBuilder Odd =
151 AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
152 TII->get(ARM::VMOVQ))
Jim Grosbach18f30e62010-06-02 21:53:11 +0000153 .addReg(OddDst,
154 getDefRegState(true) | getDeadRegState(DstIsDead))
155 .addReg(OddSrc, getKillRegState(SrcIsKill)));
Evan Chengd929f772010-05-13 00:17:02 +0000156 TransferImpOps(MI, Even, Odd);
157 MI.eraseFromParent();
158 Modified = true;
Evan Chengb9803a82009-11-06 23:52:48 +0000159 }
Evan Chengb9803a82009-11-06 23:52:48 +0000160 }
161 MBBI = NMBBI;
162 }
163
164 return Modified;
165}
166
167bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
168 TII = MF.getTarget().getInstrInfo();
Evan Chengd929f772010-05-13 00:17:02 +0000169 TRI = MF.getTarget().getRegisterInfo();
Evan Chengb9803a82009-11-06 23:52:48 +0000170
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.
180FunctionPass *llvm::createARMExpandPseudoPass() {
181 return new ARMExpandPseudo();
182}