OSDN Git Service

* fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jun 2002 00:06:18 +0000 (00:06 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jun 2002 00:06:18 +0000 (00:06 +0000)
        earlier.  Re-factor comparisons vs extrema.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@54626 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c

index 320605f..197ac51 100644 (file)
@@ -1,5 +1,10 @@
 2002-06-14  Richard Henderson  <rth@redhat.com>
 
+       * fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation
+       earlier.  Re-factor comparisons vs extrema.
+
+2002-06-14  Richard Henderson  <rth@redhat.com>
+
        * config/alpha/alpha.md (builtin_zapnot): Fix op2 mode.
 
 2002-06-14  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
index 1c29ad5..31bcddb 100644 (file)
@@ -6013,9 +6013,34 @@ fold (expr)
          }
       }
 
+      /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
+        This transformation affects the cases which are handled in later
+        optimizations involving comparisons with non-negative constants.  */
+      if (TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (arg0) != INTEGER_CST
+         && tree_int_cst_sgn (arg1) > 0)
+       {
+         switch (code)
+           {
+           case GE_EXPR:
+             code = GT_EXPR;
+             arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+             t = build (code, type, TREE_OPERAND (t, 0), arg1);
+             break;
+
+           case LT_EXPR:
+             code = LE_EXPR;
+             arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+             t = build (code, type, TREE_OPERAND (t, 0), arg1);
+             break;
+
+           default:
+             break;
+           }
+       }
+
       /* Comparisons with the highest or lowest possible integer of
-        the specified size will have known values and an unsigned
-        <= 0x7fffffff can be simplified.  */
+        the specified size will have known values.  */
       {
        int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
 
@@ -6025,43 +6050,76 @@ fold (expr)
            && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
                || POINTER_TYPE_P (TREE_TYPE (arg1))))
          {
+           unsigned HOST_WIDE_INT signed_max;
+           unsigned HOST_WIDE_INT max, min;
+
+           signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
+
+           if (TREE_UNSIGNED (TREE_TYPE (arg1)))
+             {
+               max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+               min = 0;
+             }
+           else
+             {
+               max = signed_max;
+               min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+             }
+
            if (TREE_INT_CST_HIGH (arg1) == 0
-               && (TREE_INT_CST_LOW (arg1)
-                   == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
-               && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
-             switch (TREE_CODE (t))
+               && TREE_INT_CST_LOW (arg1) == max)
+             switch (code)
                {
                case GT_EXPR:
                  return omit_one_operand (type,
                                           convert (type, integer_zero_node),
                                           arg0);
                case GE_EXPR:
+                 code = EQ_EXPR;
                  TREE_SET_CODE (t, EQ_EXPR);
                  break;
-
                case LE_EXPR:
                  return omit_one_operand (type,
                                           convert (type, integer_one_node),
                                           arg0);
                case LT_EXPR:
+                 code = NE_EXPR;
                  TREE_SET_CODE (t, NE_EXPR);
                  break;
 
+               /* The GE_EXPR and LT_EXPR cases above are not normally
+                  reached because of  previous transformations.  */
+
                default:
                  break;
                }
-
-           else if (TREE_INT_CST_HIGH (arg1) == -1
-                    && (TREE_INT_CST_LOW (arg1)
-                        == ((unsigned HOST_WIDE_INT) -1 << (width - 1)))
-                    && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
-             switch (TREE_CODE (t))
+           else if (TREE_INT_CST_HIGH (arg1) == 0
+                    && TREE_INT_CST_LOW (arg1) == max - 1)
+             switch (code)
+               {
+               case GT_EXPR:
+                 code = EQ_EXPR;
+                 arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+                 t = build (code, type, TREE_OPERAND (t, 0), arg1);
+                 break;
+               case LE_EXPR:
+                 code = NE_EXPR;
+                 arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+                 t = build (code, type, TREE_OPERAND (t, 0), arg1);
+                 break;
+               default:
+                 break;
+               }
+           else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
+                    && TREE_INT_CST_LOW (arg1) == min)
+             switch (code)
                {
                case LT_EXPR:
                  return omit_one_operand (type,
                                           convert (type, integer_zero_node),
                                           arg0);
                case LE_EXPR:
+                 code = EQ_EXPR;
                  TREE_SET_CODE (t, EQ_EXPR);
                  break;
 
@@ -6070,112 +6128,53 @@ fold (expr)
                                           convert (type, integer_one_node),
                                           arg0);
                case GT_EXPR:
+                 code = NE_EXPR;
                  TREE_SET_CODE (t, NE_EXPR);
                  break;
 
                default:
                  break;
                }
+           else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
+                    && TREE_INT_CST_LOW (arg1) == min + 1)
+             switch (code)
+               {
+               case GE_EXPR:
+                 code = NE_EXPR;
+                 arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+                 t = build (code, type, TREE_OPERAND (t, 0), arg1);
+                 break;
+               case LT_EXPR:
+                 code = EQ_EXPR;
+                 arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+                 t = build (code, type, TREE_OPERAND (t, 0), arg1);
+                 break;
+               default:
+                 break;
+               }
 
            else if (TREE_INT_CST_HIGH (arg1) == 0
-                    && (TREE_INT_CST_LOW (arg1)
-                        == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
+                    && TREE_INT_CST_LOW (arg1) == signed_max
                     && TREE_UNSIGNED (TREE_TYPE (arg1))
                     /* signed_type does not work on pointer types.  */
                     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
              {
-               if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR)
+               /* The following case also applies to X < signed_max+1
+                  and X >= signed_max+1 because previous transformations.  */
+               if (code == LE_EXPR || code == GT_EXPR)
                  {
                    tree st0, st1;
                    st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0));
                    st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1));
                    return fold
