Fix the fabs regression on x86 by abstracting the select_cc optimization
authorNate Begeman <natebegeman@mac.com>
Sat, 13 Aug 2005 06:00:21 +0000 (06:00 +0000)
committerNate Begeman <natebegeman@mac.com>
Sat, 13 Aug 2005 06:00:21 +0000 (06:00 +0000)
out into SimplifySelectCC.  This allows both ISD::SELECT and ISD::SELECT_CC
to use the same set of simplifying folds.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22779 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/SelectionDAG.h
lib/CodeGen/SelectionDAG/SelectionDAG.cpp

index e23f32d9d7bc722b9ac6cf5d57e22921849c4672..beb1cc9ff675fd53d21c84f7a18c39c02521598a 100644 (file)
@@ -214,12 +214,18 @@ public:
 private:
   void DeleteNodeIfDead(SDNode *N, void *NodeSet);
   
-  // Try to simplify a setcc built with the specified operands and cc.  If
-  // unable to simplify it, return a null SDOperand.
+  /// SimplifySetCC - Try to simplify a setcc built with the specified operands 
+  /// and cc.  If unable to simplify it, return a null SDOperand.
   SDOperand SimplifySetCC(MVT::ValueType VT, SDOperand N1,
                           SDOperand N2, ISD::CondCode Cond);
 
-  
+  /// SimplifySelectCC - Try to simplify a select_cc built with the specified
+  /// operands and cc.  This can be used to simplify both the select_cc node,
+  /// and a select node whose first operand is a setcc.
+  SDOperand SimplifySelectCC(MVT::ValueType VT, ISD::CondCode CC,
+                             SDOperand N1, SDOperand N2, SDOperand N3,
+                             SDOperand N4);
+    
   // Maps to auto-CSE operations.
   std::map<std::pair<unsigned, std::pair<SDOperand, MVT::ValueType> >,
            SDNode *> UnaryOps;
index 342148adb4ab8ff00df336c2d2d15043ea6fc320..9da30f1cf505a9f03d8339621550cd84702eb803 100644 (file)
@@ -686,6 +686,80 @@ SDOperand SelectionDAG::SimplifySetCC(MVT::ValueType VT, SDOperand N1,
   return SDOperand();
 }
 
+SDOperand SelectionDAG::SimplifySelectCC(MVT::ValueType VT, ISD::CondCode CC,
+                                    SDOperand N1, SDOperand N2, SDOperand N3,
+                                    SDOperand N4) {
+  ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.Val);
+  ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N3.Val);
+  ConstantSDNode *N4C = dyn_cast<ConstantSDNode>(N4.Val);
+  
+  // Check to see if we can simplify the select into an fabs node
+  if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(N2)) {
+    // Allow either -0.0 or 0.0
+    if (CFP->getValue() == 0.0) {
+      // select (setg[te] X, +/-0.0), X, fneg(X) -> fabs
+      if ((CC == ISD::SETGE || CC == ISD::SETGT) &&
+          N1 == N3 && N4.getOpcode() == ISD::FNEG &&
+          N1 == N4.getOperand(0))
+        return getNode(ISD::FABS, VT, N1);
+      
+      // select (setl[te] X, +/-0.0), fneg(X), X -> fabs
+      if ((CC == ISD::SETLT || CC == ISD::SETLE) &&
+          N1 == N4 && N3.getOpcode() == ISD::FNEG &&
+          N3.getOperand(0) == N4)
+        return getNode(ISD::FABS, VT, N4);
+    }
+  }
+  
+  // Check to see if we can perform the "gzip trick", transforming
+  // select_cc setlt X, 0, A, 0 -> and (sra X, size(X)-1), A
+  if (N2C && N2C->isNullValue() && N4C && N4C->isNullValue() &&
+      MVT::isInteger(N1.getValueType()) && 
+      MVT::isInteger(N3.getValueType()) && CC == ISD::SETLT) {
+    MVT::ValueType XType = N1.getValueType();
+    MVT::ValueType AType = N3.getValueType();
+    if (XType >= AType) {
+      // and (sra X, size(X)-1, A) -> "and (srl X, C2), A" iff A is a
+      // single-bit constant.  FIXME: remove once the dag combiner
+      // exists.
+      if (N3C && ((N3C->getValue() & (N3C->getValue()-1)) == 0)) {
+        unsigned ShCtV = Log2_64(N3C->getValue());
+        ShCtV = MVT::getSizeInBits(XType)-ShCtV-1;
+        SDOperand ShCt = getConstant(ShCtV, TLI.getShiftAmountTy());
+        SDOperand Shift = getNode(ISD::SRL, XType, N1, ShCt);
+        if (XType > AType)
+          Shift = getNode(ISD::TRUNCATE, AType, Shift);
+        return getNode(ISD::AND, AType, Shift, N3);
+      }
+      SDOperand Shift = getNode(ISD::SRA, XType, N1,
+                                getConstant(MVT::getSizeInBits(XType)-1,
+                                            TLI.getShiftAmountTy()));
+      if (XType > AType)
+        Shift = getNode(ISD::TRUNCATE, AType, Shift);
+      return getNode(ISD::AND, AType, Shift, N3);
+    }
+  }
+  
+  // Check to see if this is an integer abs. select_cc setl[te] X, 0, -X, X ->
+  // Y = sra (X, size(X)-1); xor (add (X, Y), Y)
+  if (N2C && N2C->isNullValue() && (CC == ISD::SETLT || CC == ISD::SETLE) &&
+      N1 == N4 && N3.getOpcode() == ISD::SUB && N1 == N3.getOperand(1)) {
+    if (ConstantSDNode *SubC = dyn_cast<ConstantSDNode>(N3.getOperand(0))) {
+      MVT::ValueType XType = N1.getValueType();
+      if (SubC->isNullValue() && MVT::isInteger(XType)) {
+        SDOperand Shift = getNode(ISD::SRA, XType, N1,
+                                  getConstant(MVT::getSizeInBits(XType)-1,
+                                              TLI.getShiftAmountTy()));
+        return getNode(ISD::XOR, XType, getNode(ISD::ADD, XType, N1, Shift), 
+                       Shift);
+      }
+    }
+  }
+  
+  // Could not fold it.
+  return SDOperand();
+}
+
 /// getNode - Gets or creates the specified node.
 ///
 SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT) {
@@ -1415,6 +1489,12 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
       if (N1 == N3)   // X ? Y : X --> X ? Y : 0 --> X & Y
         return getNode(ISD::AND, VT, N1, N2);
     }
