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 {
29 ARMExpandPseudo() : MachineFunctionPass(ID) {}
31 const TargetInstrInfo *TII;
32 const TargetRegisterInfo *TRI;
34 virtual bool runOnMachineFunction(MachineFunction &Fn);
36 virtual const char *getPassName() const {
37 return "ARM pseudo instruction expansion pass";
41 void TransferImpOps(MachineInstr &OldMI,
42 MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI);
43 bool ExpandMBB(MachineBasicBlock &MBB);
45 char ARMExpandPseudo::ID = 0;
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();
56 const MachineOperand &MO = OldMI.getOperand(i);
57 assert(MO.isReg() && MO.getReg());
59 UseMI.addReg(MO.getReg(), getKillRegState(MO.isKill()));
61 DefMI.addReg(MO.getReg(),
62 getDefRegState(true) | getDeadRegState(MO.isDead()));
66 bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
67 bool Modified = false;
69 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
71 MachineInstr &MI = *MBBI;
72 MachineBasicBlock::iterator NMBBI = llvm::next(MBBI);
74 unsigned Opcode = MI.getOpcode();
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))
92 .addOperand(MI.getOperand(2));
93 TransferImpOps(MI, MIB1, MIB2);
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;
107 LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVi16),
109 HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVTi16))
110 .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
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);
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);
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();
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))
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))
154 getDefRegState(true) | getDeadRegState(DstIsDead))
155 .addReg(OddSrc, getKillRegState(SrcIsKill)));
156 TransferImpOps(MI, Even, Odd);
157 MI.eraseFromParent();
167 bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
168 TII = MF.getTarget().getInstrInfo();
169 TRI = MF.getTarget().getRegisterInfo();
171 bool Modified = false;
172 for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;
174 Modified |= ExpandMBB(*MFI);
178 /// createARMExpandPseudoPass - returns an instance of the pseudo instruction
180 FunctionPass *llvm::createARMExpandPseudoPass() {
181 return new ARMExpandPseudo();