This patch does two things. First, it canonicalizes 'X >= C' -> 'X > C-1'
authorChris Lattner <sabre@nondot.org>
Thu, 7 Apr 2005 18:14:58 +0000 (18:14 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 7 Apr 2005 18:14:58 +0000 (18:14 +0000)
(likewise for <= >=u >=u).

Second, it implements a special case hack to turn 'X gtu SINTMAX' -> 'X lt 0'

On powerpc, for example, this changes this:

        lis r2, 32767
        ori r2, r2, 65535
        cmplw cr0, r3, r2
        bgt .LBB_test_2

into:

        cmpwi cr0, r3, 0
        blt .LBB_test_2

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

lib/CodeGen/SelectionDAG/SelectionDAG.cpp

index ea87a64ff66ec5d7eb82ee7d4a32e5b67727501d..760f42471dc41c3ce24be62e9cd4ea21892846fc 100644 (file)
@@ -375,9 +375,10 @@ SDOperand SelectionDAG::getSetCC(ISD::CondCode Cond, MVT::ValueType VT,
   case ISD::SETTRUE2:  return getConstant(1, VT);
   }
 
-  if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val))
-    if (ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.Val)) {
-      uint64_t C1 = N1C->getValue(), C2 = N2C->getValue();
+  if (ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.Val)) {
+    uint64_t C2 = N2C->getValue();
+    if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val)) {
+      uint64_t C1 = N1C->getValue();
       
       // Sign extend the operands if required
       if (ISD::isSignedIntSetCC(Cond)) {
@@ -398,11 +399,52 @@ SDOperand SelectionDAG::getSetCC(ISD::CondCode Cond, MVT::ValueType VT,
       case ISD::SETLE:  return getConstant((int64_t)C1 <= (int64_t)C2, VT);
       case ISD::SETGE:  return getConstant((int64_t)C1 >= (int64_t)C2, VT);
       }
-    } else {
-      // Ensure that the constant occurs on the RHS.
-      Cond = ISD::getSetCCSwappedOperands(Cond);
-      std::swap(N1, N2);
+    } else if (1) {
+      uint64_t MinVal, MaxVal;
+      unsigned OperandBitSize = MVT::getSizeInBits(N2C->getValueType(0));
+      if (ISD::isSignedIntSetCC(Cond)) {
+        MinVal = 1ULL << (OperandBitSize-1);
+        if (OperandBitSize != 1)   // Avoid X >> 64, which is undefined.
+          MaxVal = ~0ULL >> (65-OperandBitSize);
+        else
+          MaxVal = 0;
+      } else {
+        MinVal = 0;
+        MaxVal = ~0ULL >> (64-OperandBitSize);
+      }
+
+      // Canonicalize GE/LE comparisons to use GT/LT comparisons.
+      if (Cond == ISD::SETGE || Cond == ISD::SETUGE) {
+        if (C2 == MinVal) return getConstant(1, VT);   // X >= MIN --> true
+        --C2;                                          // X >= C1 --> X > (C1-1)
+        Cond = (Cond == ISD::SETGE) ? ISD::SETGT : ISD::SETUGT;
+        N2 = getConstant(C2, N2.getValueType());
+        N2C = cast<ConstantSDNode>(N2.Val);
+      }
+
+      if (Cond == ISD::SETLE || Cond == ISD::SETULE) {
+        if (C2 == MaxVal) return getConstant(1, VT);   // X <= MAX --> true
+        ++C2;                                          // X <= C1 --> X < (C1+1)
+        Cond = (Cond == ISD::SETLE) ? ISD::SETLT : ISD::SETULT;
+        N2 = getConstant(C2, N2.getValueType());
+        N2C = cast<ConstantSDNode>(N2.Val);
+      }
+
+      // If we have "setcc X, C1", check to see if we can shrink the immediate
+      // by changing cc.
+
+      // SETUGT X, SINTMAX  -> SETLT X, 0
+      if (Cond == ISD::SETUGT && OperandBitSize != 1 &&
+          C2 == (~0ULL >> (65-OperandBitSize)))
+        return getSetCC(ISD::SETLT, VT, N1, getConstant(0, N2.getValueType()));
+
+      // FIXME: Implement the rest of these.
+
     }
+  } else if (isa<ConstantSDNode>(N1.Val)) {
+      // Ensure that the constant occurs on the RHS.
+    return getSetCC(ISD::getSetCCSwappedOperands(Cond), VT, N2, N1);
+  }
 
   if (ConstantFPSDNode *N1C = dyn_cast<ConstantFPSDNode>(N1.Val))
     if (ConstantFPSDNode *N2C = dyn_cast<ConstantFPSDNode>(N2.Val)) {