From: Evan Cheng Date: Wed, 15 Oct 2008 02:05:31 +0000 (+0000) Subject: - Add target lowering hooks that specify which setcc conditions are illegal, X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=7f042681764c6f8eae22781d8b4cb4c218a86b76;p=oota-llvm.git - Add target lowering hooks that specify which setcc conditions are illegal, i.e. conditions that cannot be checked with a single instruction. For example, SETONE and SETUEQ on x86. - Teach legalizer to implement *illegal* setcc as a and / or of a number of legal setcc nodes. For now, only implement FP conditions. e.g. SETONE is implemented as SETO & SETNE, SETUEQ is SETUO | SETEQ. - Move x86 target over. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57542 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index c9ea40125f5..cd751639b89 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -409,6 +409,28 @@ public: getConvertAction(FromVT, ToVT) == Custom); } + /// getCondCodeAction - Return how the condition code should be treated: + /// either it is legal, needs to be expanded to some other code sequence, + /// or the target has a custom expander for it. + LegalizeAction + getCondCodeAction(ISD::CondCode CC, MVT VT) const { + assert((unsigned)CC < array_lengthof(CondCodeActions) && + (unsigned)VT.getSimpleVT() < sizeof(CondCodeActions[0])*4 && + "Table isn't big enough!"); + LegalizeAction Action = (LegalizeAction) + ((CondCodeActions[CC] >> (2*VT.getSimpleVT())) & 3); + assert(Action != Promote && "Can't promote condition code!"); + return Action; + } + + /// isCondCodeLegal - Return true if the specified condition code is legal + /// on this target. + bool isCondCodeLegal(ISD::CondCode CC, MVT VT) const { + return getCondCodeAction(CC, VT) == Legal || + getCondCodeAction(CC, VT) == Custom; + } + + /// getTypeToPromoteTo - If the action for this operation is to promote, this /// method returns the ValueType to promote to. MVT getTypeToPromoteTo(unsigned Op, MVT VT) const { @@ -903,6 +925,16 @@ protected: ToVT.getSimpleVT()*2; } + /// setCondCodeAction - Indicate that the specified condition code is or isn't + /// supported on the target and indicate what to do about it. + void setCondCodeAction(ISD::CondCode CC, MVT VT, LegalizeAction Action) { + assert((unsigned)VT.getSimpleVT() < sizeof(CondCodeActions[0])*4 && + (unsigned)CC < array_lengthof(CondCodeActions) && + "Table isn't big enough!"); + CondCodeActions[(unsigned)CC] &= ~(uint64_t(3UL) << VT.getSimpleVT()*2); + CondCodeActions[(unsigned)CC] |= (uint64_t)Action << VT.getSimpleVT()*2; + } + /// AddPromotedToType - If Opc/OrigVT is specified as being promoted, the /// promotion code defaults to trying a larger integer/fp until it can find /// one that works. If that default is insufficient, this method can be used @@ -1437,6 +1469,11 @@ private: /// (FP_EXTEND and FP_ROUND). uint64_t ConvertActions[MVT::LAST_VALUETYPE]; + /// CondCodeActions - For each condition code (ISD::CondCode) keep a + /// LegalizeAction that indicates how instruction selection should + /// deal with the condition code. + uint64_t CondCodeActions[ISD::SETCC_INVALID]; + ValueTypeActionImpl ValueTypeActions; std::vector LegalFPImmediates; diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 9fa06280294..ec4cd877965 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -193,6 +193,11 @@ private: SmallPtrSet &NodesLeadingTo); void LegalizeSetCCOperands(SDValue &LHS, SDValue &RHS, SDValue &CC); + void LegalizeSetCCCondCode(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC); + void LegalizeSetCC(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC) { + LegalizeSetCCOperands(LHS, RHS, CC); + LegalizeSetCCCondCode(VT, LHS, RHS, CC); + } SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned, SDValue &Hi); @@ -1886,10 +1891,10 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp3 = Node->getOperand(3); // RHS Tmp4 = Node->getOperand(1); // CC - LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4); + LegalizeSetCC(Node->getValueType(0), Tmp2, Tmp3, Tmp4); LastCALLSEQ_END = DAG.getEntryNode(); - // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, + // If we didn't get both a LHS and RHS back from LegalizeSetCC, // the LHS is a legal SETCC itself. In this case, we need to compare // the result against zero to select between true and false values. if (Tmp3.getNode() == 0) { @@ -2772,9 +2777,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp4 = LegalizeOp(Node->getOperand(3)); // False SDValue CC = Node->getOperand(4); - LegalizeSetCCOperands(Tmp1, Tmp2, CC); + LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, CC); - // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, + // If we didn't get both a LHS and RHS back from LegalizeSetCC, // the LHS is a legal SETCC itself. In this case, we need to compare // the result against zero to select between true and false values. if (Tmp2.getNode() == 0) { @@ -2798,7 +2803,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp1 = Node->getOperand(0); Tmp2 = Node->getOperand(1); Tmp3 = Node->getOperand(2); - LegalizeSetCCOperands(Tmp1, Tmp2, Tmp3); + LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, Tmp3); // If we had to Expand the SetCC operands into a SELECT node, then it may // not always be possible to return a true LHS & RHS. In this case, just @@ -4877,6 +4882,50 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDValue &LHS, RHS = Tmp2; } +/// LegalizeSetCCCondCode - Legalize a SETCC with given LHS and RHS and +/// condition code CC on the current target. This routine assumes LHS and rHS +/// have already been legalized by LegalizeSetCCOperands. It expands SETCC with +/// illegal condition code into AND / OR of multiple SETCC values. +void SelectionDAGLegalize::LegalizeSetCCCondCode(MVT VT, + SDValue &LHS, SDValue &RHS, + SDValue &CC) { + MVT OpVT = LHS.getValueType(); + ISD::CondCode CCCode = cast(CC)->get(); + switch (TLI.getCondCodeAction(CCCode, OpVT)) { + default: assert(0 && "Unknown condition code action!"); + case TargetLowering::Legal: + // Nothing to do. + break; + case TargetLowering::Expand: { + ISD::CondCode CC1 = ISD::SETCC_INVALID, CC2 = ISD::SETCC_INVALID; + unsigned Opc = 0; + switch (CCCode) { + default: assert(0 && "Don't know how to expand this condition!"); abort(); + case ISD::SETOEQ: CC1 = ISD::SETO; CC2 = ISD::SETEQ; Opc = ISD::AND; break; + case ISD::SETOGT: CC1 = ISD::SETO; CC2 = ISD::SETGT; Opc = ISD::AND; break; + case ISD::SETOGE: CC1 = ISD::SETO; CC2 = ISD::SETGE; Opc = ISD::AND; break; + case ISD::SETOLT: CC1 = ISD::SETO; CC2 = ISD::SETLT; Opc = ISD::AND; break; + case ISD::SETOLE: CC1 = ISD::SETO; CC2 = ISD::SETLE; Opc = ISD::AND; break; + case ISD::SETONE: CC1 = ISD::SETO; CC2 = ISD::SETNE; Opc = ISD::AND; break; + case ISD::SETUEQ: CC1 = ISD::SETUO; CC2 = ISD::SETEQ; Opc = ISD::OR; break; + case ISD::SETUGT: CC1 = ISD::SETUO; CC2 = ISD::SETGT; Opc = ISD::OR; break; + case ISD::SETUGE: CC1 = ISD::SETUO; CC2 = ISD::SETGE; Opc = ISD::OR; break; + case ISD::SETULT: CC1 = ISD::SETUO; CC2 = ISD::SETLT; Opc = ISD::OR; break; + case ISD::SETULE: CC1 = ISD::SETUO; CC2 = ISD::SETLE; Opc = ISD::OR; break; + case ISD::SETUNE: CC1 = ISD::SETUO; CC2 = ISD::SETNE; Opc = ISD::OR; break; + // FIXME: Implement more expansions. + } + + SDValue SetCC1 = DAG.getSetCC(VT, LHS, RHS, CC1); + SDValue SetCC2 = DAG.getSetCC(VT, LHS, RHS, CC2); + LHS = DAG.getNode(Opc, VT, SetCC1, SetCC2); + RHS = SDValue(); + CC = SDValue(); + break; + } + } +} + /// EmitStackConvert - Emit a store/load combination to the stack. This stores /// SrcOp to a stack slot of type SlotVT, truncating it if needed. It then does /// a load from the stack slot to DestVT, extending it if needed. diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index d60ae2eacff..4e4fd2b7d36 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -406,6 +406,7 @@ TargetLowering::TargetLowering(TargetMachine &tm) memset(TruncStoreActions, 0, sizeof(TruncStoreActions)); memset(IndexedModeActions, 0, sizeof(IndexedModeActions)); memset(ConvertActions, 0, sizeof(ConvertActions)); + memset(CondCodeActions, 0, sizeof(CondCodeActions)); // Set default actions for various operations. for (unsigned VT = 0; VT != (unsigned)MVT::LAST_VALUETYPE; ++VT) { diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 1841de2dc87..f21055782df 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -92,7 +92,15 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) setTruncStoreAction(MVT::i64, MVT::i8 , Expand); setTruncStoreAction(MVT::i32, MVT::i16, Expand); setTruncStoreAction(MVT::i32, MVT::i8 , Expand); - setTruncStoreAction(MVT::i16, MVT::i8, Expand); + setTruncStoreAction(MVT::i16, MVT::i8, Expand); + + // SETOEQ and SETUNE require checking two conditions. + setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand); + setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand); + setCondCodeAction(ISD::SETOEQ, MVT::f80, Expand); + setCondCodeAction(ISD::SETUNE, MVT::f32, Expand); + setCondCodeAction(ISD::SETUNE, MVT::f64, Expand); + setCondCodeAction(ISD::SETUNE, MVT::f80, Expand); // Promote all UINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have this // operation. @@ -4883,26 +4891,8 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { DAG.getConstant(X86CC, MVT::i8), Cond); } - assert(isFP && "Illegal integer SetCC!"); - - Cond = DAG.getNode(X86ISD::CMP, MVT::i32, Op0, Op1); - switch (SetCCOpcode) { - default: assert(false && "Illegal floating point SetCC!"); - case ISD::SETOEQ: { // !PF & ZF - SDValue Tmp1 = DAG.getNode(X86ISD::SETCC, MVT::i8, - DAG.getConstant(X86::COND_NP, MVT::i8), Cond); - SDValue Tmp2 = DAG.getNode(X86ISD::SETCC, MVT::i8, - DAG.getConstant(X86::COND_E, MVT::i8), Cond); - return DAG.getNode(ISD::AND, MVT::i8, Tmp1, Tmp2); - } - case ISD::SETUNE: { // PF | !ZF - SDValue Tmp1 = DAG.getNode(X86ISD::SETCC, MVT::i8, - DAG.getConstant(X86::COND_P, MVT::i8), Cond); - SDValue Tmp2 = DAG.getNode(X86ISD::SETCC, MVT::i8, - DAG.getConstant(X86::COND_NE, MVT::i8), Cond); - return DAG.getNode(ISD::OR, MVT::i8, Tmp1, Tmp2); - } - } + assert(0 && "Illegal SetCC!"); + return SDValue(); } SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) { diff --git a/test/CodeGen/X86/setoeq.ll b/test/CodeGen/X86/setoeq.ll new file mode 100644 index 00000000000..25a2b7e0b49 --- /dev/null +++ b/test/CodeGen/X86/setoeq.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as < %s | llc -march=x86 | grep set | count 2 +; RUN: llvm-as < %s | llc -march=x86 | grep and + +define zeroext i8 @t(double %x) nounwind readnone { +entry: + %0 = fptosi double %x to i32 ; [#uses=1] + %1 = sitofp i32 %0 to double ; [#uses=1] + %2 = fcmp oeq double %1, %x ; [#uses=1] + %retval12 = zext i1 %2 to i8 ; [#uses=1] + ret i8 %retval12 +}