From 7f0db91f86cfbd7c7268f945385d7a3056150bc7 Mon Sep 17 00:00:00 2001 From: Andrew Lenharth Date: Wed, 30 Nov 2005 07:19:56 +0000 Subject: [PATCH] All sorts of stuff. Getting in on the custom lowering thing, yay evilness with fp setcc, yuck trivial int select, hmmm in memory args for functions, yay DIV and REM, always handy. They should be custom lowered though. Lots more stuff compiles now (go go single source!). Of course, none of it probably works, but that is what the nightly tester can find out :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24533 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Alpha/AlphaISelDAGToDAG.cpp | 90 +++++++++++++++++++++++++- lib/Target/Alpha/AlphaISelLowering.cpp | 35 +++++++++- lib/Target/Alpha/AlphaISelLowering.h | 10 ++- lib/Target/Alpha/AlphaISelPattern.cpp | 22 +++---- lib/Target/Alpha/AlphaInstrFormats.td | 10 +++ lib/Target/Alpha/AlphaInstrInfo.td | 62 ++++++++++++++---- lib/Target/Alpha/AlphaRegisterInfo.td | 6 +- 7 files changed, 203 insertions(+), 32 deletions(-) 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; } }]; } -- 2.34.1