aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-01-21 17:55:34 +0000
committerJakub Jelinek <jakub@redhat.com>2013-01-21 17:55:34 +0000
commit5159c25c6d3464ce5afd8506d634ca0490ad8c49 (patch)
treea3bdef1e25a778da35e6160d0a5f3bf467d3ae9b /gcc/fold-const.c
parent8ccc4538dcb469afdc92f5a97b1fe5741d85d81e (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@195343 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 4e1e63b8405..efad9a9d833 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,