Lower the MBlaze target specific calling conventions for "interrupt_handler"

and "save_volatiles" correctly. This completes the custom calling convention
functionality changes for the MBlaze backend that were started in 121888.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121891 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Wesley Peck 2010-12-15 20:27:28 +00:00
parent d364acd3d7
commit dc9d87a9bb
6 changed files with 247 additions and 12 deletions

View File

@ -132,6 +132,92 @@ static void analyzeFrameIndexes(MachineFunction &MF) {
MBlazeFI->setStackAdjust(StackAdjust);
}
static void interruptFrameLayout(MachineFunction &MF) {
const Function *F = MF.getFunction();
llvm::CallingConv::ID CallConv = F->getCallingConv();
// If this function is not using either the interrupt_handler
// calling convention or the save_volatiles calling convention
// then we don't need to do any additional frame layout.
if (CallConv != llvm::CallingConv::MBLAZE_INTR &&
CallConv != llvm::CallingConv::MBLAZE_SVOL)
return;
MachineFrameInfo *MFI = MF.getFrameInfo();
const MachineRegisterInfo &MRI = MF.getRegInfo();
const MBlazeInstrInfo &TII =
*static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
// Determine if the calling convention is the interrupt_handler
// calling convention. Some pieces of the prologue and epilogue
// only need to be emitted if we are lowering and interrupt handler.
bool isIntr = CallConv == llvm::CallingConv::MBLAZE_INTR;
// Determine where to put prologue and epilogue additions
MachineBasicBlock &MENT = MF.front();
MachineBasicBlock &MEXT = MF.back();
MachineBasicBlock::iterator MENTI = MENT.begin();
MachineBasicBlock::iterator MEXTI = prior(MEXT.end());
DebugLoc ENTDL = MENTI != MENT.end() ? MENTI->getDebugLoc() : DebugLoc();
DebugLoc EXTDL = MEXTI != MEXT.end() ? MEXTI->getDebugLoc() : DebugLoc();
// Store the frame indexes generated during prologue additions for use
// when we are generating the epilogue additions.
SmallVector<int, 10> VFI;
// Build the prologue SWI for R3 - R12 if needed. Note that R11 must
// always have a SWI because it is used when processing RMSR.
for (unsigned r = MBlaze::R3; r <= MBlaze::R12; ++r) {
if (!MRI.isPhysRegUsed(r) && !(isIntr && r == MBlaze::R11)) continue;
int FI = MFI->CreateStackObject(4,4,false,false);
VFI.push_back(FI);
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), r)
.addFrameIndex(FI).addImm(0);
}
// Build the prologue SWI for R17, R18
int R17FI = MFI->CreateStackObject(4,4,false,false);
int R18FI = MFI->CreateStackObject(4,4,false,false);
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R17)
.addFrameIndex(R17FI).addImm(0);
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R18)
.addFrameIndex(R18FI).addImm(0);
// Buid the prologue SWI and the epilogue LWI for RMSR if needed
if (isIntr) {
int MSRFI = MFI->CreateStackObject(4,4,false,false);
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::MFS), MBlaze::R11)
.addReg(MBlaze::RMSR);
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R11)
.addFrameIndex(MSRFI).addImm(0);
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R11)
.addFrameIndex(MSRFI).addImm(0);
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::MTS), MBlaze::RMSR)
.addReg(MBlaze::R11);
}
// Build the epilogue LWI for R17, R18
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R18)
.addFrameIndex(R18FI).addImm(0);
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R17)
.addFrameIndex(R17FI).addImm(0);
// Build the epilogue LWI for R3 - R12 if needed
for (unsigned r = MBlaze::R12, i = VFI.size(); r >= MBlaze::R3; --r) {
if (!MRI.isPhysRegUsed(r)) continue;
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), r)
.addFrameIndex(VFI[--i]).addImm(0);
}
}
static void determineFrameLayout(MachineFunction &MF) {
MachineFrameInfo *MFI = MF.getFrameInfo();
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
@ -174,6 +260,9 @@ void MBlazeFrameInfo::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock::iterator MBBI = MBB.begin();
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR;
// Determine the correct frame layout
determineFrameLayout(MF);
@ -181,7 +270,7 @@ void MBlazeFrameInfo::emitPrologue(MachineFunction &MF) const {
unsigned StackSize = MFI->getStackSize();
// No need to allocate space on the stack.
if (StackSize == 0 && !MFI->adjustsStack()) return;
if (StackSize == 0 && !MFI->adjustsStack() && !requiresRA) return;
int FPOffset = MBlazeFI->getFPStackOffset();
int RAOffset = MBlazeFI->getRAStackOffset();
@ -191,7 +280,7 @@ void MBlazeFrameInfo::emitPrologue(MachineFunction &MF) const {
.addReg(MBlaze::R1).addImm(-StackSize);
// swi R15, R1, stack_loc
if (MFI->adjustsStack()) {
if (MFI->adjustsStack() || requiresRA) {
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
.addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset);
}
@ -217,6 +306,9 @@ void MBlazeFrameInfo::emitEpilogue(MachineFunction &MF,
DebugLoc dl = MBBI->getDebugLoc();
llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR;
// Get the FI's where RA and FP are saved.
int FPOffset = MBlazeFI->getFPStackOffset();
int RAOffset = MBlazeFI->getRAStackOffset();
@ -232,7 +324,7 @@ void MBlazeFrameInfo::emitEpilogue(MachineFunction &MF,
}
// lwi R15, R1, stack_loc
if (MFI->adjustsStack()) {
if (MFI->adjustsStack() || requiresRA) {
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15)
.addReg(MBlaze::R1).addImm(RAOffset);
}
@ -251,8 +343,10 @@ void MBlazeFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
const {
MachineFrameInfo *MFI = MF.getFrameInfo();
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR;
if (MFI->adjustsStack()) {
if (MFI->adjustsStack() || requiresRA) {
MBlazeFI->setRAStackOffset(0);
MFI->CreateFixedObject(4,0,true);
}
@ -262,5 +356,6 @@ void MBlazeFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
MFI->CreateFixedObject(4,4,true);
}
interruptFrameLayout(MF);
analyzeFrameIndexes(MF);
}

View File

@ -864,13 +864,18 @@ LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
Flag = Chain.getValue(1);
}
// Return on MBlaze is always a "rtsd R15, 8"
// If this function is using the interrupt_handler calling convention
// then use "rtid r14, 0" otherwise use "rtsd r15, 8"
unsigned Ret = (CallConv == llvm::CallingConv::MBLAZE_INTR) ? MBlazeISD::IRet
: MBlazeISD::Ret;
unsigned Reg = (CallConv == llvm::CallingConv::MBLAZE_INTR) ? MBlaze::R14
: MBlaze::R15;
SDValue DReg = DAG.getRegister(Reg, MVT::i32);
if (Flag.getNode())
return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other,
Chain, DAG.getRegister(MBlaze::R15, MVT::i32), Flag);
else // Return Void
return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other,
Chain, DAG.getRegister(MBlaze::R15, MVT::i32));
return DAG.getNode(Ret, dl, MVT::Other, Chain, DReg, Flag);
return DAG.getNode(Ret, dl, MVT::Other, Chain, DReg);
}
//===----------------------------------------------------------------------===//

