[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Nate Begeman natebegeman at mac.com
Mon Oct 10 14:27:00 PDT 2005



Changes in directory llvm/lib/CodeGen/SelectionDAG:

DAGCombiner.cpp updated: 1.26 -> 1.27
---
Log message:

Teach the DAGCombiner several new tricks, teaching it how to turn
sext_inreg into zext_inreg based on the signbit (fires a lot), srem into
urem, etc.


---
Diffs of the changes:  (+46 -32)

 DAGCombiner.cpp |   78 +++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 46 insertions(+), 32 deletions(-)


Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.26 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.27
--- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.26	Mon Oct 10 11:52:03 2005
+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp	Mon Oct 10 16:26:48 2005
@@ -20,7 +20,6 @@
 // ZERO_EXTEND/SIGN_EXTEND by converting them to an ANY_EXTEND node which
 // we don't have yet.
 //
-// FIXME: select C, 16, 0 -> shr C, 4 
 // FIXME: select C, pow2, pow2 -> something smart
 // FIXME: trunc(select X, Y, Z) -> select X, trunc(Y), trunc(Z)
 // FIXME: (select C, load A, load B) -> load (select C, A, B)
@@ -30,20 +29,13 @@
 // FIXME: TRUNC (LOAD)   -> EXT_LOAD/LOAD(smaller)
 // FIXME: mul (x, const) -> shifts + adds
 // FIXME: undef values
-// FIXME: zero extend when top bits are 0 -> drop it ?
 // FIXME: make truncate see through SIGN_EXTEND and AND
-// FIXME: sext_in_reg(setcc) on targets that return zero or one, and where 
-//        EVT != MVT::i1 can drop the sext.
 // FIXME: (sra (sra x, c1), c2) -> (sra x, c1+c2)
 // FIXME: verify that getNode can't return extends with an operand whose type
 //        is >= to that of the extend.
 // FIXME: divide by zero is currently left unfolded.  do we want to turn this
 //        into an undef?
 // FIXME: select ne (select cc, 1, 0), 0, true, false -> select cc, true, false
-// FIXME: sext_inreg(SRL) -> SRA:
-// int %simple(uint %X) { %tmp.4 = shr uint %X, ubyte 16
-//    %tmp.5 = cast uint %tmp.4 to short     %tmp.6 = cast short %tmp.5 to int
-//    ret int %tmp.6 }
 // 
 //===----------------------------------------------------------------------===//
 
@@ -154,8 +146,8 @@
   };
 }
 
-/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero.  We use
-/// this predicate to simplify operations downstream.  V and Mask are known to
+/// MaskedValueIsZero - Return true if 'Op & Mask' is known to be zero.  We use
+/// this predicate to simplify operations downstream.  Op and Mask are known to
 /// be the same type.
 static bool MaskedValueIsZero(const SDOperand &Op, uint64_t Mask,
                               const TargetLowering &TLI) {
@@ -167,7 +159,6 @@
   case ISD::Constant:
     return (cast<ConstantSDNode>(Op)->getValue() & Mask) == 0;
   case ISD::SETCC:
-    // FIXME: teach this about non ZeroOrOne values, such as 0 or -1
     return ((Mask & 1) == 0) &&
     TLI.getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult;
   case ISD::ZEXTLOAD:
@@ -184,7 +175,6 @@
     if (MaskedValueIsZero(Op.getOperand(1), Mask, TLI) ||
         MaskedValueIsZero(Op.getOperand(0), Mask, TLI))
       return true;
-    
     // (X & C1) & C2 == 0   iff   C1 & C2 == 0.
     if (ConstantSDNode *AndRHS = dyn_cast<ConstantSDNode>(Op.getOperand(1)))
       return MaskedValueIsZero(Op.getOperand(0),AndRHS->getValue() & Mask, TLI);
@@ -545,15 +535,12 @@
   if (N0C && N1C && !N1C->isNullValue())
     return DAG.getConstant(N0C->getSignExtended() / N1C->getSignExtended(),
                            N->getValueType(0));
-
   // If we know the sign bits of both operands are zero, strength reduce to a
   // udiv instead.  Handles (X&15) /s 4 -> X&15 >> 2
   uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1);
   if (MaskedValueIsZero(N1, SignBit, TLI) &&
       MaskedValueIsZero(N0, SignBit, TLI))
     return DAG.getNode(ISD::UDIV, N1.getValueType(), N0, N1);
-  
-  
   return SDOperand();
 }
 
@@ -578,6 +565,7 @@
 SDOperand DAGCombiner::visitSREM(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
   SDOperand N1 = N->getOperand(1);
+  MVT::ValueType VT = N->getValueType(0);
   ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
   ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
   
@@ -585,6 +573,12 @@
   if (N0C && N1C && !N1C->isNullValue())
     return DAG.getConstant(N0C->getSignExtended() % N1C->getSignExtended(),
                            N->getValueType(0));
+  // If we know the sign bits of both operands are zero, strength reduce to a
+  // urem instead.  Handles (X & 0x0FFFFFFF) %s 16 -> X&15
+  uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1);
+  if (MaskedValueIsZero(N1, SignBit, TLI) &&
+      MaskedValueIsZero(N0, SignBit, TLI))
+    return DAG.getNode(ISD::UREM, N1.getValueType(), N0, N1);
   return SDOperand();
 }
 
