blob: 7907905a0f254c4e4268fe5e3544b596d6c0a806 [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"
22
23using namespace llvm;
24
25namespace {
26 class ARMExpandPseudo : public MachineFunctionPass {
27 public:
28 static char ID;
29 ARMExpandPseudo() : MachineFunctionPass(&ID) {}
30
31 const TargetInstrInfo *TII;
32
33 virtual bool runOnMachineFunction(MachineFunction &Fn);
34
35 virtual const char *getPassName() const {
36 return "ARM pseudo instruction expansion pass";
37 }
38
39 private:
Evan Cheng43130072010-05-12 23:13:12 +000040 void TransferImpOps(MachineInstr &OldMI,
41 MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI);
Evan Chengb9803a82009-11-06 23:52:48 +000042 bool ExpandMBB(MachineBasicBlock &MBB);
43 };
44 char ARMExpandPseudo::ID = 0;
45}
46
Evan Cheng43130072010-05-12 23:13:12 +000047/// TransferImpOps - Transfer implicit operands on the pseudo instruction to
48/// the instructions created from the expansion.
49void ARMExpandPseudo::TransferImpOps(MachineInstr &OldMI,
50 MachineInstrBuilder &UseMI,
51 MachineInstrBuilder &DefMI) {
52 const TargetInstrDesc &Desc = OldMI.getDesc();
53 for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands();
54 i != e; ++i) {
55 const MachineOperand &MO = OldMI.getOperand(i);
56 assert(MO.isReg() && MO.getReg());
57 if (MO.isUse())
58 UseMI.addReg(MO.getReg(), getKillRegState(MO.isKill()));
59 else
60 DefMI.addReg(MO.getReg(),
61 getDefRegState(true) | getDeadRegState(MO.isDead()));
62 }
63}
64
Evan Chengb9803a82009-11-06 23:52:48 +000065bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
66 bool Modified = false;
67
68 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
69 while (MBBI != E) {
70 MachineInstr &MI = *MBBI;
Chris Lattner7896c9f2009-12-03 00:50:42 +000071 MachineBasicBlock::iterator NMBBI = llvm::next(MBBI);
Evan Chengb9803a82009-11-06 23:52:48 +000072
73 unsigned Opcode = MI.getOpcode();
74 switch (Opcode) {
75 default: break;
76 case ARM::tLDRpci_pic:
77 case ARM::t2LDRpci_pic: {
78 unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)
79 ? ARM::tLDRpci : ARM::t2LDRpci;
80 unsigned DstReg = MI.getOperand(0).getReg();
Evan Cheng43130072010-05-12 23:13:12 +000081 bool DstIsDead = MI.getOperand(0).isDead();
82 MachineInstrBuilder MIB1 =
83 AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
84 TII->get(NewLdOpc), DstReg)
85 .addOperand(MI.getOperand(1)));
86 (*MIB1).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
87 MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
88 TII->get(ARM::tPICADD))
89 .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
90 .addReg(DstReg)
91 .addOperand(MI.getOperand(2));
92 TransferImpOps(MI, MIB1, MIB2);
Evan Chengb9803a82009-11-06 23:52:48 +000093 MI.eraseFromParent();
94 Modified = true;
95 break;
96 }
Evan Cheng43130072010-05-12 23:13:12 +000097
Evan Chengb9803a82009-11-06 23:52:48 +000098 case ARM::t2MOVi32imm: {
Evan Cheng43130072010-05-12 23:13:12 +000099 unsigned PredReg = 0;
100 ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
Evan Chengb9803a82009-11-06 23:52:48 +0000101 unsigned DstReg = MI.getOperand(0).getReg();
Evan Cheng43130072010-05-12 23:13:12 +0000102 bool DstIsDead = MI.getOperand(0).isDead();
103 const MachineOperand &MO = MI.getOperand(1);
104 MachineInstrBuilder LO16, HI16;
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000105
Evan Cheng43130072010-05-12 23:13:12 +0000106 LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVi16),
107 DstReg);
108 HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVTi16))
109 .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
110 .addReg(DstReg);
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000111
Evan Cheng43130072010-05-12 23:13:12 +0000112 if (MO.isImm()) {
113 unsigned Imm = MO.getImm();
114 unsigned Lo16 = Imm & 0xffff;
115 unsigned Hi16 = (Imm >> 16) & 0xffff;
116 LO16 = LO16.addImm(Lo16);
117 HI16 = HI16.addImm(Hi16);
118 } else {
119 const GlobalValue *GV = MO.getGlobal();
120 unsigned TF = MO.getTargetFlags();
121 LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16);
122 HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16);
Evan Chengb9803a82009-11-06 23:52:48 +0000123 }
Evan Cheng43130072010-05-12 23:13:12 +0000124 (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
125 (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
126 LO16.addImm(Pred).addReg(PredReg);
127 HI16.addImm(Pred).addReg(PredReg);
128 TransferImpOps(MI, LO16, HI16);
Evan Chengb9803a82009-11-06 23:52:48 +0000129 MI.eraseFromParent();
130 Modified = true;
131 }
Evan Chengb9803a82009-11-06 23:52:48 +0000132 }
133 MBBI = NMBBI;
134 }
135
136 return Modified;
137}
138
139bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
140 TII = MF.getTarget().getInstrInfo();
141
142 bool Modified = false;
143 for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;
144 ++MFI)
145 Modified |= ExpandMBB(*MFI);
146 return Modified;
147}
148
149/// createARMExpandPseudoPass - returns an instance of the pseudo instruction
150/// expansion pass.
151FunctionPass *llvm::createARMExpandPseudoPass() {
152 return new ARMExpandPseudo();
153}