Mark some pattern-less instructions as neverHasSideEffects.
[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
23 using namespace llvm;
24
25 namespace {
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:
40     void TransferImpOps(MachineInstr &OldMI,
41                         MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI);
42     bool ExpandMBB(MachineBasicBlock &MBB);
43   };
44   char ARMExpandPseudo::ID = 0;
45 }
46
47 /// TransferImpOps - Transfer implicit operands on the pseudo instruction to
48 /// the instructions created from the expansion.
49 void 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
65 bool 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;
71     MachineBasicBlock::iterator NMBBI = llvm::next(MBBI);
72
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();
81       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);
93       MI.eraseFromParent();
94       Modified = true;
95       break;
96     }
97
98     case ARM::t2MOVi32imm: {
99       unsigned PredReg = 0;
100       ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
101       unsigned DstReg = MI.getOperand(0).getReg();
102       bool DstIsDead = MI.getOperand(0).isDead();
103       const MachineOperand &MO = MI.getOperand(1);
104       MachineInstrBuilder LO16, HI16;
105
106       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);
111
112       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);
123       }
124       (*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);
129       MI.eraseFromParent();
130       Modified = true;
131     }
132     }
133     MBBI = NMBBI;
134   }
135
136   return Modified;
137 }
138
139 bool 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.
151 FunctionPass *llvm::createARMExpandPseudoPass() {
152   return new ARMExpandPseudo();
153 }