[llvm-commits] [llvm] r57542 - in /llvm/trunk: include/llvm/Target/TargetLowering.h lib/CodeGen/SelectionDAG/LegalizeDAG.cpp lib/CodeGen/SelectionDAG/TargetLowering.cpp lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/setoeq.ll

Evan Cheng evan.cheng at apple.com
Tue Oct 14 19:05:33 PDT 2008


Author: evancheng
Date: Tue Oct 14 21:05:31 2008
New Revision: 57542

URL: http://llvm.org/viewvc/llvm-project?rev=57542&view=rev
Log:
- 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.

Added:
    llvm/trunk/test/CodeGen/X86/setoeq.ll
Modified:
    llvm/trunk/include/llvm/Target/TargetLowering.h
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp

Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=57542&r1=57541&r2=57542&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
+++ llvm/trunk/include/llvm/Target/TargetLowering.h Tue Oct 14 21:05:31 2008
@@ -409,6 +409,28 @@
        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 @@
       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 @@
   /// (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<APFloat> LegalFPImmediates;

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=57542&r1=57541&r2=57542&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Tue Oct 14 21:05:31 2008
@@ -193,6 +193,11 @@
                                     SmallPtrSet<SDNode*, 32> &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 @@
     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 @@
     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 @@
     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 @@
   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<CondCodeSDNode>(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.

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=57542&r1=57541&r2=57542&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Tue Oct 14 21:05:31 2008
@@ -406,6 +406,7 @@
   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) {

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=57542&r1=57541&r2=57542&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Oct 14 21:05:31 2008
@@ -92,7 +92,15 @@
   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 @@
                        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) {

Added: llvm/trunk/test/CodeGen/X86/setoeq.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setoeq.ll?rev=57542&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/setoeq.ll (added)
+++ llvm/trunk/test/CodeGen/X86/setoeq.ll Tue Oct 14 21:05:31 2008
@@ -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		; <i32> [#uses=1]
+	%1 = sitofp i32 %0 to double		; <double> [#uses=1]
+	%2 = fcmp oeq double %1, %x		; <i1> [#uses=1]
+	%retval12 = zext i1 %2 to i8		; <i8> [#uses=1]
+	ret i8 %retval12
+}





More information about the llvm-commits mailing list