View File

@ -78,8 +78,11 @@ namespace llvm {
// Integer Compare
ICmp,
// Return
Ret
// Return from subroutine
Ret,
// Return from interrupt
IRet
};
}

View File

@ -18,6 +18,7 @@ include "MBlazeInstrFormats.td"
// def SDTMBlazeSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>;
def SDT_MBlazeRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
def SDT_MBlazeIRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
def SDT_MBlazeJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
def SDT_MBCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
@ -28,6 +29,8 @@ def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
def MBlazeRet : SDNode<"MBlazeISD::Ret", SDT_MBlazeRet,
[SDNPHasChain, SDNPOptInFlag]>;
def MBlazeIRet : SDNode<"MBlazeISD::IRet", SDT_MBlazeIRet,
[SDNPHasChain, SDNPOptInFlag]>;
def MBlazeJmpLink : SDNode<"MBlazeISD::JmpLink",SDT_MBlazeJmpLink,
[SDNPHasChain,SDNPOptInFlag,SDNPOutFlag]>;
@ -727,6 +730,7 @@ def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R),
// Ret instructions
def : Pat<(MBlazeRet GPR:$target), (RTSD GPR:$target, 0x8)>;
def : Pat<(MBlazeIRet GPR:$target), (RTID GPR:$target, 0x0)>;
// BR instructions
def : Pat<(br bb:$T), (BRID bb:$T)>;

View File

