| Evan Cheng | 207b246 | 2009-11-06 23:52:48 +0000 | [diff] [blame] | 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 | bool ExpandMBB(MachineBasicBlock &MBB); | 
|  | 41 | }; | 
|  | 42 | char ARMExpandPseudo::ID = 0; | 
|  | 43 | } | 
|  | 44 |  | 
|  | 45 | bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) { | 
|  | 46 | bool Modified = false; | 
|  | 47 |  | 
|  | 48 | MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); | 
|  | 49 | while (MBBI != E) { | 
|  | 50 | MachineInstr &MI = *MBBI; | 
| Chris Lattner | a48f44d | 2009-12-03 00:50:42 +0000 | [diff] [blame] | 51 | MachineBasicBlock::iterator NMBBI = llvm::next(MBBI); | 
| Evan Cheng | 207b246 | 2009-11-06 23:52:48 +0000 | [diff] [blame] | 52 |  | 
|  | 53 | unsigned Opcode = MI.getOpcode(); | 
|  | 54 | switch (Opcode) { | 
|  | 55 | default: break; | 
|  | 56 | case ARM::tLDRpci_pic: | 
|  | 57 | case ARM::t2LDRpci_pic: { | 
|  | 58 | unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic) | 
|  | 59 | ? ARM::tLDRpci : ARM::t2LDRpci; | 
|  | 60 | unsigned DstReg = MI.getOperand(0).getReg(); | 
|  | 61 | if (!MI.getOperand(0).isDead()) { | 
|  | 62 | MachineInstr *NewMI = | 
|  | 63 | AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), | 
|  | 64 | TII->get(NewLdOpc), DstReg) | 
|  | 65 | .addOperand(MI.getOperand(1))); | 
|  | 66 | NewMI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); | 
|  | 67 | BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPICADD)) | 
|  | 68 | .addReg(DstReg, getDefRegState(true)) | 
|  | 69 | .addReg(DstReg) | 
|  | 70 | .addOperand(MI.getOperand(2)); | 
|  | 71 | } | 
|  | 72 | MI.eraseFromParent(); | 
|  | 73 | Modified = true; | 
|  | 74 | break; | 
|  | 75 | } | 
|  | 76 | case ARM::t2MOVi32imm: { | 
|  | 77 | unsigned DstReg = MI.getOperand(0).getReg(); | 
| Evan Cheng | 207b246 | 2009-11-06 23:52:48 +0000 | [diff] [blame] | 78 | if (!MI.getOperand(0).isDead()) { | 
| Anton Korobeynikov | 2522908 | 2009-11-24 00:44:37 +0000 | [diff] [blame] | 79 | const MachineOperand &MO = MI.getOperand(1); | 
|  | 80 | MachineInstrBuilder LO16, HI16; | 
|  | 81 |  | 
|  | 82 | LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVi16), | 
|  | 83 | DstReg); | 
|  | 84 | HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVTi16)) | 
|  | 85 | .addReg(DstReg, getDefRegState(true)).addReg(DstReg); | 
|  | 86 |  | 
|  | 87 | if (MO.isImm()) { | 
|  | 88 | unsigned Imm = MO.getImm(); | 
|  | 89 | unsigned Lo16 = Imm & 0xffff; | 
|  | 90 | unsigned Hi16 = (Imm >> 16) & 0xffff; | 
|  | 91 | LO16 = LO16.addImm(Lo16); | 
|  | 92 | HI16 = HI16.addImm(Hi16); | 
|  | 93 | } else { | 
|  | 94 | GlobalValue *GV = MO.getGlobal(); | 
|  | 95 | unsigned TF = MO.getTargetFlags(); | 
|  | 96 | LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16); | 
|  | 97 | HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16); | 
|  | 98 | // FIXME: What's about memoperands? | 
|  | 99 | } | 
|  | 100 | AddDefaultPred(LO16); | 
|  | 101 | AddDefaultPred(HI16); | 
| Evan Cheng | 207b246 | 2009-11-06 23:52:48 +0000 | [diff] [blame] | 102 | } | 
|  | 103 | MI.eraseFromParent(); | 
|  | 104 | Modified = true; | 
|  | 105 | } | 
|  | 106 | // FIXME: expand t2MOVi32imm | 
|  | 107 | } | 
|  | 108 | MBBI = NMBBI; | 
|  | 109 | } | 
|  | 110 |  | 
|  | 111 | return Modified; | 
|  | 112 | } | 
|  | 113 |  | 
|  | 114 | bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) { | 
|  | 115 | TII = MF.getTarget().getInstrInfo(); | 
|  | 116 |  | 
|  | 117 | bool Modified = false; | 
|  | 118 | for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; | 
|  | 119 | ++MFI) | 
|  | 120 | Modified |= ExpandMBB(*MFI); | 
|  | 121 | return Modified; | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | /// createARMExpandPseudoPass - returns an instance of the pseudo instruction | 
|  | 125 | /// expansion pass. | 
|  | 126 | FunctionPass *llvm::createARMExpandPseudoPass() { | 
|  | 127 | return new ARMExpandPseudo(); | 
|  | 128 | } |