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
This commit is contained in:
Akira Hatanaka 2011-05-04 17:54:27 +00:00
parent 597a7664e1
commit 6b7588e6c4
7 changed files with 125 additions and 12 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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.

View File

@ -76,6 +76,12 @@ addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
return true;
}
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));

View File

@ -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);
};

View File

@ -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}

View File

@ -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 (...)*