LLVM API Documentation
00001 //===--------- MipsOptimizePICCall.cpp - Optimize PIC Calls ---------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This pass eliminates unnecessary instructions that set up $gp and replace 00011 // instructions that load target function addresses with copy instructions. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "Mips.h" 00016 #include "MCTargetDesc/MipsBaseInfo.h" 00017 #include "MipsMachineFunction.h" 00018 #include "MipsTargetMachine.h" 00019 #include "llvm/ADT/ScopedHashTable.h" 00020 #include "llvm/CodeGen/MachineDominators.h" 00021 #include "llvm/CodeGen/MachineRegisterInfo.h" 00022 #include "llvm/Support/CommandLine.h" 00023 00024 using namespace llvm; 00025 00026 #define DEBUG_TYPE "optimize-mips-pic-call" 00027 00028 static cl::opt<bool> LoadTargetFromGOT("mips-load-target-from-got", 00029 cl::init(true), 00030 cl::desc("Load target address from GOT"), 00031 cl::Hidden); 00032 00033 static cl::opt<bool> EraseGPOpnd("mips-erase-gp-opnd", 00034 cl::init(true), cl::desc("Erase GP Operand"), 00035 cl::Hidden); 00036 00037 namespace { 00038 typedef PointerUnion<const Value *, const PseudoSourceValue *> ValueType; 00039 00040 typedef std::pair<unsigned, unsigned> CntRegP; 00041 typedef RecyclingAllocator<BumpPtrAllocator, 00042 ScopedHashTableVal<ValueType, CntRegP> > 00043 AllocatorTy; 00044 typedef ScopedHashTable<ValueType, CntRegP, DenseMapInfo<ValueType>, 00045 AllocatorTy> ScopedHTType; 00046 00047 class MBBInfo { 00048 public: 00049 MBBInfo(MachineDomTreeNode *N); 00050 const MachineDomTreeNode *getNode() const; 00051 bool isVisited() const; 00052 void preVisit(ScopedHTType &ScopedHT); 00053 void postVisit(); 00054 00055 private: 00056 MachineDomTreeNode *Node; 00057 ScopedHTType::ScopeTy *HTScope; 00058 }; 00059 00060 class OptimizePICCall : public MachineFunctionPass { 00061 public: 00062 OptimizePICCall(TargetMachine &tm) : MachineFunctionPass(ID) {} 00063 00064 const char *getPassName() const override { return "Mips OptimizePICCall"; } 00065 00066 bool runOnMachineFunction(MachineFunction &F) override; 00067 00068 void getAnalysisUsage(AnalysisUsage &AU) const override { 00069 AU.addRequired<MachineDominatorTree>(); 00070 MachineFunctionPass::getAnalysisUsage(AU); 00071 } 00072 00073 private: 00074 /// \brief Visit MBB. 00075 bool visitNode(MBBInfo &MBBI); 00076 00077 /// \brief Test if MI jumps to a function via a register. 00078 /// 00079 /// Also, return the virtual register containing the target function's address 00080 /// and the underlying object in Reg and Val respectively, if the function's 00081 /// address can be resolved lazily. 00082 bool isCallViaRegister(MachineInstr &MI, unsigned &Reg, 00083 ValueType &Val) const; 00084 00085 /// \brief Return the number of instructions that dominate the current 00086 /// instruction and load the function address from object Entry. 00087 unsigned getCount(ValueType Entry); 00088 00089 /// \brief Return the destination virtual register of the last instruction 00090 /// that loads from object Entry. 00091 unsigned getReg(ValueType Entry); 00092 00093 /// \brief Update ScopedHT. 00094 void incCntAndSetReg(ValueType Entry, unsigned Reg); 00095 00096 ScopedHTType ScopedHT; 00097 static char ID; 00098 }; 00099 00100 char OptimizePICCall::ID = 0; 00101 } // end of anonymous namespace 00102 00103 /// Return the first MachineOperand of MI if it is a used virtual register. 00104 static MachineOperand *getCallTargetRegOpnd(MachineInstr &MI) { 00105 if (MI.getNumOperands() == 0) 00106 return nullptr; 00107 00108 MachineOperand &MO = MI.getOperand(0); 00109 00110 if (!MO.isReg() || !MO.isUse() || 00111 !TargetRegisterInfo::isVirtualRegister(MO.getReg())) 00112 return nullptr; 00113 00114 return &MO; 00115 } 00116 00117 /// Return type of register Reg. 00118 static MVT::SimpleValueType getRegTy(unsigned Reg, MachineFunction &MF) { 00119 const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(Reg); 00120 assert(RC->vt_end() - RC->vt_begin() == 1); 00121 return *RC->vt_begin(); 00122 } 00123 00124 /// Do the following transformation: 00125 /// 00126 /// jalr $vreg 00127 /// => 00128 /// copy $t9, $vreg 00129 /// jalr $t9 00130 static void setCallTargetReg(MachineBasicBlock *MBB, 00131 MachineBasicBlock::iterator I) { 00132 MachineFunction &MF = *MBB->getParent(); 00133 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 00134 unsigned SrcReg = I->getOperand(0).getReg(); 00135 unsigned DstReg = getRegTy(SrcReg, MF) == MVT::i32 ? Mips::T9 : Mips::T9_64; 00136 BuildMI(*MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), DstReg) 00137 .addReg(SrcReg); 00138 I->getOperand(0).setReg(DstReg); 00139 } 00140 00141 /// Search MI's operands for register GP and erase it. 00142 static void eraseGPOpnd(MachineInstr &MI) { 00143 if (!EraseGPOpnd) 00144 return; 00145 00146 MachineFunction &MF = *MI.getParent()->getParent(); 00147 MVT::SimpleValueType Ty = getRegTy(MI.getOperand(0).getReg(), MF); 00148 unsigned Reg = Ty == MVT::i32 ? Mips::GP : Mips::GP_64; 00149 00150 for (unsigned I = 0; I < MI.getNumOperands(); ++I) { 00151 MachineOperand &MO = MI.getOperand(I); 00152 if (MO.isReg() && MO.getReg() == Reg) { 00153 MI.RemoveOperand(I); 00154 return; 00155 } 00156 } 00157 00158 llvm_unreachable(nullptr); 00159 } 00160 00161 MBBInfo::MBBInfo(MachineDomTreeNode *N) : Node(N), HTScope(nullptr) {} 00162 00163 const MachineDomTreeNode *MBBInfo::getNode() const { return Node; } 00164 00165 bool MBBInfo::isVisited() const { return HTScope; } 00166 00167 void MBBInfo::preVisit(ScopedHTType &ScopedHT) { 00168 HTScope = new ScopedHTType::ScopeTy(ScopedHT); 00169 } 00170 00171 void MBBInfo::postVisit() { 00172 delete HTScope; 00173 } 00174 00175 // OptimizePICCall methods. 00176 bool OptimizePICCall::runOnMachineFunction(MachineFunction &F) { 00177 if (F.getTarget().getSubtarget<MipsSubtarget>().inMips16Mode()) 00178 return false; 00179 00180 // Do a pre-order traversal of the dominator tree. 00181 MachineDominatorTree *MDT = &getAnalysis<MachineDominatorTree>(); 00182 bool Changed = false; 00183 00184 SmallVector<MBBInfo, 8> WorkList(1, MBBInfo(MDT->getRootNode())); 00185 00186 while (!WorkList.empty()) { 00187 MBBInfo &MBBI = WorkList.back(); 00188 00189 // If this MBB has already been visited, destroy the scope for the MBB and 00190 // pop it from the work list. 00191 if (MBBI.isVisited()) { 00192 MBBI.postVisit(); 00193 WorkList.pop_back(); 00194 continue; 00195 } 00196 00197 // Visit the MBB and add its children to the work list. 00198 MBBI.preVisit(ScopedHT); 00199 Changed |= visitNode(MBBI); 00200 const MachineDomTreeNode *Node = MBBI.getNode(); 00201 const std::vector<MachineDomTreeNode *> &Children = Node->getChildren(); 00202 WorkList.append(Children.begin(), Children.end()); 00203 } 00204 00205 return Changed; 00206 } 00207 00208 bool OptimizePICCall::visitNode(MBBInfo &MBBI) { 00209 bool Changed = false; 00210 MachineBasicBlock *MBB = MBBI.getNode()->getBlock(); 00211 00212 for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; 00213 ++I) { 00214 unsigned Reg; 00215 ValueType Entry; 00216 00217 // Skip instructions that are not call instructions via registers. 00218 if (!isCallViaRegister(*I, Reg, Entry)) 00219 continue; 00220 00221 Changed = true; 00222 unsigned N = getCount(Entry); 00223 00224 if (N != 0) { 00225 // If a function has been called more than twice, we do not have to emit a 00226 // load instruction to get the function address from the GOT, but can 00227 // instead reuse the address that has been loaded before. 00228 if (N >= 2 && !LoadTargetFromGOT) 00229 getCallTargetRegOpnd(*I)->setReg(getReg(Entry)); 00230 00231 // Erase the $gp operand if this isn't the first time a function has 00232 // been called. $gp needs to be set up only if the function call can go 00233 // through a lazy binding stub. 00234 eraseGPOpnd(*I); 00235 } 00236 00237 if (Entry) 00238 incCntAndSetReg(Entry, Reg); 00239 00240 setCallTargetReg(MBB, I); 00241 } 00242 00243 return Changed; 00244 } 00245 00246 bool OptimizePICCall::isCallViaRegister(MachineInstr &MI, unsigned &Reg, 00247 ValueType &Val) const { 00248 if (!MI.isCall()) 00249 return false; 00250 00251 MachineOperand *MO = getCallTargetRegOpnd(MI); 00252 00253 // Return if MI is not a function call via a register. 00254 if (!MO) 00255 return false; 00256 00257 // Get the instruction that loads the function address from the GOT. 00258 Reg = MO->getReg(); 00259 Val = (Value*)nullptr; 00260 MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); 00261 MachineInstr *DefMI = MRI.getVRegDef(Reg); 00262 00263 assert(DefMI); 00264 00265 // See if DefMI is an instruction that loads from a GOT entry that holds the 00266 // address of a lazy binding stub. 00267 if (!DefMI->mayLoad() || DefMI->getNumOperands() < 3) 00268 return true; 00269 00270 unsigned Flags = DefMI->getOperand(2).getTargetFlags(); 00271 00272 if (Flags != MipsII::MO_GOT_CALL && Flags != MipsII::MO_CALL_LO16) 00273 return true; 00274 00275 // Return the underlying object for the GOT entry in Val. 00276 assert(DefMI->hasOneMemOperand()); 00277 Val = (*DefMI->memoperands_begin())->getValue(); 00278 if (!Val) 00279 Val = (*DefMI->memoperands_begin())->getPseudoValue(); 00280 return true; 00281 } 00282 00283 unsigned OptimizePICCall::getCount(ValueType Entry) { 00284 return ScopedHT.lookup(Entry).first; 00285 } 00286 00287 unsigned OptimizePICCall::getReg(ValueType Entry) { 00288 unsigned Reg = ScopedHT.lookup(Entry).second; 00289 assert(Reg); 00290 return Reg; 00291 } 00292 00293 void OptimizePICCall::incCntAndSetReg(ValueType Entry, unsigned Reg) { 00294 CntRegP P = ScopedHT.lookup(Entry); 00295 ScopedHT.insert(Entry, std::make_pair(P.first + 1, Reg)); 00296 } 00297 00298 /// Return an OptimizeCall object. 00299 FunctionPass *llvm::createMipsOptimizePICCallPass(MipsTargetMachine &TM) { 00300 return new OptimizePICCall(TM); 00301 }