diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-01-21 18:55:34 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-01-21 18:55:34 +0100 |
commit | 8f498c1bdcb9d3b99905f654faa0a343c3e9ef99 (patch) | |
tree | a3bdef1e25a778da35e6160d0a5f3bf467d3ae9b | |
parent | 35d59da7f7e282a68589d8c857ee7f0503d588d2 (diff) | |
download | gcc-8f498c1bdcb9d3b99905f654faa0a343c3e9ef99.zip gcc-8f498c1bdcb9d3b99905f654faa0a343c3e9ef99.tar.gz gcc-8f498c1bdcb9d3b99905f654faa0a343c3e9ef99.tar.bz2 |
re PR tree-optimization/56051 (Wrong expression evaluation)
PR tree-optimization/56051
* fold-const.c (fold_binary_loc): Don't fold
X < (cast) (1 << Y) into (X >> Y) != 0 if cast is either
a narrowing conversion, or widening conversion from signed
to unsigned.
* gcc.c-torture/execute/pr56051.c: New test.
From-SVN: r195343
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fold-const.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr56051.c | 32 |
4 files changed, 57 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 196a26e..8ec4ee2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2013-01-21 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/56051 + * fold-const.c (fold_binary_loc): Don't fold + X < (cast) (1 << Y) into (X >> Y) != 0 if cast is either + a narrowing conversion, or widening conversion from signed + to unsigned. + 2012-01-21 Uros Bizjak <ubizjak@gmail.com> PR rtl-optimization/56023 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 4e1e63b..efad9a9 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -13556,10 +13556,22 @@ fold_binary_loc (location_t loc, TREE_OPERAND (arg1, 1)), build_zero_cst (TREE_TYPE (arg0))); + /* Similarly for X < (cast) (1 << Y). But cast can't be narrowing, + otherwise Y might be >= # of bits in X's type and thus e.g. + (unsigned char) (1 << Y) for Y 15 might be 0. + If the cast is widening, then 1 << Y should have unsigned type, + otherwise if Y is number of bits in the signed shift type minus 1, + we can't optimize this. E.g. (unsigned long long) (1 << Y) for Y + 31 might be 0xffffffff80000000. */ if ((code == LT_EXPR || code == GE_EXPR) && TYPE_UNSIGNED (TREE_TYPE (arg0)) && CONVERT_EXPR_P (arg1) && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR + && (TYPE_PRECISION (TREE_TYPE (arg1)) + >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)))) + && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0))) + || (TYPE_PRECISION (TREE_TYPE (arg1)) + == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0))))) && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0))) { tem = build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 385cd9c..a88bfa8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-01-21 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/56051 + * gcc.c-torture/execute/pr56051.c: New test. + 2012-01-21 Uros Bizjak <ubizjak@gmail.com> PR rtl-optimization/56023 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr56051.c b/gcc/testsuite/gcc.c-torture/execute/pr56051.c new file mode 100644 index 0000000..4ff6b9e --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr56051.c @@ -0,0 +1,32 @@ +/* PR tree-optimization/56051 */ + +extern void abort (void); + +int +main () +{ + unsigned char x1[1] = { 0 }; + unsigned int s1 = __CHAR_BIT__; + int a1 = x1[0] < (unsigned char) (1 << s1); + unsigned char y1 = (unsigned char) (1 << s1); + int b1 = x1[0] < y1; + if (a1 != b1) + abort (); +#if __SIZEOF_LONG_LONG__ > __SIZEOF_INT__ + unsigned long long x2[1] = { 2ULL << (sizeof (int) * __CHAR_BIT__) }; + unsigned int s2 = sizeof (int) * __CHAR_BIT__ - 1; + int a2 = x2[0] >= (unsigned long long) (1 << s2); + unsigned long long y2 = 1 << s2; + int b2 = x2[0] >= y2; + if (a2 != b2) + abort (); + unsigned long long x3[1] = { 2ULL << (sizeof (int) * __CHAR_BIT__) }; + unsigned int s3 = sizeof (int) * __CHAR_BIT__ - 1; + int a3 = x3[0] >= (unsigned long long) (1U << s3); + unsigned long long y3 = 1U << s3; + int b3 = x3[0] >= y3; + if (a3 != b3) + abort (); +#endif + return 0; +} |