[backport proposed gcc-4.8 fix for wrong-code PR56051 ] Date: Sun, 20 Jan 2013 20:46:58 +0100 From: Jakub Jelinek Subject: [PATCH] Fix up X < (cast) (1 << Y) folding (PR tree-optimization/56051) List-Archive: Hi! As the first hunk in the testcase shows, we can't perform this optimization if the conversion is narrowing. As the second hunk shows, if we allow 1 << 31 (we don't optimize int foo (int x) { return (1 << x) < 0; } so I think it would be surprising if we did optimize it in this case, plus I'm afraid it could break a lot of code if we started optimizing (1 << x) < 0 into 0), we can't optimize a widening conversion from signed to unsigned either. Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? For 4.9, I think we should see why e.g. X < (unsigned) (1 << Y) optimization isn't performed e.g. when X is just an unsigned int variable (rather than say ARRAY_REF as in the testcase), probably we need to handle it for arg1 being X and arg0 being (1 << Y) too. 2013-01-20 Jakub Jelinek 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. --- gcc-4.7.2/gcc/fold-const.c.~1~ 2012-06-01 19:03:19.000000000 +0200 +++ gcc-4.7.2/gcc/fold-const.c 2013-01-20 21:11:08.752411672 +0100 @@ -13439,6 +13439,11 @@ fold_binary_loc (location_t loc, && 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, --- gcc-4.7.2/gcc/testsuite/gcc.c-torture/execute/pr56051.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.7.2/gcc/testsuite/gcc.c-torture/execute/pr56051.c 2013-01-20 21:11:08.752411672 +0100 @@ -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; +}