diff --git a/lib/Target/Alpha/AlphaISelDAGToDAG.cpp b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp index b920bc4d8cc..50ff1b09d01 100644 --- a/lib/Target/Alpha/AlphaISelDAGToDAG.cpp +++ b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp @@ -16,6 +16,7 @@ #include "AlphaTargetMachine.h" #include "AlphaISelLowering.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SSARegMap.h" #include "llvm/CodeGen/SelectionDAG.h" @@ -278,6 +279,7 @@ SDOperand AlphaDAGToDAGISel::Select(SDOperand Op) { CurDAG->SelectNodeTo(N, Alpha::LDAr, MVT::i64, CPI, Tmp); return SDOperand(N, 0); } + break; } case ISD::ConstantFP: if (ConstantFPSDNode *CN = dyn_cast(N)) { @@ -296,7 +298,76 @@ SDOperand AlphaDAGToDAGISel::Select(SDOperand Op) { } else { abort(); } + break; } + case ISD::SDIV: + case ISD::UDIV: + case ISD::UREM: + case ISD::SREM: + if (MVT::isInteger(N->getValueType(0))) { + const char* opstr = 0; + switch(N->getOpcode()) { + case ISD::UREM: opstr = "__remqu"; break; + case ISD::SREM: opstr = "__remq"; break; + case ISD::UDIV: opstr = "__divqu"; break; + case ISD::SDIV: opstr = "__divq"; break; + } + SDOperand Tmp1 = Select(N->getOperand(0)), + Tmp2 = Select(N->getOperand(1)), + Addr = CurDAG->getExternalSymbol(opstr, AlphaLowering.getPointerTy()); + SDOperand Tmp3 = Select(Addr); + SDOperand Chain = CurDAG->getCopyToReg(CurDAG->getRoot(), Alpha::R24, + Tmp1, SDOperand()); + Chain = CurDAG->getCopyToReg(CurDAG->getRoot(), Alpha::R25, + Tmp2, Chain.getValue(1)); + Chain = CurDAG->getCopyToReg(CurDAG->getRoot(), Alpha::R27, + Tmp3, Chain.getValue(1)); + Chain = CurDAG->getTargetNode(Alpha::JSRs, MVT::i64, MVT::Flag, + CurDAG->getRegister(Alpha::R27, MVT::i64), + getI64Imm(0)); + return CurDAG->getCopyFromReg(Chain.getValue(1), Alpha::R27, MVT::i64, + Chain.getValue(1)); + } + break; + + case ISD::SETCC: + if (MVT::isFloatingPoint(N->getOperand(0).Val->getValueType(0))) { + unsigned Opc = Alpha::WTF; + ISD::CondCode CC = cast(N->getOperand(2))->get(); + bool rev = false; + switch(CC) { + default: N->dump(); assert(0 && "Unknown FP comparison!"); + case ISD::SETEQ: Opc = Alpha::CMPTEQ; break; + case ISD::SETLT: Opc = Alpha::CMPTLT; break; + case ISD::SETLE: Opc = Alpha::CMPTLE; break; + case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break; + case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break; + //case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break; + }; + SDOperand tmp1 = Select(N->getOperand(0)), + tmp2 = Select(N->getOperand(1)); + SDOperand cmp = CurDAG->getTargetNode(Opc, MVT::f64, + rev?tmp2:tmp1, + rev?tmp1:tmp2); + SDOperand LD; + if (AlphaLowering.hasITOF()) { + LD = CurDAG->getNode(AlphaISD::FTOIT_, MVT::i64, cmp); + } else { + int FrameIdx = + CurDAG->getMachineFunction().getFrameInfo()->CreateStackObject(8, 8); + SDOperand FI = CurDAG->getFrameIndex(FrameIdx, MVT::i64); + SDOperand ST = CurDAG->getTargetNode(Alpha::STT, MVT::Other, + cmp, FI, CurDAG->getRegister(Alpha::R31, MVT::i64)); + LD = CurDAG->getTargetNode(Alpha::LDQ, MVT::i64, FI, + CurDAG->getRegister(Alpha::R31, MVT::i64), + ST); + } + SDOperand FP = CurDAG->getTargetNode(Alpha::CMPULT, MVT::i64, + CurDAG->getRegister(Alpha::R31, MVT::i64), + LD); + return FP; + } + break; } return SelectCode(Op); @@ -328,13 +399,26 @@ SDOperand AlphaDAGToDAGISel::SelectCALL(SDOperand Op) { for (int i = 0; i < std::min(6, count); ++i) { if (MVT::isInteger(TypeOperands[i])) { Chain = CurDAG->getCopyToReg(Chain, args_int[i], CallOperands[i]); - } else if (TypeOperands[i] == MVT::f64 || TypeOperands[i] == MVT::f64) { + } else if (TypeOperands[i] == MVT::f32 || TypeOperands[i] == MVT::f64) { Chain = CurDAG->getCopyToReg(Chain, args_float[i], CallOperands[i]); } else assert(0 && "Unknown operand"); } - - assert(CallOperands.size() <= 6 && "Too big a call"); + for (int i = 6; i < count; ++i) { + unsigned Opc = Alpha::WTF; + if (MVT::isInteger(TypeOperands[i])) { + Opc = Alpha::STQ; + } else if (TypeOperands[i] == MVT::f32) { + Opc = Alpha::STS; + } else if (TypeOperands[i] == MVT::f64) { + Opc = Alpha::STT; + } else + assert(0 && "Unknown operand"); + Chain = CurDAG->getTargetNode(Opc, MVT::Other, CallOperands[i], + getI64Imm((i - 6) * 8), + CurDAG->getRegister(Alpha::R30, MVT::i64), + Chain); + } Chain = CurDAG->getCopyToReg(Chain, Alpha::R27, Addr); // Finally, once everything is in registers to pass to the call, emit the diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index 021c92db3c9..92ba16e21bf 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -72,6 +72,7 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) setOperationAction(ISD::FREM, MVT::f64, Expand); setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); + setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); if (!TM.getSubtarget().hasCT()) { setOperationAction(ISD::CTPOP , MVT::i64 , Expand); @@ -101,10 +102,12 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) // We don't have line number support yet. setOperationAction(ISD::LOCATION, MVT::Other, Expand); - computeRegisterProperties(); - addLegalFPImmediate(+0.0); //F31 addLegalFPImmediate(-0.0); //-F31 + + computeRegisterProperties(); + + useITOF = TM.getSubtarget().hasF2I(); } @@ -385,3 +388,31 @@ void AlphaTargetLowering::restoreRA(MachineBasicBlock* BB) } +/// LowerOperation - Provide custom lowering hooks for some operations. +/// +SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + default: assert(0 && "Wasn't expecting to be able to lower this!"); + case ISD::SINT_TO_FP: { + assert(MVT::i64 == Op.getOperand(0).getValueType() && + "Unhandled SINT_TO_FP type in custom expander!"); + SDOperand LD; + bool isDouble = MVT::f64 == Op.getValueType(); + if (useITOF) { + LD = DAG.getNode(AlphaISD::ITOFT_, MVT::f64, Op.getOperand(0)); + } else { + int FrameIdx = + DAG.getMachineFunction().getFrameInfo()->CreateStackObject(8, 8); + SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i64); + SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(), + Op.getOperand(0), FI, DAG.getSrcValue(0)); + LD = DAG.getLoad(MVT::f64, ST, FI, DAG.getSrcValue(0)); + } + SDOperand FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, + isDouble?MVT::f64:MVT::f32, LD); + return FP; + } + } + return SDOperand(); +} + diff --git a/lib/Target/Alpha/AlphaISelLowering.h b/lib/Target/Alpha/AlphaISelLowering.h index 2bcd526d8fd..378ec0f9247 100644 --- a/lib/Target/Alpha/AlphaISelLowering.h +++ b/lib/Target/Alpha/AlphaISelLowering.h @@ -25,6 +25,8 @@ namespace llvm { enum NodeType { // Start the numbering where the builting ops and target ops leave off. FIRST_NUMBER = ISD::BUILTIN_OP_END+Alpha::INSTRUCTION_LIST_END, + //These corrospond to the identical Instruction + ITOFT_, FTOIT_, CVTQT_, CVTQS_, }; } @@ -33,9 +35,14 @@ namespace llvm { int VarArgsBase; // What is the base FrameIndex unsigned GP; //GOT vreg unsigned RA; //Return Address + bool useITOF; public: AlphaTargetLowering(TargetMachine &TM); - + + /// LowerOperation - Provide custom lowering hooks for some operations. + /// + virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); + /// 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 @@ -61,6 +68,7 @@ namespace llvm { void restoreRA(MachineBasicBlock* BB); unsigned getVRegGP() { return GP; } unsigned getVRegRA() { return RA; } + bool hasITOF() { return useITOF; } }; } diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp index 6c2e3a6f53d..05ed61f8cf5 100644 --- a/lib/Target/Alpha/AlphaISelPattern.cpp +++ b/lib/Target/Alpha/AlphaISelPattern.cpp @@ -1559,17 +1559,17 @@ unsigned AlphaISel::SelectExpr(SDOperand N) { } return Result; - case ISD::SINT_TO_FP: - { - assert (N.getOperand(0).getValueType() == MVT::i64 - && "only quads can be loaded from"); - Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register - Tmp2 = MakeReg(MVT::f64); - MoveInt2FP(Tmp1, Tmp2, true); - Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS; - BuildMI(BB, Opc, 1, Result).addReg(Tmp2); - return Result; - } + case AlphaISD::CVTQT_: + BuildMI(BB, Alpha::CVTQT, 1, Result).addReg(SelectExpr(N.getOperand(0))); + return Result; + + case AlphaISD::CVTQS_: + BuildMI(BB, Alpha::CVTQS, 1, Result).addReg(SelectExpr(N.getOperand(0))); + return Result; + + case AlphaISD::ITOFT_: + BuildMI(BB, Alpha::ITOFT, 1, Result).addReg(SelectExpr(N.getOperand(0))); + return Result; case ISD::AssertSext: case ISD::AssertZext: diff --git a/lib/Target/Alpha/AlphaInstrFormats.td b/lib/Target/Alpha/AlphaInstrFormats.td index 1f446072758..1d4c11d1d82 100644 --- a/lib/Target/Alpha/AlphaInstrFormats.td +++ b/lib/Target/Alpha/AlphaInstrFormats.td @@ -40,6 +40,16 @@ class InstAlpha op, dag OL, string asmstr> } //3.3.1 +class MFormAlt opcode, string asmstr> + : InstAlphaAlt { + bits<5> Ra; + bits<16> disp; + bits<5> Rb; + + let Inst{25-21} = Ra; + let Inst{20-16} = Rb; + let Inst{15-0} = disp; +} class MForm opcode, string asmstr> : InstAlpha { bits<5> Ra; diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td index aea28619947..6bd9d78d88a 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.td +++ b/lib/Target/Alpha/AlphaInstrInfo.td @@ -12,6 +12,20 @@ include "AlphaInstrFormats.td" +//******************** +//Custom DAG Nodes +//******************** + +def SDTFPUnaryOpUnC : SDTypeProfile<1, 1, [ + SDTCisFP<1>, SDTCisFP<0> +]>; + +def Alpha_itoft : SDNode<"AlphaISD::ITOFT_", SDTIntToFPOp, []>; +def Alpha_ftoit : SDNode<"AlphaISD::FTOIT_", SDTFPToIntOp, []>; +def Alpha_cvtqt : SDNode<"AlphaISD::CVTQT_", SDTFPUnaryOpUnC, []>; +def Alpha_cvtqs : SDNode<"AlphaISD::CVTQS_", SDTFPUnaryOpUnC, []>; + + //******************** //Paterns for matching //******************** @@ -143,6 +157,10 @@ def CMOVLTi : OForm4L< 0x11, 0x44, "cmovlt $RCOND,$L,$RDEST">; //CMOVE if RCOND def CMOVNE : OForm4< 0x11, 0x26, "cmovne $RCOND,$RSRC,$RDEST">; //CMOVE if RCOND != zero def CMOVNEi : OForm4L< 0x11, 0x26, "cmovne $RCOND,$L,$RDEST">; //CMOVE if RCOND != zero +//FIXME: fold setcc with select +def : Pat<(select GPRC:$which, GPRC:$src1, GPRC:$src2), + (CMOVEQ GPRC:$src1, GPRC:$src2, GPRC:$which)>; + //conditional moves, fp let OperandList = (ops F8RC:$RDEST, F8RC:$RSRC2, F8RC:$RSRC, F8RC:$RCOND), isTwoAddress = 1 in { @@ -409,12 +427,16 @@ def LDBU : MForm<0x0A, "ldbu $RA,$DISP($RB)">; //Load zero-extended byte def LDWU : MForm<0x0C, "ldwu $RA,$DISP($RB)">; //Load zero-extended word //Stores, float -def STS : MForm<0x26, "sts $RA,$DISP($RB)">; //Store S_floating -def STT : MForm<0x27, "stt $RA,$DISP($RB)">; //Store T_floating +let OperandList = (ops F4RC:$RA, s16imm:$DISP, GPRC:$RB) in +def STS : MFormAlt<0x26, "sts $RA,$DISP($RB)">; //Store S_floating +let OperandList = (ops F8RC:$RA, s16imm:$DISP, GPRC:$RB) in +def STT : MFormAlt<0x27, "stt $RA,$DISP($RB)">; //Store T_floating //Loads, float -def LDS : MForm<0x22, "lds $RA,$DISP($RB)">; //Load S_floating -def LDT : MForm<0x23, "ldt $RA,$DISP($RB)">; //Load T_floating +let OperandList = (ops F4RC:$RA, s16imm:$DISP, GPRC:$RB) in +def LDS : MFormAlt<0x22, "lds $RA,$DISP($RB)">; //Load S_floating +let OperandList = (ops F8RC:$RA, s16imm:$DISP, GPRC:$RB) in +def LDT : MFormAlt<0x23, "ldt $RA,$DISP($RB)">; //Load T_floating //Load address def LDA : MForm<0x08, "lda $RA,$DISP($RB)">; //Load address @@ -428,8 +450,10 @@ def LDBUr : MForm<0x0A, "ldbu $RA,$DISP($RB)\t\t!gprellow">; //Load zero-extende def LDWUr : MForm<0x0C, "ldwu $RA,$DISP($RB)\t\t!gprellow">; //Load zero-extended word //Loads, float, Rellocated Low form -def LDSr : MForm<0x22, "lds $RA,$DISP($RB)\t\t!gprellow">; //Load S_floating -def LDTr : MForm<0x23, "ldt $RA,$DISP($RB)\t\t!gprellow">; //Load T_floating +let OperandList = (ops F4RC:$RA, s16imm:$DISP, GPRC:$RB) in +def LDSr : MFormAlt<0x22, "lds $RA,$DISP($RB)\t\t!gprellow">; //Load S_floating +let OperandList = (ops F8RC:$RA, s16imm:$DISP, GPRC:$RB) in +def LDTr : MFormAlt<0x23, "ldt $RA,$DISP($RB)\t\t!gprellow">; //Load T_floating //Load address, rellocated low and high form def LDAr : MForm<0x08, "lda $RA,$DISP($RB)\t\t!gprellow">; //Load address @@ -450,8 +474,10 @@ def STLr : MForm<0x2C, "stl $RA,$DISP($RB)\t\t!gprellow">; // Store longword def STQr : MForm<0x2D, "stq $RA,$DISP($RB)\t\t!gprellow">; //Store quadword //Stores, float -def STSr : MForm<0x26, "sts $RA,$DISP($RB)\t\t!gprellow">; //Store S_floating -def STTr : MForm<0x27, "stt $RA,$DISP($RB)\t\t!gprellow">; //Store T_floating +let OperandList = (ops F4RC:$RA, s16imm:$DISP, GPRC:$RB) in +def STSr : MFormAlt<0x26, "sts $RA,$DISP($RB)\t\t!gprellow">; //Store S_floating +let OperandList = (ops F8RC:$RA, s16imm:$DISP, GPRC:$RB) in +def STTr : MFormAlt<0x27, "stt $RA,$DISP($RB)\t\t!gprellow">; //Store T_floating //Branches, int @@ -533,17 +559,21 @@ def CMPTUN : FPForm<0x16, 0x5A4, "cmptun/su $RA,$RB,$RC", []>; let OperandList = (ops GPRC:$RC, F4RC:$RA), Fb = 31 in def FTOIS : FPForm<0x1C, 0x078, "ftois $RA,$RC",[]>; //Floating to integer move, S_floating let OperandList = (ops GPRC:$RC, F8RC:$RA), Fb = 31 in -def FTOIT : FPForm<0x1C, 0x070, "ftoit $RA,$RC",[]>; //Floating to integer move, T_floating +def FTOIT : FPForm<0x1C, 0x070, "ftoit $RA,$RC", + [(set GPRC:$RC, (Alpha_ftoit F8RC:$RA))]>; //Floating to integer move let OperandList = (ops F4RC:$RC, GPRC:$RA), Fb = 31 in def ITOFS : FPForm<0x14, 0x004, "itofs $RA,$RC",[]>; //Integer to floating move, S_floating let OperandList = (ops F8RC:$RC, GPRC:$RA), Fb = 31 in -def ITOFT : FPForm<0x14, 0x024, "itoft $RA,$RC",[]>; //Integer to floating move, T_floating +def ITOFT : FPForm<0x14, 0x024, "itoft $RA,$RC", + [(set F8RC:$RC, (Alpha_itoft GPRC:$RA))]>; //Integer to floating move let OperandList = (ops F4RC:$RC, F8RC:$RB), Fa = 31 in -def CVTQS : FPForm<0x16, 0x7BC, "cvtqs/sui $RB,$RC",[]>; //Convert quadword to S_floating +def CVTQS : FPForm<0x16, 0x7BC, "cvtqs/sui $RB,$RC", + [(set F4RC:$RC, (Alpha_cvtqs F8RC:$RB))]>; let OperandList = (ops F8RC:$RC, F8RC:$RB), Fa = 31 in -def CVTQT : FPForm<0x16, 0x7BE, "cvtqt/sui $RB,$RC",[]>; //Convert quadword to T_floating +def CVTQT : FPForm<0x16, 0x7BE, "cvtqt/sui $RB,$RC", + [(set F8RC:$RC, (Alpha_cvtqt F8RC:$RB))]>; let OperandList = (ops F8RC:$RC, F8RC:$RB), Fa = 31 in def CVTTQ : FPForm<0x16, 0x52F, "cvttq/svc $RB,$RC",[]>; //Convert T_floating to quadword let OperandList = (ops F8RC:$RC, F4RC:$RB), Fa = 31 in @@ -648,3 +678,11 @@ def : Pat<(sext_inreg GPRC:$RB, i32), def : Pat<(select GPRC:$which, GPRC:$src1, GPRC:$src2), (CMOVEQ GPRC:$src1, GPRC:$src2, GPRC:$which)>; //may be CMOVNE +def : Pat<(fabs F8RC:$RB), + (CPYST F31, F8RC:$RB)>; +def : Pat<(fabs F4RC:$RB), + (CPYSS F31, F4RC:$RB)>; +def : Pat<(fneg F8RC:$RB), + (CPYSNT F8RC:$RB, F8RC:$RB)>; +def : Pat<(fneg F4RC:$RB), + (CPYSNS F4RC:$RB, F4RC:$RB)>; diff --git a/lib/Target/Alpha/AlphaRegisterInfo.td b/lib/Target/Alpha/AlphaRegisterInfo.td index b99086553f6..b0884360861 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.td +++ b/lib/Target/Alpha/AlphaRegisterInfo.td @@ -78,7 +78,6 @@ def F30 : FPR<30, "$f30">; def F31 : FPR<31, "$f31">; // $28 is undefined after any and all calls /// Register classes -// Don't allocate 15, 28, 30, 31 def GPRC : RegisterClass<"Alpha", i64, 64, // Volatile [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, @@ -89,7 +88,8 @@ def GPRC : RegisterClass<"Alpha", i64, 64, R29, //global offset table address // Non-volatile R9, R10, R11, R12, R13, R14, - R31 ]> //zero +// Don't allocate 15, 30, 31 + R15, R30, R31 ]> //zero { let MethodProtos = [{ iterator allocation_order_end(MachineFunction &MF) const; @@ -97,7 +97,7 @@ def GPRC : RegisterClass<"Alpha", i64, 64, let MethodBodies = [{ GPRCClass::iterator GPRCClass::allocation_order_end(MachineFunction &MF) const { - return end()-1; + return end()-3; } }]; }