-                     (build (TREE_CODE (t) == LE_EXPR ? GE_EXPR: LT_EXPR,
+                     (build (code == LE_EXPR ? GE_EXPR: LT_EXPR,
                              type, convert (st0, arg0),
                              convert (st1, integer_zero_node)));
                  }
              }
-           else if (TREE_INT_CST_HIGH (arg1) == 0
-                    && (TREE_INT_CST_LOW (arg1)
-                        == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1)
-                    && TREE_UNSIGNED (TREE_TYPE (arg1)))
-             switch (TREE_CODE (t))
-               {
-               case GT_EXPR:
-                 return omit_one_operand (type,
-                                          convert (type, integer_zero_node),
-                                          arg0);
-               case GE_EXPR:
-                 TREE_SET_CODE (t, EQ_EXPR);
-                 break;
-
-               case LE_EXPR:
-                 return omit_one_operand (type,
-                                          convert (type, integer_one_node),
-                                          arg0);
-               case LT_EXPR:
-                 TREE_SET_CODE (t, NE_EXPR);
-                 break;
-
-               default:
-                 break;
-               }
          }
       }
 
-      /* Change X >= C to X > C-1 and X < C to X <= C-1 if C is positive.  */
-      if (TREE_CODE (arg1) == INTEGER_CST
-         && TREE_CODE (arg0) != INTEGER_CST
-         && tree_int_cst_sgn (arg1) > 0)
-       {
-         switch (TREE_CODE (t))
-           {
-           case GE_EXPR:
-             code = GT_EXPR;
-             arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-             t = build (code, type, TREE_OPERAND (t, 0), arg1);
-             break;
-
-           case LT_EXPR:
-             code = LE_EXPR;
-             arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-             t = build (code, type, TREE_OPERAND (t, 0), arg1);
-             break;
-
-           default:
-             break;
-           }
-       }
-
-      /* An unsigned comparison against 0 can be simplified.  */
-      if (integer_zerop (arg1)
-         && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
-             || POINTER_TYPE_P (TREE_TYPE (arg1)))
-         && TREE_UNSIGNED (TREE_TYPE (arg1)))
-       {
-         switch (TREE_CODE (t))
-           {
-           case GT_EXPR:
-             code = NE_EXPR;
-             TREE_SET_CODE (t, NE_EXPR);
-             break;
-           case LE_EXPR:
-             code = EQ_EXPR;
-             TREE_SET_CODE (t, EQ_EXPR);
-             break;
-           case GE_EXPR:
-             return omit_one_operand (type,
-                                      convert (type, integer_one_node),
-                                      arg0);
-           case LT_EXPR:
-             return omit_one_operand (type,
-                                      convert (type, integer_zero_node),
-                                      arg0);
-           default:
-             break;
-           }
-       }
-
       /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
         a MINUS_EXPR of a constant, we can convert it into a comparison with
         a revised constant as long as no overflow occurs.  */