re PR middle-end/168 (Spurious signed/unsigned comparison warning)
authorRoger Sayle <roger@eyesopen.com>
Thu, 12 Jun 2003 20:33:02 +0000 (20:33 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Thu, 12 Jun 2003 20:33:02 +0000 (20:33 +0000)
PR middle-end/168
* fold-const.c (tree_expr_nonnegative_p):  Handle addition
and multiplication of zero extensions, floating point division,
and integer<->fp, fp<->fp and zero extension conversions.
The built-in ceil and floor functions preserve signedness.

* gcc.dg/20030612-1.c: New test case.

From-SVN: r67850

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20030612-1.c [new file with mode: 0644]

index 4777c1568ea5a963a278ac18dd9c123c298a0314..d50d290912ca1fc01b0686c6b3f9977fa310687a 100644 (file)
@@ -1,3 +1,11 @@
+2003-06-12  Roger Sayle  <roger@eyesopen.com>
+
+       PR middle-end/168
+       * fold-const.c (tree_expr_nonnegative_p):  Handle addition
+       and multiplication of zero extensions, floating point division,
+       and integer<->fp, fp<->fp and zero extension conversions.
+       The built-in ceil and floor functions preserve signedness.
+
 2003-06-12  Kazu Hirata  <kazu@cs.umass.edu>
 
        * ChangeLog: Follow spelling conventions.
index b3271a2c6dadc33e4547738961e1ca913d2dcfdc..e67f0f657699b25ef0afe153251a058e8ff9c7e6 100644 (file)
@@ -8022,9 +8022,27 @@ tree_expr_nonnegative_p (t)
       return ! REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
 
     case PLUS_EXPR:
-      return FLOAT_TYPE_P (TREE_TYPE (t))
-            && tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-            && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+      if (FLOAT_TYPE_P (TREE_TYPE (t)))
+       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+              && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
+      /* zero_extend(x) + zero_extend(y) is non-negative is x and y are
+        both unsigned and at atleast 2 bits shorter than the result.  */
+      if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+         && TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR
+         && TREE_CODE (TREE_OPERAND (t, 1)) == NOP_EXPR)
+       {
+         tree inner1 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+         tree inner2 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0));
+         if (TREE_CODE (inner1) == INTEGER_TYPE && TREE_UNSIGNED (inner1)
+             && TREE_CODE (inner2) == INTEGER_TYPE && TREE_UNSIGNED (inner2))
+           {
+             unsigned int prec = MAX (TYPE_PRECISION (inner1),
+                                      TYPE_PRECISION (inner2)) + 1;
+             return prec < TYPE_PRECISION (TREE_TYPE (t));
+           }
+       }
+      break;
 
     case MULT_EXPR:
       if (FLOAT_TYPE_P (TREE_TYPE (t)))
@@ -8035,6 +8053,20 @@ tree_expr_nonnegative_p (t)
          return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
                 && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
        }
+
+      /* zero_extend(x) * zero_extend(y) is non-negative is x and y are
+        both unsigned and their total bits is shorter than the result.  */
+      if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+         && TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR
+         && TREE_CODE (TREE_OPERAND (t, 1)) == NOP_EXPR)
+       {
+         tree inner1 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+         tree inner2 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0));
+         if (TREE_CODE (inner1) == INTEGER_TYPE && TREE_UNSIGNED (inner1)
+             && TREE_CODE (inner2) == INTEGER_TYPE && TREE_UNSIGNED (inner2))
+           return TYPE_PRECISION (inner1) + TYPE_PRECISION (inner2)
+                  < TYPE_PRECISION (TREE_TYPE (t));
+       }
       return 0;
 
     case TRUNC_DIV_EXPR:
@@ -8042,12 +8074,45 @@ tree_expr_nonnegative_p (t)
     case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-       && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+            && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
     case TRUNC_MOD_EXPR:
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+
+    case RDIV_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+            && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
+    case NOP_EXPR:
+      {
+       tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0));
+       tree outer_type = TREE_TYPE (t);
+
+       if (TREE_CODE (outer_type) == REAL_TYPE)
+         {
+           if (TREE_CODE (inner_type) == REAL_TYPE)
+             return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+           if (TREE_CODE (inner_type) == INTEGER_TYPE)
+             {
+               if (TREE_UNSIGNED (inner_type))
+                 return 1;
+               return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+             }
+         }
+       else if (TREE_CODE (outer_type) == INTEGER_TYPE)
+         {
+           if (TREE_CODE (inner_type) == REAL_TYPE)
+             return tree_expr_nonnegative_p (TREE_OPERAND (t,0));
+           if (TREE_CODE (inner_type) == INTEGER_TYPE)
+             return TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type)
+                     && TREE_UNSIGNED (inner_type);
+         }
+      }
+      break;
+
     case COND_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
        && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
@@ -8097,6 +8162,12 @@ tree_expr_nonnegative_p (t)
              case BUILT_IN_ATAN:
              case BUILT_IN_ATANF:
              case BUILT_IN_ATANL:
+             case BUILT_IN_CEIL:
+             case BUILT_IN_CEILF:
+             case BUILT_IN_CEILL:
+             case BUILT_IN_FLOOR:
+             case BUILT_IN_FLOORF:
+             case BUILT_IN_FLOORL:
                return tree_expr_nonnegative_p (TREE_VALUE (arglist));
 
              case BUILT_IN_POW:
@@ -8115,10 +8186,10 @@ tree_expr_nonnegative_p (t)
       if (truth_value_p (TREE_CODE (t)))
        /* Truth values evaluate to 0 or 1, which is nonnegative.  */
        return 1;
-      else
-       /* We don't know sign of `t', so be conservative and return false.  */
-       return 0;
     }
+
+  /* We don't know sign of `t', so be conservative and return false.  */
+  return 0;
 }
 
 /* Return true if `r' is known to be non-negative.
index 2dcfe1433d6dee5d2a5ae103c1b7a59e3eabe281..5a31745ce5eb48722af495e9c6c8a1d8813faf6c 100644 (file)
@@ -1,3 +1,8 @@
+2003-06-12  Roger Sayle  <roger@eyesopen.com>
+
+       PR middle-end/168
+       * gcc.dg/20030612-1.c: New test case.
+
 2003-06-12  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/10635
diff --git a/gcc/testsuite/gcc.dg/20030612-1.c b/gcc/testsuite/gcc.dg/20030612-1.c
new file mode 100644 (file)
index 0000000..f9f212c
--- /dev/null
@@ -0,0 +1,20 @@
+/* Derived from PR middle-end/168.  */
+
+/* { dg-do compile } */
+/* { dg-options "-W" } */
+
+extern void foo ();
+
+unsigned char uc;
+unsigned short int usi;
+unsigned int ui;
+
+
+void bar()
+{
+  if (uc + usi >= ui)  /* { dg-bogus "between signed and unsigned" } */
+    foo ();
+  if (uc * usi >= ui)  /* { dg-bogus "between signed and unsigned" } */
+    foo ();
+}
+