From dc9d87a9bbb5bc2ddaad7ab0db4aed82d88636c6 Mon Sep 17 00:00:00 2001 From: Wesley Peck Date: Wed, 15 Dec 2010 20:27:28 +0000 Subject: [PATCH] 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 --- lib/Target/MBlaze/MBlazeFrameInfo.cpp | 103 ++++++++++++++++++++++- lib/Target/MBlaze/MBlazeISelLowering.cpp | 17 ++-- lib/Target/MBlaze/MBlazeISelLowering.h | 7 +- lib/Target/MBlaze/MBlazeInstrInfo.td | 4 + test/CodeGen/MBlaze/intr.ll | 48 +++++++++++ test/CodeGen/MBlaze/svol.ll | 80 ++++++++++++++++++ 6 files changed, 247 insertions(+), 12 deletions(-) create mode 100644 test/CodeGen/MBlaze/intr.ll create mode 100644 test/CodeGen/MBlaze/svol.ll diff --git a/lib/Target/MBlaze/MBlazeFrameInfo.cpp b/lib/Target/MBlaze/MBlazeFrameInfo.cpp index 77897232f7f..3b5023d3a75 100644 --- a/lib/Target/MBlaze/MBlazeFrameInfo.cpp +++ b/lib/Target/MBlaze/MBlazeFrameInfo.cpp @@ -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(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 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(); @@ -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(); + 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); } diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp index ad7222a4c54..dc7cff8637f 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -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); } //===----------------------------------------------------------------------===// diff --git a/lib/Target/MBlaze/MBlazeISelLowering.h b/lib/Target/MBlaze/MBlazeISelLowering.h index 4f09851e7f3..aa1c9aa3aa5 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.h +++ b/lib/Target/MBlaze/MBlazeISelLowering.h @@ -78,8 +78,11 @@ namespace llvm { // Integer Compare ICmp, - // Return - Ret + // Return from subroutine + Ret, + + // Return from interrupt + IRet }; } diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.td b/lib/Target/MBlaze/MBlazeInstrInfo.td index cf69efa8776..39ddd6ad352 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.td +++ b/lib/Target/MBlaze/MBlazeInstrInfo.td @@ -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)>; diff --git a/test/CodeGen/MBlaze/intr.ll b/test/CodeGen/MBlaze/intr.ll new file mode 100644 index 00000000000..79c6bffd00c --- /dev/null +++ b/test/CodeGen/MBlaze/intr.ll @@ -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*, ...) diff --git a/test/CodeGen/MBlaze/svol.ll b/test/CodeGen/MBlaze/svol.ll new file mode 100644 index 00000000000..c1e96202845 --- /dev/null +++ b/test/CodeGen/MBlaze/svol.ll @@ -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*, ...) -- 2.34.1