From 10c085b52557d002ba00ce741127b87e58845f7f Mon Sep 17 00:00:00 2001 From: Andrew Lenharth Date: Sat, 2 Apr 2005 22:32:39 +0000 Subject: [PATCH] Select optimization git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21051 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Alpha/AlphaISelPattern.cpp | 197 ++++++++++++++++++-------- lib/Target/Alpha/AlphaInstrInfo.td | 2 + 2 files changed, 143 insertions(+), 56 deletions(-) diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp index 9393b92373d..6f093ba65f8 100644 --- a/lib/Target/Alpha/AlphaISelPattern.cpp +++ b/lib/Target/Alpha/AlphaISelPattern.cpp @@ -335,6 +335,8 @@ public: void SelectBranchCC(SDOperand N); void MoveFP2Int(unsigned src, unsigned dst, bool isDouble); void MoveInt2FP(unsigned src, unsigned dst, bool isDouble); + //returns whether the sense of the comparison was inverted + bool SelectFPSetCC(SDOperand N, unsigned dst); }; } @@ -418,6 +420,64 @@ void ISel::MoveInt2FP(unsigned src, unsigned dst, bool isDouble) } } +bool ISel::SelectFPSetCC(SDOperand N, unsigned dst) +{ + SDNode *Node = N.Val; + unsigned Opc, Tmp1, Tmp2, Tmp3; + SetCCSDNode *SetCC = dyn_cast(Node); + + //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted"); + bool rev = false; + bool inv = false; + + switch (SetCC->getCondition()) { + default: Node->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; + } + + //FIXME: check for constant 0.0 + ConstantFPSDNode *CN; + if ((CN = dyn_cast(SetCC->getOperand(0))) + && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0))) + Tmp1 = Alpha::F31; + else + Tmp1 = SelectExpr(N.getOperand(0)); + + if ((CN = dyn_cast(SetCC->getOperand(1))) + && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0))) + Tmp2 = Alpha::F31; + else + Tmp2 = SelectExpr(N.getOperand(1)); + + //Can only compare doubles, and dag won't promote for me + if (SetCC->getOperand(0).getValueType() == MVT::f32) + { + //assert(0 && "Setcc On float?\n"); + std::cerr << "Setcc on float!\n"; + Tmp3 = MakeReg(MVT::f64); + BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1); + Tmp1 = Tmp3; + } + if (SetCC->getOperand(1).getValueType() == MVT::f32) + { + //assert (0 && "Setcc On float?\n"); + std::cerr << "Setcc on float!\n"; + Tmp3 = MakeReg(MVT::f64); + BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2); + Tmp2 = Tmp3; + } + + if (rev) std::swap(Tmp1, Tmp2); + //do the comparison + BuildMI(BB, Opc, 2, dst).addReg(Tmp1).addReg(Tmp2); + return inv; +} + //Check to see if the load is a constant offset from a base register void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset) { @@ -1318,62 +1378,15 @@ unsigned ISel::SelectExpr(SDOperand N) { } } } else { - //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted"); - bool rev = false; - bool inv = false; - - switch (SetCC->getCondition()) { - default: Node->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; - } - - //FIXME: check for constant 0.0 - ConstantFPSDNode *CN; - if ((CN = dyn_cast(SetCC->getOperand(0))) - && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0))) - Tmp1 = Alpha::F31; - else - Tmp1 = SelectExpr(N.getOperand(0)); - - if ((CN = dyn_cast(SetCC->getOperand(1))) - && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0))) - Tmp2 = Alpha::F31; - else - Tmp2 = SelectExpr(N.getOperand(1)); - - //Can only compare doubles, and dag won't promote for me - if (SetCC->getOperand(0).getValueType() == MVT::f32) - { - //assert(0 && "Setcc On float?\n"); - std::cerr << "Setcc on float!\n"; - Tmp3 = MakeReg(MVT::f64); - BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1); - Tmp1 = Tmp3; - } - if (SetCC->getOperand(1).getValueType() == MVT::f32) - { - //assert (0 && "Setcc On float?\n"); - std::cerr << "Setcc on float!\n"; - Tmp3 = MakeReg(MVT::f64); - BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2); - Tmp2 = Tmp3; - } - - if (rev) std::swap(Tmp1, Tmp2); - Tmp3 = MakeReg(MVT::f64); //do the comparison - BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2); - + Tmp1 = MakeReg(MVT::f64); + bool inv = SelectFPSetCC(N, Tmp1); + //now arrange for Result (int) to have a 1 or 0 - unsigned Tmp4 = MakeReg(MVT::i64); - BuildMI(BB, Alpha::ADDQi, 2, Tmp4).addReg(Alpha::R31).addImm(1); + Tmp2 = MakeReg(MVT::i64); + BuildMI(BB, Alpha::ADDQi, 2, Tmp2).addReg(Alpha::R31).addImm(1); Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP; - BuildMI(BB, Opc, 3, Result).addReg(Tmp4).addImm(0).addReg(Tmp3); + BuildMI(BB, Opc, 3, Result).addReg(Tmp2).addImm(0).addReg(Tmp1); } } return Result; @@ -1554,16 +1567,88 @@ unsigned ISel::SelectExpr(SDOperand N) { return Result; } - // // case ISD::FP_TO_UINT: - case ISD::SELECT: { //FIXME: look at parent to decide if intCC can be folded, or if setCC(FP) and can save stack use - Tmp1 = SelectExpr(N.getOperand(0)); //Cond + //Tmp1 = SelectExpr(N.getOperand(0)); //Cond Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE // Get the condition into the zero flag. + //BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1); + SDOperand CC = N.getOperand(0); + SetCCSDNode* SetCC = dyn_cast(CC.Val); + + if (CC.getOpcode() == ISD::SETCC && + !MVT::isInteger(SetCC->getOperand(0).getValueType())) + { //FP Setcc -> Int Select + Tmp1 = MakeReg(MVT::f64); + bool inv = SelectFPSetCC(CC, Tmp1); + BuildMI(BB, inv?Alpha::CMOVNE_FP:Alpha::CMOVEQ_FP, 2, Result) + .addReg(Tmp2).addReg(Tmp3).addReg(Tmp1); + return Result; + } + if (CC.getOpcode() == ISD::SETCC) { + //Int SetCC -> Select + //Dropping the CC is only useful if we are comparing to 0 + if(SetCC->getOperand(1).getOpcode() == ISD::Constant && + cast(SetCC->getOperand(0))->getValue() == 0) + { + bool useI = (SetCC->getOperand(1).getOpcode() == ISD::Constant && + cast(SetCC->getOperand(1))->getValue() <= 255); + + switch (SetCC->getCondition()) { + default: CC.Val->dump(); assert(0 && "Unknown integer comparison!"); + case ISD::SETEQ: Opc = useI?Alpha::CMOVEQi:Alpha::CMOVEQ; break; + case ISD::SETLT: Opc = useI?Alpha::CMOVGTi:Alpha::CMOVGT; break; + case ISD::SETLE: Opc = useI?Alpha::CMOVGEi:Alpha::CMOVGE; break; + case ISD::SETGT: Opc = useI?Alpha::CMOVLTi:Alpha::CMOVLT; break; + case ISD::SETGE: Opc = useI?Alpha::CMOVLEi:Alpha::CMOVLE; break; + case ISD::SETULT: Opc = useI?Alpha::CMOVNEi:Alpha::CMOVNE; break; + case ISD::SETUGT: assert(0 && "0 > (unsigned) x is never true"); break; + case ISD::SETULE: assert(0 && "0 <= (unsigned) x is always true"); break; + case ISD::SETUGE: Opc = useI?Alpha::CMOVEQi:Alpha::CMOVEQ; break; //Technically you could have this CC + case ISD::SETNE: Opc = useI?Alpha::CMOVNEi:Alpha::CMOVNE; break; + } + if (useI) + BuildMI(BB, Opc, 2, Result).addReg(Tmp2).addReg(Tmp3) + .addImm(cast(SetCC->getOperand(1))->getValue()); + else + BuildMI(BB, Opc, 2, Result).addReg(Tmp2).addReg(Tmp3) + .addReg(SelectExpr(SetCC->getOperand(1))); + return Result; + } + if(SetCC->getOperand(1).getOpcode() == ISD::Constant && + cast(SetCC->getOperand(1))->getValue() == 0) + { + bool useI = (SetCC->getOperand(0).getOpcode() == ISD::Constant && + cast(SetCC->getOperand(0))->getValue() <= 255); + + switch (SetCC->getCondition()) { + default: CC.Val->dump(); assert(0 && "Unknown integer comparison!"); + case ISD::SETEQ: Opc = useI?Alpha::CMOVEQi:Alpha::CMOVEQ; break; + case ISD::SETLT: Opc = useI?Alpha::CMOVLTi:Alpha::CMOVLT; break; + case ISD::SETLE: Opc = useI?Alpha::CMOVLEi:Alpha::CMOVLE; break; + case ISD::SETGT: Opc = useI?Alpha::CMOVGTi:Alpha::CMOVGT; break; + case ISD::SETGE: Opc = useI?Alpha::CMOVGEi:Alpha::CMOVGE; break; + case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break; + case ISD::SETUGT: Opc = useI?Alpha::CMOVNEi:Alpha::CMOVNE; break; + case ISD::SETULE: Opc = useI?Alpha::CMOVEQi:Alpha::CMOVEQ; break; //Technically you could have this CC + case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break; + case ISD::SETNE: Opc = useI?Alpha::CMOVNEi:Alpha::CMOVNE; break; + } + if (useI) + BuildMI(BB, Opc, 2, Result).addReg(Tmp2).addReg(Tmp3) + .addImm(cast(SetCC->getOperand(0))->getValue()); + else + BuildMI(BB, Opc, 2, Result).addReg(Tmp2).addReg(Tmp3) + .addReg(SelectExpr(SetCC->getOperand(0))); + return Result; + } + //Otherwise, fall though + } + Tmp1 = SelectExpr(N.getOperand(0)); //Cond BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1); + return Result; } diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td index 6b18f2b74b3..2d52ee81123 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.td +++ b/lib/Target/Alpha/AlphaInstrInfo.td @@ -55,6 +55,7 @@ let isCall = 1, let isReturn = 1, isTerminator = 1 in def RETURN : PseudoInstAlpha<(ops ), "ret $$31,($$26),1">; //Return from subroutine +//These are evil as they get expanded into multiple instructions to take care of reallocation let Uses = [R29], Defs = [R28] in { def LOAD_ADDR : PseudoInstAlpha<(ops GPRC:$RA, s64imm:$DISP), "lda $RA,$DISP">; //Load address def LDQ_SYM : PseudoInstAlpha<(ops GPRC:$RA, s64imm:$DISP), "ldq $RA,$DISP">; //Load quadword @@ -80,6 +81,7 @@ let Uses = [R29], Defs = [R28] in { //RESULTS of these go to R27 +//These are also evil as the assembler expands them into calls let Uses = [R29], Defs = [R28, R23, R24, R25, R27] in {