diff --git a/llvm/lib/Target/Alpha/AlphaISelLowering.cpp b/llvm/lib/Target/Alpha/AlphaISelLowering.cpp index b47a51891aae..3a5c7d92e8d0 100644 --- a/llvm/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/llvm/lib/Target/Alpha/AlphaISelLowering.cpp @@ -128,6 +128,8 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) setOperationAction(ISD::VAARG, MVT::Other, Custom); setOperationAction(ISD::VAARG, MVT::i32, Custom); + setOperationAction(ISD::RET, MVT::Other, Custom); + setStackPointerRegisterToSaveRestore(Alpha::R30); setOperationAction(ISD::ConstantFP, MVT::f64, Expand); @@ -154,6 +156,7 @@ const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode) const { case AlphaISD::GlobalBaseReg: return "Alpha::GlobalBaseReg"; case AlphaISD::CALL: return "Alpha::CALL"; case AlphaISD::DivCall: return "Alpha::DivCall"; + case AlphaISD::RET_FLAG: return "Alpha::RET_FLAG"; } } @@ -175,116 +178,121 @@ const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode) const { // //#define GP $29 // //#define SP $30 -std::vector -AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) -{ +static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG, + int &VarArgsBase, + int &VarArgsOffset, + unsigned int &GP, + unsigned int &RA) { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); + SSARegMap *RegMap = MF.getSSARegMap(); std::vector ArgValues; + SDOperand Root = Op.getOperand(0); + + GP = AddLiveIn(MF, Alpha::R29, &Alpha::GPRCRegClass); + RA = AddLiveIn(MF, Alpha::R26, &Alpha::GPRCRegClass); unsigned args_int[] = { Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21}; unsigned args_float[] = { Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21}; - - int count = 0; - - GP = AddLiveIn(MF, Alpha::R29, getRegClassFor(MVT::i64)); - RA = AddLiveIn(MF, Alpha::R26, getRegClassFor(MVT::i64)); - - for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) - { + + for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) { SDOperand argt; - if (count < 6) { + MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); + SDOperand ArgVal; + + if (ArgNo < 6) { unsigned Vreg; - MVT::ValueType VT = getValueType(I->getType()); - switch (VT) { + switch (ObjectVT) { default: - std::cerr << "Unknown Type " << VT << "\n"; + std::cerr << "Unknown Type " << ObjectVT << "\n"; abort(); case MVT::f64: case MVT::f32: - args_float[count] = AddLiveIn(MF, args_float[count], getRegClassFor(VT)); - argt = DAG.getCopyFromReg(DAG.getRoot(), args_float[count], VT); - DAG.setRoot(argt.getValue(1)); + args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], + &Alpha::F8RCRegClass); + ArgVal = DAG.getCopyFromReg(Root, args_float[ArgNo], ObjectVT); break; - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: case MVT::i64: - args_int[count] = AddLiveIn(MF, args_int[count], getRegClassFor(MVT::i64)); - argt = DAG.getCopyFromReg(DAG.getRoot(), args_int[count], MVT::i64); - DAG.setRoot(argt.getValue(1)); - if (VT != MVT::i64) { - unsigned AssertOp = - I->getType()->isSigned() ? ISD::AssertSext : ISD::AssertZext; - argt = DAG.getNode(AssertOp, MVT::i64, argt, - DAG.getValueType(VT)); - argt = DAG.getNode(ISD::TRUNCATE, VT, argt); - } + args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo], + &Alpha::GPRCRegClass); + ArgVal = DAG.getCopyFromReg(Root, args_int[ArgNo], MVT::i64); break; } } else { //more args // Create the frame index object for this incoming parameter... - int FI = MFI->CreateFixedObject(8, 8 * (count - 6)); + int FI = MFI->CreateFixedObject(8, 8 * (ArgNo - 6)); // Create the SelectionDAG nodes corresponding to a load //from this parameter SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64); - argt = DAG.getLoad(getValueType(I->getType()), - DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL)); + ArgVal = DAG.getLoad(ObjectVT, Root, FIN, DAG.getSrcValue(NULL)); } - ++count; - ArgValues.push_back(argt); + ArgValues.push_back(ArgVal); } // If the functions takes variable number of arguments, copy all regs to stack - if (F.isVarArg()) { - VarArgsOffset = count * 8; + bool isVarArg = cast(Op.getOperand(2))->getValue() != 0; + if (isVarArg) { + VarArgsOffset = (Op.Val->getNumValues()-1) * 8; std::vector LS; for (int i = 0; i < 6; ++i) { if (MRegisterInfo::isPhysicalRegister(args_int[i])) - args_int[i] = AddLiveIn(MF, args_int[i], getRegClassFor(MVT::i64)); - SDOperand argt = DAG.getCopyFromReg(DAG.getRoot(), args_int[i], MVT::i64); + args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass); + SDOperand argt = DAG.getCopyFromReg(Root, args_int[i], MVT::i64); int FI = MFI->CreateFixedObject(8, -8 * (6 - i)); if (i == 0) VarArgsBase = FI; SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64); - LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(), argt, + LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Root, argt, SDFI, DAG.getSrcValue(NULL))); if (MRegisterInfo::isPhysicalRegister(args_float[i])) - args_float[i] = AddLiveIn(MF, args_float[i], getRegClassFor(MVT::f64)); - argt = DAG.getCopyFromReg(DAG.getRoot(), args_float[i], MVT::f64); + args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass); + argt = DAG.getCopyFromReg(Root, args_float[i], MVT::f64); FI = MFI->CreateFixedObject(8, - 8 * (12 - i)); SDFI = DAG.getFrameIndex(FI, MVT::i64); - LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(), argt, + LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Root, argt, SDFI, DAG.getSrcValue(NULL))); } //Set up a token factor with all the stack traffic - DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, LS)); + Root = DAG.getNode(ISD::TokenFactor, MVT::Other, LS); } - // Finally, inform the code generator which regs we return values in. - switch (getValueType(F.getReturnType())) { - default: assert(0 && "Unknown type!"); - case MVT::isVoid: break; - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - case MVT::i64: - MF.addLiveOut(Alpha::R0); - break; - case MVT::f32: - case MVT::f64: - MF.addLiveOut(Alpha::F0); + ArgValues.push_back(Root); + + // Return the new list of results. + std::vector RetVT(Op.Val->value_begin(), + Op.Val->value_end()); + return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues); +} + +static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) { + SDOperand Copy; + switch (Op.getNumOperands()) { + default: + assert(0 && "Do not know how to return this many arguments!"); + abort(); + case 1: + return SDOperand(); // ret void is legal + case 3: { + MVT::ValueType ArgVT = Op.getOperand(1).getValueType(); + unsigned ArgReg; + if (MVT::isInteger(ArgVT)) + ArgReg = Alpha::R0; + else { + assert(MVT::isFloatingPoint(ArgVT)); + ArgReg = Alpha::F0; + } + Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1), + SDOperand()); + if(DAG.getMachineFunction().liveout_empty()) + DAG.getMachineFunction().addLiveOut(ArgReg); break; } - - //return the arguments+ - return ArgValues; + } + return DAG.getNode(AlphaISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); } std::pair @@ -371,7 +379,12 @@ static int getUID() /// SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { - default: assert(0 && "Wasn't expecting to be able to lower this!"); + default: assert(0 && "Wasn't expecting to be able to lower this!"); + case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG, + VarArgsBase, + VarArgsOffset, + GP, RA); + case ISD::RET: return LowerRET(Op,DAG); case ISD::SINT_TO_FP: { assert(MVT::i64 == Op.getOperand(0).getValueType() && "Unhandled SINT_TO_FP type in custom expander!"); diff --git a/llvm/lib/Target/Alpha/AlphaISelLowering.h b/llvm/lib/Target/Alpha/AlphaISelLowering.h index d6886fcc69ec..28bbfc50a9b1 100644 --- a/llvm/lib/Target/Alpha/AlphaISelLowering.h +++ b/llvm/lib/Target/Alpha/AlphaISelLowering.h @@ -42,7 +42,10 @@ namespace llvm { CALL, /// DIVCALL - used for special library calls for div and rem - DivCall + DivCall, + + /// return flag operand + RET_FLAG }; } @@ -64,11 +67,6 @@ namespace llvm { //Friendly names for dumps const char *getTargetNodeName(unsigned Opcode) const; - /// LowerArguments - This hook must be implemented to indicate how we should - /// lower the arguments for the specified function, into the specified DAG. - virtual std::vector - LowerArguments(Function &F, SelectionDAG &DAG); - /// LowerCallTo - This hook lowers an abstract call to a function into an /// actual call. virtual std::pair diff --git a/llvm/lib/Target/Alpha/AlphaInstrFormats.td b/llvm/lib/Target/Alpha/AlphaInstrFormats.td index 663562948d47..3f6e6495f667 100644 --- a/llvm/lib/Target/Alpha/AlphaInstrFormats.td +++ b/llvm/lib/Target/Alpha/AlphaInstrFormats.td @@ -75,6 +75,20 @@ class MbrForm opcode, bits<2> TB, dag OL, string asmstr, InstrItinClass let Inst{15-14} = TB; let Inst{13-0} = disp; } +class MbrpForm opcode, bits<2> TB, dag OL, string asmstr, list pattern, InstrItinClass itin> + : InstAlpha { + let Pattern=pattern; + bits<5> Ra; + bits<5> Rb; + bits<14> disp; + + let OperandList = OL; + + let Inst{25-21} = Ra; + let Inst{20-16} = Rb; + let Inst{15-14} = TB; + let Inst{13-0} = disp; +} //3.3.2 def target : Operand {} diff --git a/llvm/lib/Target/Alpha/AlphaInstrInfo.td b/llvm/lib/Target/Alpha/AlphaInstrInfo.td index 85e2f27f15a1..6649fabcfd4f 100644 --- a/llvm/lib/Target/Alpha/AlphaInstrInfo.td +++ b/llvm/lib/Target/Alpha/AlphaInstrInfo.td @@ -28,6 +28,9 @@ def Alpha_gprello : SDNode<"AlphaISD::GPRelLo", SDTIntBinOp, []>; def Alpha_gprelhi : SDNode<"AlphaISD::GPRelHi", SDTIntBinOp, []>; def Alpha_rellit : SDNode<"AlphaISD::RelLit", SDTIntBinOp, []>; +def retflag : SDNode<"AlphaISD::RET_FLAG", SDTRet, + [SDNPHasChain, SDNPOptInFlag]>; + // These are target-independent nodes, but have target-specific formats. def SDT_AlphaCallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i64> ]>; def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_AlphaCallSeq,[SDNPHasChain]>; @@ -425,8 +428,10 @@ def : Pat<(setune GPRC:$X, GPRC:$Y), (CMPEQi (CMPEQ GPRC:$X, GPRC:$Y), 0)>; def : Pat<(setune GPRC:$X, immUExt8:$Y), (CMPEQi (CMPEQ GPRC:$X, immUExt8:$Y), 0)>; -let isReturn = 1, isTerminator = 1, noResults = 1, Ra = 31, Rb = 26, disp = 1, Uses = [R26] in +let isReturn = 1, isTerminator = 1, noResults = 1, Ra = 31, Rb = 26, disp = 1, Uses = [R26] in { def RETDAG : MbrForm< 0x1A, 0x02, (ops), "ret $$31,($$26),1", s_jsr>; //Return from subroutine + def RETDAGp : MbrpForm< 0x1A, 0x02, (ops), "ret $$31,($$26),1", [(retflag)], s_jsr>; //Return from subroutine +} def JMP : MbrForm< 0x1A, 0x00, (ops GPRC:$RD, GPRC:$RS, GPRC:$DISP), "jmp $RD,($RS),$DISP", s_jsr>; //Jump let isCall = 1, noResults = 1, Ra = 26, diff --git a/llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp b/llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp index 0eb778090195..9ea4b70893e1 100644 --- a/llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -346,7 +346,7 @@ void AlphaRegisterInfo::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); MachineBasicBlock::iterator MBBI = prior(MBB.end()); - assert(MBBI->getOpcode() == Alpha::RETDAG + assert(MBBI->getOpcode() == Alpha::RETDAG || MBBI->getOpcode() == Alpha::RETDAGp && "Can only insert epilog into returning blocks"); bool FP = hasFP(MF);