diff options
author | Akira Hatanaka <ahatanak@gmail.com> | 2011-05-04 17:54:27 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanak@gmail.com> | 2011-05-04 17:54:27 +0000 |
commit | 6b7588e6c4f6f1a9ab2b5182fafaa95eeb56ca8d (patch) | |
tree | ce8641b51bd329cebd7bb0043678e9a43d1f3f38 | |
parent | 597a7664e1bbe2ea5f757eb6e853bd1d2fe98d6c (diff) |
Prevent instructions using $gp from being placed between a jalr and the instruction that restores the clobbered $gp.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130847 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/Mips/Mips.h | 1 | ||||
-rw-r--r-- | lib/Target/Mips/MipsEmitGPRestore.cpp | 80 | ||||
-rw-r--r-- | lib/Target/Mips/MipsISelLowering.cpp | 11 | ||||
-rw-r--r-- | lib/Target/Mips/MipsTargetMachine.cpp | 6 | ||||
-rw-r--r-- | lib/Target/Mips/MipsTargetMachine.h | 2 | ||||
-rw-r--r-- | test/CodeGen/Mips/gprestore.ll | 35 | ||||
-rw-r--r-- | test/CodeGen/Mips/internalfunc.ll | 2 |
7 files changed, 125 insertions, 12 deletions
diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h index 05b4c5a070..76a26a9ba5 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -26,6 +26,7 @@ namespace llvm { FunctionPass *createMipsISelDag(MipsTargetMachine &TM); FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM); FunctionPass *createMipsExpandPseudoPass(MipsTargetMachine &TM); + FunctionPass *createMipsEmitGPRestorePass(MipsTargetMachine &TM); extern Target TheMipsTarget; extern Target TheMipselTarget; diff --git a/lib/Target/Mips/MipsEmitGPRestore.cpp b/lib/Target/Mips/MipsEmitGPRestore.cpp new file mode 100644 index 0000000000..dd541e5d62 --- /dev/null +++ b/lib/Target/Mips/MipsEmitGPRestore.cpp @@ -0,0 +1,80 @@ +//===-- MipsEmitGPRestore.cpp - Emit GP restore instruction-----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===-----------------------------------------------------------------------===// +// +// This pass emits instructions that restore $gp right +// after jalr instructions. +// +//===-----------------------------------------------------------------------===// + +#define DEBUG_TYPE "emit-gp-restore" + +#include "Mips.h" +#include "MipsTargetMachine.h" +#include "MipsMachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/Statistic.h" + +using namespace llvm; + +namespace { + struct Inserter : public MachineFunctionPass { + + TargetMachine &TM; + const TargetInstrInfo *TII; + + static char ID; + Inserter(TargetMachine &tm) + : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } + + virtual const char *getPassName() const { + return "Mips Emit GP Restore"; + } + + bool runOnMachineBasicBlock(MachineBasicBlock &MBB); + bool runOnMachineFunction(MachineFunction &F); + }; + char Inserter::ID = 0; +} // end of anonymous namespace + +bool Inserter::runOnMachineFunction(MachineFunction &F) { + if (TM.getRelocationModel() != Reloc::PIC_) + return false; + + bool Changed = false; + int FI = F.getInfo<MipsFunctionInfo>()->getGPFI(); + + for (MachineFunction::iterator MFI = F.begin(), MFE = F.end(); + MFI != MFE; ++MFI) { + MachineBasicBlock& MBB = *MFI; + MachineBasicBlock::iterator I = MFI->begin(); + + while (I != MFI->end()) { + if (I->getOpcode() != Mips::JALR) { + ++I; + continue; + } + + DebugLoc dl = I->getDebugLoc(); + // emit lw $gp, ($gp save slot on stack) after jalr + BuildMI(MBB, ++I, dl, TII->get(Mips::LW), Mips::GP).addImm(0).addFrameIndex(FI); + Changed = true; + } + } + + return Changed; +} + +/// createMipsEmitGPRestorePass - Returns a pass that emits instructions that +/// restores $gp clobbered by jalr instructions. +FunctionPass *llvm::createMipsEmitGPRestorePass(MipsTargetMachine &tm) { + return new Inserter(tm); +} + diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 1f1220f192..9592244014 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -1298,17 +1298,6 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, } MipsFI->setGPStackOffset(LastArgStackLoc); } - - // Reload GP value. - FI = MipsFI->getGPFI(); - SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); - SDValue GPLoad = DAG.getLoad(MVT::i32, dl, Chain, FIN, - MachinePointerInfo::getFixedStack(FI), - false, false, 0); - Chain = GPLoad.getValue(1); - Chain = DAG.getCopyToReg(Chain, dl, DAG.getRegister(Mips::GP, MVT::i32), - GPLoad, SDValue(0,0)); - InFlag = Chain.getValue(1); } // Create the CALLSEQ_END node. diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 53190b4600..9f5c2184ca 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -77,6 +77,12 @@ addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) } bool MipsTargetMachine:: +addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { + PM.add(createMipsEmitGPRestorePass(*this)); + return true; +} + +bool MipsTargetMachine:: addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { PM.add(createMipsExpandPseudoPass(*this)); return true; diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index badb652922..102dd8566d 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -63,6 +63,8 @@ namespace llvm { CodeGenOpt::Level OptLevel); virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreRegAlloc(PassManagerBase &PM, + CodeGenOpt::Level OptLevel); virtual bool addPostRegAlloc(PassManagerBase &, CodeGenOpt::Level); }; diff --git a/test/CodeGen/Mips/gprestore.ll b/test/CodeGen/Mips/gprestore.ll new file mode 100644 index 0000000000..0e69a7bd0e --- /dev/null +++ b/test/CodeGen/Mips/gprestore.ll @@ -0,0 +1,35 @@ +; RUN: llc -march=mips < %s | FileCheck %s + +@p = external global i32 +@q = external global i32 +@r = external global i32 + +define void @f0() nounwind { +entry: +; CHECK: jalr +; CHECK-NOT: got({{.*}})($gp) +; CHECK: lw $gp +; CHECK: jalr +; CHECK-NOT: got({{.*}})($gp) +; CHECK: lw $gp +; CHECK: jalr +; CHECK-NOT: got({{.*}})($gp) +; CHECK: lw $gp + tail call void (...)* @f1() nounwind + %tmp = load i32* @p, align 4, !tbaa !0 + tail call void @f2(i32 %tmp) nounwind + %tmp1 = load i32* @q, align 4, !tbaa !0 + %tmp2 = load i32* @r, align 4, !tbaa !0 + tail call void @f3(i32 %tmp1, i32 %tmp2) nounwind + ret void +} + +declare void @f1(...) + +declare void @f2(i32) + +declare void @f3(i32, i32) + +!0 = metadata !{metadata !"int", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null} diff --git a/test/CodeGen/Mips/internalfunc.ll b/test/CodeGen/Mips/internalfunc.ll index fdfa01a9e0..50d099385a 100644 --- a/test/CodeGen/Mips/internalfunc.ll +++ b/test/CodeGen/Mips/internalfunc.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=mips | FileCheck %s +; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s @caller.sf1 = internal unnamed_addr global void (...)* null, align 4 @gf1 = external global void (...)* |