@@ -598,7 +592,10 @@
   if (N0C && N1C && !N1C->isNullValue())
     return DAG.getConstant(N0C->getValue() % N1C->getValue(),
                            N->getValueType(0));
-  // FIXME: c2 power of 2 -> mask?
+  // fold (urem x, pow2) -> (and x, pow2-1)
+  if (N1C && !N1C->isNullValue() && isPowerOf2_64(N1C->getValue()))
+    return DAG.getNode(ISD::AND, N0.getValueType(), N0, 
+                       DAG.getConstant(N1C->getValue()-1, N1.getValueType()));
   return SDOperand();
 }
 
@@ -1173,6 +1170,7 @@
   ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
   MVT::ValueType VT = N->getValueType(0);
   MVT::ValueType EVT = cast<VTSDNode>(N1)->getVT();
+  unsigned EVTBits = MVT::getSizeInBits(EVT);
   
   // fold (sext_in_reg c1) -> c1
   if (N0C) {
@@ -1200,23 +1198,20 @@
     return N0;
   }
   // fold (sext_in_reg (setcc x)) -> setcc x iff (setcc x) == 0 or -1
-  // FIXME: teach isSetCCEquivalent about 0, -1 and then use it here
   if (N0.getOpcode() == ISD::SETCC &&
       TLI.getSetCCResultContents() == 
         TargetLowering::ZeroOrNegativeOneSetCCResult)
     return N0;
-  // FIXME: this code is currently just ported over from SelectionDAG.cpp
-  // we probably actually want to handle this in two pieces.  Rather than
-  // checking all the top bits for zero, just check the sign bit here and turn
-  // it into a zero extend inreg (AND with constant).
-  // then, let the code for AND figure out if the mask is superfluous rather
-  // than doing so here.
-  if (N0.getOpcode() == ISD::AND && 
-      N0.getOperand(1).getOpcode() == ISD::Constant) {
-    uint64_t Mask = cast<ConstantSDNode>(N0.getOperand(1))->getValue();
-    unsigned NumBits = MVT::getSizeInBits(EVT);
-    if ((Mask & (~0ULL << (NumBits-1))) == 0)
-      return N0;
+  // fold (sext_in_reg x) -> (zext_in_reg x) if the sign bit is zero
+  if (MaskedValueIsZero(N0, 1ULL << (EVTBits-1), TLI))
+    return DAG.getNode(ISD::AND, N0.getValueType(), N0,
+                       DAG.getConstant(~0ULL >> (64-EVTBits), VT));
+  // fold (sext_in_reg (srl x)) -> sra x
+  if (N0.getOpcode() == ISD::SRL && 
+      N0.getOperand(1).getOpcode() == ISD::Constant &&
+      cast<ConstantSDNode>(N0.getOperand(1))->getValue() == EVTBits) {
+    return DAG.getNode(ISD::SRA, N0.getValueType(), N0.getOperand(0), 
+                       N0.getOperand(1));
   }
   return SDOperand();
 }
@@ -1590,8 +1585,7 @@
     MVT::ValueType AType = N2.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.
+      // single-bit constant.
       if (N2C && ((N2C->getValue() & (N2C->getValue()-1)) == 0)) {
         unsigned ShCtV = Log2_64(N2C->getValue());
         ShCtV = MVT::getSizeInBits(XType)-ShCtV-1;
@@ -1615,7 +1609,27 @@
       return DAG.getNode(ISD::AND, AType, Shift, N2);
     }
   }
-
+  
+  // fold select C, 16, 0 -> shl C, 4
+  if (N2C && N3C && N3C->isNullValue() && isPowerOf2_64(N2C->getValue()) &&
+      TLI.getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult) {
+    // Get a SetCC of the condition
+    // FIXME: Should probably make sure that setcc is legal if we ever have a
+    // target where it isn't.
+    SDOperand Temp, SCC = DAG.getSetCC(TLI.getSetCCResultTy(), N0, N1, CC);
+    WorkList.push_back(SCC.Val);
+    // cast from setcc result type to select result type
+    if (AfterLegalize)
+      Temp = DAG.getZeroExtendInReg(SCC, N2.getValueType());
+    else
+      Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getValueType(), SCC);
+    WorkList.push_back(Temp.Val);
+    // shl setcc result by log2 n2c
+    return DAG.getNode(ISD::SHL, N2.getValueType(), Temp,
+                       DAG.getConstant(Log2_64(N2C->getValue()),
+                                       TLI.getShiftAmountTy()));
+  }
+    
   // Check to see if this is the equivalent of setcc
   // FIXME: Turn all of these into setcc if setcc if setcc is legal
   // otherwise, go ahead with the folds.






More information about the llvm-commits mailing list