aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-06-12 20:33:02 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-06-12 20:33:02 +0000
commit96f26e41615a7767578deead92417485696c7f4f (patch)
treed43978ab935534e794d98400e5934ee15ca8180e /gcc
parent6356f8928853bc14e841e5b4e990ce2508c38f26 (diff)
downloadgcc-96f26e41615a7767578deead92417485696c7f4f.zip
gcc-96f26e41615a7767578deead92417485696c7f4f.tar.gz
gcc-96f26e41615a7767578deead92417485696c7f4f.tar.bz2
re PR middle-end/168 (Spurious signed/unsigned comparison warning)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c85
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/20030612-1.c20
4 files changed, 111 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4777c15..d50d290 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index b3271a2..e67f0f6 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2dcfe14..5a31745 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..f9f212c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20030612-1.c
@@ -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 ();
+}
+