Home | History | Annotate | Download | only in Mips
      1 //===-- MipsEmitGPRestore.cpp - Emit GP Restore Instruction ---------------===//
      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 emits instructions that restore $gp right
     11 // after jalr instructions.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #define DEBUG_TYPE "emit-gp-restore"
     16 
     17 #include "Mips.h"
     18 #include "MipsTargetMachine.h"
     19 #include "MipsMachineFunction.h"
     20 #include "llvm/CodeGen/MachineFunctionPass.h"
     21 #include "llvm/CodeGen/MachineInstrBuilder.h"
     22 #include "llvm/Target/TargetInstrInfo.h"
     23 #include "llvm/ADT/Statistic.h"
     24 
     25 using namespace llvm;
     26 
     27 namespace {
     28   struct Inserter : public MachineFunctionPass {
     29 
     30     TargetMachine &TM;
     31     const TargetInstrInfo *TII;
     32 
     33     static char ID;
     34     Inserter(TargetMachine &tm)
     35       : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { }
     36 
     37     virtual const char *getPassName() const {
     38       return "Mips Emit GP Restore";
     39     }
     40 
     41     bool runOnMachineFunction(MachineFunction &F);
     42   };
     43   char Inserter::ID = 0;
     44 } // end of anonymous namespace
     45 
     46 bool Inserter::runOnMachineFunction(MachineFunction &F) {
     47   MipsFunctionInfo *MipsFI = F.getInfo<MipsFunctionInfo>();
     48 
     49   if ((TM.getRelocationModel() != Reloc::PIC_) ||
     50       (!MipsFI->globalBaseRegFixed()))
     51     return false;
     52 
     53   bool Changed = false;
     54   int FI = MipsFI->getGPFI();
     55 
     56   for (MachineFunction::iterator MFI = F.begin(), MFE = F.end();
     57        MFI != MFE; ++MFI) {
     58     MachineBasicBlock& MBB = *MFI;
     59     MachineBasicBlock::iterator I = MFI->begin();
     60 
     61     // If MBB is a landing pad, insert instruction that restores $gp after
     62     // EH_LABEL.
     63     if (MBB.isLandingPad()) {
     64       // Find EH_LABEL first.
     65       for (; I->getOpcode() != TargetOpcode::EH_LABEL; ++I) ;
     66 
     67       // Insert lw.
     68       ++I;
     69       DebugLoc dl = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
     70       BuildMI(MBB, I, dl, TII->get(Mips::LW), Mips::GP).addFrameIndex(FI)
     71                                                        .addImm(0);
     72       Changed = true;
     73     }
     74 
     75     while (I != MFI->end()) {
     76       if (I->getOpcode() != Mips::JALR) {
     77         ++I;
     78         continue;
     79       }
     80 
     81       DebugLoc dl = I->getDebugLoc();
     82       // emit lw $gp, ($gp save slot on stack) after jalr
     83       BuildMI(MBB, ++I, dl, TII->get(Mips::LW), Mips::GP).addFrameIndex(FI)
     84                                                          .addImm(0);
     85       Changed = true;
     86     }
     87   }
     88 
     89   return Changed;
     90 }
     91 
     92 /// createMipsEmitGPRestorePass - Returns a pass that emits instructions that
     93 /// restores $gp clobbered by jalr instructions.
     94 FunctionPass *llvm::createMipsEmitGPRestorePass(MipsTargetMachine &tm) {
     95   return new Inserter(tm);
     96 }
     97 
     98