ARMExpandPseudoInsts.cpp revision 431300797b84600fc9b4eb8ca283277d3e0674eb
1b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng//===-- ARMExpandPseudoInsts.cpp - Expand pseudo instructions -----*- C++ -*-=//
2b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng//
3b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng//                     The LLVM Compiler Infrastructure
4b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng//
5b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng// This file is distributed under the University of Illinois Open Source
6b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng// License. See LICENSE.TXT for details.
7b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng//
8b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng//===----------------------------------------------------------------------===//
9b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng//
10b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng// This file contains a pass that expand pseudo instructions into target
11b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng// instructions to allow proper scheduling, if-conversion, and other late
12b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng// optimizations. This pass should be run after register allocation but before
13b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng// post- regalloc scheduling pass.
14b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng//
15b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng//===----------------------------------------------------------------------===//
16b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
17b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng#define DEBUG_TYPE "arm-pseudo"
18b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng#include "ARM.h"
19b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng#include "ARMBaseInstrInfo.h"
20b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng#include "llvm/CodeGen/MachineFunctionPass.h"
21b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng#include "llvm/CodeGen/MachineInstrBuilder.h"
22b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
23b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Chengusing namespace llvm;
24b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
25b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Chengnamespace {
26b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  class ARMExpandPseudo : public MachineFunctionPass {
27b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  public:
28b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    static char ID;
29b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    ARMExpandPseudo() : MachineFunctionPass(&ID) {}
30b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
31b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    const TargetInstrInfo *TII;
32b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
33b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    virtual bool runOnMachineFunction(MachineFunction &Fn);
34b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
35b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    virtual const char *getPassName() const {
36b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      return "ARM pseudo instruction expansion pass";
37b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    }
38b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
39b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  private:
40431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng    void TransferImpOps(MachineInstr &OldMI,
41431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng                        MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI);
42b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    bool ExpandMBB(MachineBasicBlock &MBB);
43b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  };
44b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  char ARMExpandPseudo::ID = 0;
45b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng}
46b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
47431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng/// TransferImpOps - Transfer implicit operands on the pseudo instruction to
48431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng/// the instructions created from the expansion.
49431300797b84600fc9b4eb8ca283277d3e0674ebEvan Chengvoid ARMExpandPseudo::TransferImpOps(MachineInstr &OldMI,
50431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng                                     MachineInstrBuilder &UseMI,
51431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng                                     MachineInstrBuilder &DefMI) {
52431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng  const TargetInstrDesc &Desc = OldMI.getDesc();
53431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng  for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands();
54431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng       i != e; ++i) {
55431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng    const MachineOperand &MO = OldMI.getOperand(i);
56431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng    assert(MO.isReg() && MO.getReg());
57431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng    if (MO.isUse())
58431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      UseMI.addReg(MO.getReg(), getKillRegState(MO.isKill()));
59431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng    else
60431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      DefMI.addReg(MO.getReg(),
61431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng                   getDefRegState(true) | getDeadRegState(MO.isDead()));
62431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng  }
63431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng}
64431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng
65b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Chengbool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
66b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  bool Modified = false;
67b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
68b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
69b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  while (MBBI != E) {
70b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    MachineInstr &MI = *MBBI;
717896c9f436a4eda5ec15e882a7505ba482a2fcd0Chris Lattner    MachineBasicBlock::iterator NMBBI = llvm::next(MBBI);
72b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
73b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    unsigned Opcode = MI.getOpcode();
74b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    switch (Opcode) {
75b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    default: break;
76b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    case ARM::tLDRpci_pic:
77b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    case ARM::t2LDRpci_pic: {
78b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)
79b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng        ? ARM::tLDRpci : ARM::t2LDRpci;
80b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      unsigned DstReg = MI.getOperand(0).getReg();
81431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      bool DstIsDead = MI.getOperand(0).isDead();
82431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      MachineInstrBuilder MIB1 =
83431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
84431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng                               TII->get(NewLdOpc), DstReg)
85431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng                       .addOperand(MI.getOperand(1)));
86431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      (*MIB1).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
87431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
88431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng                                         TII->get(ARM::tPICADD))
89431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
90431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        .addReg(DstReg)
91431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        .addOperand(MI.getOperand(2));
92431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      TransferImpOps(MI, MIB1, MIB2);
93b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      MI.eraseFromParent();
94b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      Modified = true;
95b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      break;
96b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    }
97431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng
98b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    case ARM::t2MOVi32imm: {
99431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      unsigned PredReg = 0;
100431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
101b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      unsigned DstReg = MI.getOperand(0).getReg();
102431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      bool DstIsDead = MI.getOperand(0).isDead();
103431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      const MachineOperand &MO = MI.getOperand(1);
104431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      MachineInstrBuilder LO16, HI16;
105431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng
106431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVi16),
107431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng                     DstReg);
108431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVTi16))
109431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead))
110431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        .addReg(DstReg);
111431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng
112431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      if (MO.isImm()) {
113431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        unsigned Imm = MO.getImm();
114431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        unsigned Lo16 = Imm & 0xffff;
115431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        unsigned Hi16 = (Imm >> 16) & 0xffff;
116431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        LO16 = LO16.addImm(Lo16);
117431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        HI16 = HI16.addImm(Hi16);
118431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      } else {
119431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        const GlobalValue *GV = MO.getGlobal();
120431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        unsigned TF = MO.getTargetFlags();
121431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16);
122431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng        HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16);
123b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      }
124431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
125431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
126431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      LO16.addImm(Pred).addReg(PredReg);
127431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      HI16.addImm(Pred).addReg(PredReg);
128431300797b84600fc9b4eb8ca283277d3e0674ebEvan Cheng      TransferImpOps(MI, LO16, HI16);
129b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      MI.eraseFromParent();
130b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng      Modified = true;
131b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    }
132b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    }
133b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    MBBI = NMBBI;
134b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  }
135b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
136b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  return Modified;
137b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng}
138b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
139b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Chengbool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
140b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  TII = MF.getTarget().getInstrInfo();
141b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
142b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  bool Modified = false;
143b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;
144b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng       ++MFI)
145b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng    Modified |= ExpandMBB(*MFI);
146b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  return Modified;
147b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng}
148b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng
149b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng/// createARMExpandPseudoPass - returns an instance of the pseudo instruction
150b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng/// expansion pass.
151b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan ChengFunctionPass *llvm::createARMExpandPseudoPass() {
152b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng  return new ARMExpandPseudo();
153b9803a8fa65f043c96612fa9c5aeeee12739db2bEvan Cheng}
154