- Add target lowering hooks that specify which setcc conditions are illegal,
authorEvan Cheng <evan.cheng@apple.com>
Wed, 15 Oct 2008 02:05:31 +0000 (02:05 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Wed, 15 Oct 2008 02:05:31 +0000 (02:05 +0000)
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

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 [new file with mode: 0644]

index c9ea40125f5ee24668c47e8aef5b76a480c88a12..cd751639b894bceb0c463a435976bc1bc29dc59b 100644 (file)
@@ -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<APFloat> LegalFPImmediates;
index 9fa06280294981abc01b4214d4a9a567f41ce770..ec4cd877965434e8cd37cc21ad7a7bd20277842c 100644 (file)
@@ -193,6 +193,11 @@ private:
                                     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 @@ 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<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.
index d60ae2eacff37ade9bd57537b1a25af451a6ecff..4e4fd2b7d36b97653a2468c0011b4a07667f76bf 100644 (file)
@@ -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) {
index 1841de2dc874deacf78a1d8eb2d653aee321bbe4..f21055782df4474688666cc4b5e361e93c9aa265 100644 (file)
@@ -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 (file)
index 0000000..25a2b7e
--- /dev/null
@@ -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
+}