diff options
author | Roger Sayle <roger@eyesopen.com> | 2003-06-12 20:33:02 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-06-12 20:33:02 +0000 |
commit | 96f26e41615a7767578deead92417485696c7f4f (patch) | |
tree | d43978ab935534e794d98400e5934ee15ca8180e /gcc | |
parent | 6356f8928853bc14e841e5b4e990ce2508c38f26 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fold-const.c | 85 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/20030612-1.c | 20 |
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 (); +} + |