+    if (N1.getOpcode() == ISD::SETCC) {
+      SDOperand Simp = SimplifySelectCC(VT, 
+                                  cast<CondCodeSDNode>(N1.getOperand(2))->get(),
+                                  N1.getOperand(0), N1.getOperand(1), N2, N3);
+      if (Simp.Val) return Simp;
+    }
     break;
   case ISD::BRCOND:
     if (N2C)
@@ -1461,74 +1541,9 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
            "LHS and RHS of condition must have same type!");
     assert(N3.getValueType() == N4.getValueType() &&
            "True and False arms of SelectCC must have same type!");
-    
-    ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.Val);
-    ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N3.Val);
-    ConstantSDNode *N4C = dyn_cast<ConstantSDNode>(N4.Val);
-    ISD::CondCode CC = cast<CondCodeSDNode>(N5)->get();
-
-    // Check to see if we can simplify the select into an fabs node
-    if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(N2)) {
-      // Allow either -0.0 or 0.0
-      if (CFP->getValue() == 0.0) {
-        // select (setg[te] X, +/-0.0), X, fneg(X) -> fabs
-        if ((CC == ISD::SETGE || CC == ISD::SETGT) &&
-            N1 == N3 && N4.getOpcode() == ISD::FNEG &&
-            N1 == N4.getOperand(0))
-          return getNode(ISD::FABS, VT, N1);
-        
-        // select (setl[te] X, +/-0.0), fneg(X), X -> fabs
-        if ((CC == ISD::SETLT || CC == ISD::SETLE) &&
-            N1 == N4 && N3.getOpcode() == ISD::FNEG &&
-            N3.getOperand(0) == N4)
-          return getNode(ISD::FABS, VT, N4);
-      }
-    }
-    
-    // Check to see if we can perform the "gzip trick", transforming
-    // select_cc setlt X, 0, A, 0 -> and (sra X, size(X)-1), A
-    if (N2C && N2C->isNullValue() && N4C && N4C->isNullValue() &&
-        MVT::isInteger(N1.getValueType()) && 
-        MVT::isInteger(N3.getValueType()) && CC == ISD::SETLT) {
-      MVT::ValueType XType = N1.getValueType();
-      MVT::ValueType AType = N3.getValueType();
-      if (XType >= AType) {
-        // and (sra X, size(X)-1, A) -> "and (srl X, C2), A" iff A is a
-        // single-bit constant.  FIXME: remove once the dag combiner
-        // exists.
-        if (N3C && ((N3C->getValue() & (N3C->getValue()-1)) == 0)) {
-          unsigned ShCtV = Log2_64(N3C->getValue());
-          ShCtV = MVT::getSizeInBits(XType)-ShCtV-1;
-          SDOperand ShCt = getConstant(ShCtV, TLI.getShiftAmountTy());
-          SDOperand Shift = getNode(ISD::SRL, XType, N1, ShCt);
-          if (XType > AType)
-            Shift = getNode(ISD::TRUNCATE, AType, Shift);
-          return getNode(ISD::AND, AType, Shift, N3);
-        }
-        SDOperand Shift = getNode(ISD::SRA, XType, N1,
-                                  getConstant(MVT::getSizeInBits(XType)-1,
-                                              TLI.getShiftAmountTy()));
-        if (XType > AType)
-          Shift = getNode(ISD::TRUNCATE, AType, Shift);
-        return getNode(ISD::AND, AType, Shift, N3);
-      }
-    }
-    
-    // Check to see if this is an integer abs. select_cc setl[te] X, 0, -X, X ->
-    // Y = sra (X, size(X)-1); xor (add (X, Y), Y)
-    if (N2C && N2C->isNullValue() && (CC == ISD::SETLT || CC == ISD::SETLE) &&
-        N1 == N4 && N3.getOpcode() == ISD::SUB && N1 == N3.getOperand(1)) {
-      if (ConstantSDNode *SubC = dyn_cast<ConstantSDNode>(N3.getOperand(0))) {
-        MVT::ValueType XType = N1.getValueType();
-        if (SubC->isNullValue() && MVT::isInteger(XType)) {
-          SDOperand Shift = getNode(ISD::SRA, XType, N1,
-                                    getConstant(MVT::getSizeInBits(XType)-1,
-                                                TLI.getShiftAmountTy()));
-          return getNode(ISD::XOR, XType, getNode(ISD::ADD, XType, N1, Shift), 
-                         Shift);
-        }
-      }
-    }
+    SDOperand Simp = SimplifySelectCC(VT, cast<CondCodeSDNode>(N5)->get(), N1, 
+                                      N2, N3, N4);
+    if (Simp.Val) return Simp;
   }
         
   std::vector<SDOperand> Ops;