MipsOptimizePICCall.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===--------- MipsOptimizePICCall.cpp - Optimize PIC Calls ---------------===//
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 pass eliminates unnecessary instructions that set up $gp and replace
11// instructions that load target function addresses with copy instructions.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "optimize-mips-pic-call"
16
17#include "Mips.h"
18#include "MCTargetDesc/MipsBaseInfo.h"
19#include "MipsMachineFunction.h"
20#include "MipsTargetMachine.h"
21#include "llvm/ADT/ScopedHashTable.h"
22#include "llvm/CodeGen/MachineDominators.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/Support/CommandLine.h"
25
26using namespace llvm;
27
28static cl::opt<bool> LoadTargetFromGOT("mips-load-target-from-got",
29                                       cl::init(true),
30                                       cl::desc("Load target address from GOT"),
31                                       cl::Hidden);
32
33static cl::opt<bool> EraseGPOpnd("mips-erase-gp-opnd",
34                                 cl::init(true), cl::desc("Erase GP Operand"),
35                                 cl::Hidden);
36
37namespace {
38typedef std::pair<unsigned, unsigned> CntRegP;
39typedef RecyclingAllocator<BumpPtrAllocator,
40                           ScopedHashTableVal<const Value *, CntRegP> >
41AllocatorTy;
42typedef ScopedHashTable<const Value *, CntRegP, DenseMapInfo<const Value *>,
43                        AllocatorTy> ScopedHTType;
44
45class MBBInfo {
46public:
47  MBBInfo(MachineDomTreeNode *N);
48  const MachineDomTreeNode *getNode() const;
49  bool isVisited() const;
50  void preVisit(ScopedHTType &ScopedHT);
51  void postVisit();
52
53private:
54  MachineDomTreeNode *Node;
55  ScopedHTType::ScopeTy *HTScope;
56};
57
58class OptimizePICCall : public MachineFunctionPass {
59public:
60  OptimizePICCall(TargetMachine &tm) : MachineFunctionPass(ID) {}
61
62  virtual const char *getPassName() const { return "Mips OptimizePICCall"; }
63
64  bool runOnMachineFunction(MachineFunction &F);
65
66  void getAnalysisUsage(AnalysisUsage &AU) const {
67    AU.addRequired<MachineDominatorTree>();
68    MachineFunctionPass::getAnalysisUsage(AU);
69  }
70
71private:
72  /// \brief Visit MBB.
73  bool visitNode(MBBInfo &MBBI);
74
75  /// \brief Test if MI jumps to a function via a register.
76  ///
77  /// Also, return the virtual register containing the target function's address
78  /// and the underlying object in Reg and Val respectively, if the function's
79  /// address can be resolved lazily.
80  bool isCallViaRegister(MachineInstr &MI, unsigned &Reg,
81                         const Value *&Val) const;
82
83  /// \brief Return the number of instructions that dominate the current
84  /// instruction and load the function address from object Entry.
85  unsigned getCount(const Value *Entry);
86
87  /// \brief Return the destination virtual register of the last instruction
88  /// that loads from object Entry.
89  unsigned getReg(const Value *Entry);
90
91  /// \brief Update ScopedHT.
92  void incCntAndSetReg(const Value *Entry, unsigned Reg);
93
94  ScopedHTType ScopedHT;
95  static char ID;
96};
97
98char OptimizePICCall::ID = 0;
99} // end of anonymous namespace
100
101/// Return the first MachineOperand of MI if it is a used virtual register.
102static MachineOperand *getCallTargetRegOpnd(MachineInstr &MI) {
103  if (MI.getNumOperands() == 0)
104    return 0;
105
106  MachineOperand &MO = MI.getOperand(0);
107
108  if (!MO.isReg() || !MO.isUse() ||
109      !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
110    return 0;
111
112  return &MO;
113}
114
115/// Return type of register Reg.
116static MVT::SimpleValueType getRegTy(unsigned Reg, MachineFunction &MF) {
117  const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(Reg);
118  assert(RC->vt_end() - RC->vt_begin() == 1);
119  return *RC->vt_begin();
120}
121
122/// Do the following transformation:
123///
124/// jalr $vreg
125/// =>
126/// copy $t9, $vreg
127/// jalr $t9
128static void setCallTargetReg(MachineBasicBlock *MBB,
129                             MachineBasicBlock::iterator I) {
130  MachineFunction &MF = *MBB->getParent();
131  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
132  unsigned SrcReg = I->getOperand(0).getReg();
133  unsigned DstReg = getRegTy(SrcReg, MF) == MVT::i32 ? Mips::T9 : Mips::T9_64;
134  BuildMI(*MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), DstReg)
135      .addReg(SrcReg);
136  I->getOperand(0).setReg(DstReg);
137}
138
139/// Search MI's operands for register GP and erase it.
140static void eraseGPOpnd(MachineInstr &MI) {
141  if (!EraseGPOpnd)
142    return;
143
144  MachineFunction &MF = *MI.getParent()->getParent();
145  MVT::SimpleValueType Ty = getRegTy(MI.getOperand(0).getReg(), MF);
146  unsigned Reg = Ty == MVT::i32 ? Mips::GP : Mips::GP_64;
147
148  for (unsigned I = 0; I < MI.getNumOperands(); ++I) {
149    MachineOperand &MO = MI.getOperand(I);
150    if (MO.isReg() && MO.getReg() == Reg) {
151      MI.RemoveOperand(I);
152      return;
153    }
154  }
155
156  llvm_unreachable(0);
157}
158
159MBBInfo::MBBInfo(MachineDomTreeNode *N) : Node(N), HTScope(0) {}
160
161const MachineDomTreeNode *MBBInfo::getNode() const { return Node; }
162
163bool MBBInfo::isVisited() const { return HTScope; }
164
165void MBBInfo::preVisit(ScopedHTType &ScopedHT) {
166  HTScope = new ScopedHTType::ScopeTy(ScopedHT);
167}
168
169void MBBInfo::postVisit() {
170  delete HTScope;
171}
172
173// OptimizePICCall methods.
174bool OptimizePICCall::runOnMachineFunction(MachineFunction &F) {
175  if (F.getTarget().getSubtarget<MipsSubtarget>().inMips16Mode())
176    return false;
177
178  // Do a pre-order traversal of the dominator tree.
179  MachineDominatorTree *MDT = &getAnalysis<MachineDominatorTree>();
180  bool Changed = false;
181
182  SmallVector<MBBInfo, 8> WorkList(1, MBBInfo(MDT->getRootNode()));
183
184  while (!WorkList.empty()) {
185    MBBInfo &MBBI = WorkList.back();
186
187    // If this MBB has already been visited, destroy the scope for the MBB and
188    // pop it from the work list.
189    if (MBBI.isVisited()) {
190      MBBI.postVisit();
191      WorkList.pop_back();
192      continue;
193    }
194
195    // Visit the MBB and add its children to the work list.
196    MBBI.preVisit(ScopedHT);
197    Changed |= visitNode(MBBI);
198    const MachineDomTreeNode *Node = MBBI.getNode();
199    const std::vector<MachineDomTreeNode *> &Children = Node->getChildren();
200    WorkList.append(Children.begin(), Children.end());
201  }
202
203  return Changed;
204}
205
206bool OptimizePICCall::visitNode(MBBInfo &MBBI) {
207  bool Changed = false;
208  MachineBasicBlock *MBB = MBBI.getNode()->getBlock();
209
210  for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
211       ++I) {
212    unsigned Reg;
213    const Value *Entry;
214
215    // Skip instructions that are not call instructions via registers.
216    if (!isCallViaRegister(*I, Reg, Entry))
217      continue;
218
219    Changed = true;
220    unsigned N = getCount(Entry);
221
222    if (N != 0) {
223      // If a function has been called more than twice, we do not have to emit a
224      // load instruction to get the function address from the GOT, but can
225      // instead reuse the address that has been loaded before.
226      if (N >= 2 && !LoadTargetFromGOT)
227        getCallTargetRegOpnd(*I)->setReg(getReg(Entry));
228
229      // Erase the $gp operand if this isn't the first time a function has
230      // been called. $gp needs to be set up only if the function call can go
231      // through a lazy binding stub.
232      eraseGPOpnd(*I);
233    }
234
235    if (Entry)
236      incCntAndSetReg(Entry, Reg);
237
238    setCallTargetReg(MBB, I);
239  }
240
241  return Changed;
242}
243
244bool OptimizePICCall::isCallViaRegister(MachineInstr &MI, unsigned &Reg,
245                                        const Value *&Val) const {
246  if (!MI.isCall())
247    return false;
248
249  MachineOperand *MO = getCallTargetRegOpnd(MI);
250
251  // Return if MI is not a function call via a register.
252  if (!MO)
253    return false;
254
255  // Get the instruction that loads the function address from the GOT.
256  Reg = MO->getReg();
257  Val = 0;
258  MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
259  MachineInstr *DefMI = MRI.getVRegDef(Reg);
260
261  assert(DefMI);
262
263  // See if DefMI is an instruction that loads from a GOT entry that holds the
264  // address of a lazy binding stub.
265  if (!DefMI->mayLoad() || DefMI->getNumOperands() < 3)
266    return true;
267
268  unsigned Flags = DefMI->getOperand(2).getTargetFlags();
269
270  if (Flags != MipsII::MO_GOT_CALL && Flags != MipsII::MO_CALL_LO16)
271    return true;
272
273  // Return the underlying object for the GOT entry in Val.
274  assert(DefMI->hasOneMemOperand());
275  Val = (*DefMI->memoperands_begin())->getValue();
276  return true;
277}
278
279unsigned OptimizePICCall::getCount(const Value *Entry) {
280  return ScopedHT.lookup(Entry).first;
281}
282
283unsigned OptimizePICCall::getReg(const Value *Entry) {
284  unsigned Reg = ScopedHT.lookup(Entry).second;
285  assert(Reg);
286  return Reg;
287}
288
289void OptimizePICCall::incCntAndSetReg(const Value *Entry, unsigned Reg) {
290  CntRegP P = ScopedHT.lookup(Entry);
291  ScopedHT.insert(Entry, std::make_pair(P.first + 1, Reg));
292}
293
294/// Return an OptimizeCall object.
295FunctionPass *llvm::createMipsOptimizePICCallPass(MipsTargetMachine &TM) {
296  return new OptimizePICCall(TM);
297}
298