From 8f498c1bdcb9d3b99905f654faa0a343c3e9ef99 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 21 Jan 2013 18:55:34 +0100 Subject: 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 --- gcc/fold-const.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'gcc/fold-const.c') 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, -- cgit v1.1