From bea99471c796fd7563f36e9f1d5c2a0d20be5fcd Mon Sep 17 00:00:00 2001 From: Duraid Madina Date: Fri, 20 Jan 2006 20:24:31 +0000 Subject: [PATCH] remove RET hack, add proper support for rets (watching out for ret voids) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25486 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/IA64/IA64ISelDAGToDAG.cpp | 51 --------------------- lib/Target/IA64/IA64ISelLowering.cpp | 66 ++++++++++++++++++++++++++++ lib/Target/IA64/IA64ISelLowering.h | 16 ++++++- lib/Target/IA64/IA64InstrInfo.td | 12 +++-- 4 files changed, 89 insertions(+), 56 deletions(-) diff --git a/lib/Target/IA64/IA64ISelDAGToDAG.cpp b/lib/Target/IA64/IA64ISelDAGToDAG.cpp index 5c5802eb654..a0f6ac2f6f8 100644 --- a/lib/Target/IA64/IA64ISelDAGToDAG.cpp +++ b/lib/Target/IA64/IA64ISelDAGToDAG.cpp @@ -585,57 +585,6 @@ SDOperand IA64DAGToDAGISel::Select(SDOperand Op) { getI64Imm(Amt), Select(N->getOperand(0))); } - case ISD::RET: { - SDOperand Chain = Select(N->getOperand(0)); // Token chain. - SDOperand InFlag; - - switch (N->getNumOperands()) { - default: - assert(0 && "Unknown return instruction!"); - case 2: { - SDOperand RetVal = Select(N->getOperand(1)); - switch (RetVal.getValueType()) { - default: assert(0 && "I don't know how to return this type! (promote?)"); - // FIXME: do I need to add support for bools here? - // (return '0' or '1' in r8, basically...) - // - // FIXME: need to round floats - 80 bits is bad, the tester - // told me so - case MVT::i64: - // we mark r8 as live on exit up above in LowerArguments() - // BuildMI(BB, IA64::MOV, 1, IA64::r8).addReg(Tmp1); - Chain = CurDAG->getCopyToReg(Chain, IA64::r8, RetVal); - InFlag = Chain.getValue(1); - break; - case MVT::f64: - // we mark F8 as live on exit up above in LowerArguments() - // BuildMI(BB, IA64::FMOV, 1, IA64::F8).addReg(Tmp1); - Chain = CurDAG->getCopyToReg(Chain, IA64::F8, RetVal); - InFlag = Chain.getValue(1); - break; - } - break; - } - case 1: - break; - } - - // we need to copy VirtGPR (the vreg (to become a real reg)) that holds - // the output of this function's alloc instruction back into ar.pfs - // before we return. this copy must not float up above the last - // outgoing call in this function!!! - SDOperand AR_PFSVal = CurDAG->getCopyFromReg(Chain, IA64Lowering.VirtGPR, - MVT::i64); - Chain = AR_PFSVal.getValue(1); - Chain = CurDAG->getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal); - - // and then just emit a 'ret' instruction - // before returning, restore the ar.pfs register (set by the 'alloc' up top) - // BuildMI(BB, IA64::MOV, 1).addReg(IA64::AR_PFS).addReg(IA64Lowering.VirtGPR); - // - return CurDAG->SelectNodeTo(N, IA64::RET, MVT::Other, Chain); - } - case ISD::BR: // FIXME: we don't need long branches all the time! return CurDAG->SelectNodeTo(N, IA64::BRL_NOTCALL, MVT::Other, diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp index 7e46fdf7062..0c3c86fc58c 100644 --- a/lib/Target/IA64/IA64ISelLowering.cpp +++ b/lib/Target/IA64/IA64ISelLowering.cpp @@ -39,6 +39,11 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM) setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand); setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand); + // We need to handle ISD::RET for void functions ourselves, + // so we get a chance to restore ar.pfs before adding a + // br.ret insn + setOperationAction(ISD::RET, MVT::Other, Custom); + setSetCCResultType(MVT::i1); setShiftAmountType(MVT::i64); @@ -101,6 +106,7 @@ const char *IA64TargetLowering::getTargetNodeName(unsigned Opcode) const { default: return 0; case IA64ISD::GETFD: return "IA64ISD::GETFD"; case IA64ISD::BRCALL: return "IA64ISD::BRCALL"; + case IA64ISD::RET_FLAG: return "IA64ISD::RET_FLAG"; } } @@ -524,6 +530,44 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, return std::make_pair(RetVal, Chain); } +SDOperand IA64TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, + SelectionDAG &DAG) { + SDOperand Copy, InFlag; + SDOperand AR_PFSVal = DAG.getCopyFromReg(Chain, this->VirtGPR, + MVT::i64); + Chain = AR_PFSVal.getValue(1); + + switch (Op.getValueType()) { + default: assert(0 && "Unknown type to return! (promote?)"); + case MVT::i64: + Copy = DAG.getCopyToReg(Chain, IA64::r8, Op, InFlag); + break; + case MVT::f64: + Copy = DAG.getCopyToReg(Chain, IA64::F8, Op, InFlag); + break; + } + + Chain = Copy.getValue(0); + InFlag = Copy.getValue(1); + // we need to copy VirtGPR (the vreg (to become a real reg)) that holds + // the output of this function's alloc instruction back into ar.pfs + // before we return. this copy must not float up above the last + // outgoing call in this function - we flag this to the ret instruction + Chain = DAG.getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal, InFlag); + InFlag = Chain.getValue(1); + + // and then just emit a 'ret' instruction + std::vector NodeTys; + std::vector RetOperands; + NodeTys.push_back(MVT::Other); + NodeTys.push_back(MVT::Flag); + RetOperands.push_back(Chain); + RetOperands.push_back(InFlag); + + return DAG.getNode(IA64ISD::RET_FLAG, NodeTys, RetOperands); +// return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, MVT::Other, Copy, Chain, InFlag); +} + SDOperand IA64TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP, Value *VAListV, SelectionDAG &DAG) { @@ -566,3 +610,25 @@ LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, abort(); } +SDOperand IA64TargetLowering:: +LowerOperation(SDOperand Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + default: assert(0 && "Should not custom lower this!"); + case ISD::RET: { // the DAGgy stuff takes care of + // restoring ar.pfs before adding a br.ret for functions + // that return something, but we need to take care of stuff + // that returns void manually, so here it is: + assert(Op.getNumOperands()==1 && + "trying to custom lower a return other than void! (numops!=1)"); + + SDOperand Chain = Op.getOperand(0); + SDOperand AR_PFSVal = DAG.getCopyFromReg(Chain, this->VirtGPR, + MVT::i64); + Chain = AR_PFSVal.getValue(1); + Chain = DAG.getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal); + + // and then just emit a 'ret' instruction + return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, Chain); + } + } +} diff --git a/lib/Target/IA64/IA64ISelLowering.h b/lib/Target/IA64/IA64ISelLowering.h index 305903a88cf..a73bbaa7f14 100644 --- a/lib/Target/IA64/IA64ISelLowering.h +++ b/lib/Target/IA64/IA64ISelLowering.h @@ -30,7 +30,10 @@ namespace llvm { GETFD, // TODO: explain this hack - BRCALL + BRCALL, + + // RET_FLAG - Return with a flag operand + RET_FLAG }; } @@ -64,9 +67,18 @@ namespace llvm { bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); + /// LowerReturnTo - This spits out restore-previous-frame-state+br.ret + /// instructions + virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op, + SelectionDAG &DAG); + + /// LowerOperation - for custom lowering specific ops + /// (currently, only "ret void") + virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); + virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP, Value *VAListV, SelectionDAG &DAG); - + virtual std::pair LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV, const Type *ArgTy, SelectionDAG &DAG); diff --git a/lib/Target/IA64/IA64InstrInfo.td b/lib/Target/IA64/IA64InstrInfo.td index 315cd97aa3c..847f9c1010e 100644 --- a/lib/Target/IA64/IA64InstrInfo.td +++ b/lib/Target/IA64/IA64InstrInfo.td @@ -21,6 +21,10 @@ include "IA64InstrFormats.td" def IA64getfd : SDNode<"IA64ISD::GETFD", SDTFPToIntOp, []>; +def SDT_IA64RetFlag : SDTypeProfile<0, 0, []>; +def retflag : SDNode<"IA64ISD::RET_FLAG", SDT_IA64RetFlag, + [SDNPHasChain, SDNPOptInFlag]>; + //===--------- def u2imm : Operand; @@ -717,7 +721,9 @@ let isCall = 1, noResults = 1, /* isTerminator = 1, isBranch = 1, */ "($qp) br.cond.call.sptk $dst;;">; } +// Return branch: let isTerminator = 1, isReturn = 1, noResults = 1 in - def RET : RawForm<0x03, 0xb0, (ops), "br.ret.sptk.many rp;;">; // return - - + def RET : AForm_DAG<0x03, 0x0b, (ops), + "br.ret.sptk.many rp;;", + [(retflag)]>; // return +def : Pat<(ret), (RET)>; -- 2.34.1