@ -0,0 +1,48 @@
; Ensure that the MBlaze interrupt_handler calling convention (cc73) is handled
; correctly correctly by the MBlaze backend.
;
; RUN: llc < %s -march=mblaze | FileCheck %s
@.str = private constant [28 x i8] c"The interrupt has gone off\0A\00"
@_interrupt_handler = alias void ()* @myintr
define cc73 void @myintr() nounwind noinline {
; CHECK: myintr:
; CHECK: swi r3, r1
; CHECK: swi r4, r1
; CHECK: swi r5, r1
; CHECK: swi r6, r1
; CHECK: swi r7, r1
; CHECK: swi r8, r1
; CHECK: swi r9, r1
; CHECK: swi r10, r1
; CHECK: swi r11, r1
; CHECK: swi r12, r1
; CHECK: swi r17, r1
; CHECK: swi r18, r1
; CHECK: mfs r11, rmsr
; CHECK: swi r11, r1
entry:
%call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([28 x i8]* @.str, i32 0, i32 0))
ret void
; CHECK: lwi r11, r1
; CHECK: mts rmsr, r11
; CHECK: lwi r18, r1
; CHECK: lwi r17, r1
; CHECK: lwi r12, r1
; CHECK: lwi r11, r1
; CHECK: lwi r10, r1
; CHECK: lwi r9, r1
; CHECK: lwi r8, r1
; CHECK: lwi r7, r1
; CHECK: lwi r6, r1
; CHECK: lwi r5, r1
; CHECK: lwi r4, r1
; CHECK: lwi r3, r1
; CHECK: rtid r14, 0
}
; CHECK: .globl _interrupt_handler
; CHECK: _interrupt_handler = myintr
declare i32 @printf(i8*, ...)

View File

@ -0,0 +1,80 @@
; Ensure that the MBlaze save_volatiles calling convention (cc74) is handled
; correctly correctly by the MBlaze backend.
;
; RUN: llc < %s -march=mblaze | FileCheck %s
@.str = private constant [28 x i8] c"The interrupt has gone off\0A\00"
define cc74 void @mysvol() nounwind noinline {
; CHECK: mysvol:
; CHECK: swi r3, r1
; CHECK: swi r4, r1
; CHECK: swi r5, r1
; CHECK: swi r6, r1
; CHECK: swi r7, r1
; CHECK: swi r8, r1
; CHECK: swi r9, r1
; CHECK: swi r10, r1
; CHECK: swi r11, r1
; CHECK: swi r12, r1
; CHECK: swi r17, r1
; CHECK: swi r18, r1
; CHECK-NOT: mfs r11, rmsr
entry:
%call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([28 x i8]* @.str, i32 0, i32 0))
ret void
; CHECK-NOT: mts rmsr, r11
; CHECK: lwi r18, r1
; CHECK: lwi r17, r1
; CHECK: lwi r12, r1
; CHECK: lwi r11, r1
; CHECK: lwi r10, r1
; CHECK: lwi r9, r1
; CHECK: lwi r8, r1
; CHECK: lwi r7, r1
; CHECK: lwi r6, r1
; CHECK: lwi r5, r1
; CHECK: lwi r4, r1
; CHECK: lwi r3, r1
; CHECK: rtsd r15, 8
}
define cc74 void @mysvol2() nounwind noinline {
; CHECK: mysvol2:
; CHECK-NOT: swi r3, r1
; CHECK-NOT: swi r4, r1
; CHECK-NOT: swi r5, r1
; CHECK-NOT: swi r6, r1
; CHECK-NOT: swi r7, r1
; CHECK-NOT: swi r8, r1
; CHECK-NOT: swi r9, r1
; CHECK-NOT: swi r10, r1
; CHECK-NOT: swi r11, r1
; CHECK-NOT: swi r12, r1
; CHECK: swi r17, r1
; CHECK: swi r18, r1
; CHECK-NOT: mfs r11, rmsr
entry:
; CHECK-NOT: mts rmsr, r11
; CHECK: lwi r18, r1
; CHECK: lwi r17, r1
; CHECK-NOT: lwi r12, r1
; CHECK-NOT: lwi r11, r1
; CHECK-NOT: lwi r10, r1
; CHECK-NOT: lwi r9, r1
; CHECK-NOT: lwi r8, r1
; CHECK-NOT: lwi r7, r1
; CHECK-NOT: lwi r6, r1
; CHECK-NOT: lwi r5, r1
; CHECK-NOT: lwi r4, r1
; CHECK-NOT: lwi r3, r1
; CHECK: rtsd r15, 8
ret void
}
; CHECK-NOT: .globl _interrupt_handler
; CHECK-NOT: _interrupt_handler = mysvol
; CHECK-NOT: _interrupt_handler = mysvol2
declare i32 @printf(i8*, ...)