From: rguenth Date: Wed, 4 Jan 2012 13:25:28 +0000 (+0000) Subject: 2012-01-04 Richard Guenther X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=a6c23958b0f999e3d48b0679e263be234368dc99;hp=f48068845f391e30be9c0962ab50f70d8c7a4f4d 2012-01-04 Richard Guenther PR middle-end/51750 * tree.c (size_low_cst): New function. * tree.h (size_low_cst): Declare. * fold-const.c (fold_comparison): Use it to extract the low part of the POINTER_PLUS_EXPR offset. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182872 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e34cfa07d30..33caab17d6a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2012-01-04 Richard Guenther + + PR middle-end/51750 + * tree.c (size_low_cst): New function. + * tree.h (size_low_cst): Declare. + * fold-const.c (fold_comparison): Use it to extract the low + part of the POINTER_PLUS_EXPR offset. + 2012-01-04 Georg-Johann Lay Fix clearing ZERO_REG diff --git a/gcc/fold-const.c b/gcc/fold-const.c index b88b5d72621..40a0986dda8 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8886,13 +8886,16 @@ fold_comparison (location_t loc, enum tree_code code, tree type, indirect_base0 = true; } offset0 = TREE_OPERAND (arg0, 1); - if (host_integerp (offset0, 0) - && ((HOST_WIDE_INT) (TREE_INT_CST_LOW (offset0) * BITS_PER_UNIT) - / BITS_PER_UNIT - == (HOST_WIDE_INT) TREE_INT_CST_LOW (offset0))) + if (host_integerp (offset0, 0)) { - bitpos0 = TREE_INT_CST_LOW (offset0) * BITS_PER_UNIT; - offset0 = NULL_TREE; + HOST_WIDE_INT off = size_low_cst (offset0); + if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off) + * BITS_PER_UNIT) + / BITS_PER_UNIT == (HOST_WIDE_INT) off) + { + bitpos0 = off * BITS_PER_UNIT; + offset0 = NULL_TREE; + } } } @@ -8917,13 +8920,16 @@ fold_comparison (location_t loc, enum tree_code code, tree type, indirect_base1 = true; } offset1 = TREE_OPERAND (arg1, 1); - if (host_integerp (offset1, 0) - && ((HOST_WIDE_INT) (TREE_INT_CST_LOW (offset1) * BITS_PER_UNIT) - / BITS_PER_UNIT - == (HOST_WIDE_INT) TREE_INT_CST_LOW (offset1))) + if (host_integerp (offset1, 0)) { - bitpos1 = TREE_INT_CST_LOW (offset1) * BITS_PER_UNIT; - offset1 = NULL_TREE; + HOST_WIDE_INT off = size_low_cst (offset1); + if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off) + * BITS_PER_UNIT) + / BITS_PER_UNIT == (HOST_WIDE_INT) off) + { + bitpos1 = off * BITS_PER_UNIT; + offset1 = NULL_TREE; + } } } diff --git a/gcc/tree.c b/gcc/tree.c index d7bbae3c675..76488f7528a 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6509,6 +6509,17 @@ tree_low_cst (const_tree t, int pos) return TREE_INT_CST_LOW (t); } +/* Return the HOST_WIDE_INT least significant bits of T, a sizetype + kind INTEGER_CST. This makes sure to properly sign-extend the + constant. */ + +HOST_WIDE_INT +size_low_cst (const_tree t) +{ + double_int d = tree_to_double_int (t); + return double_int_sext (d, TYPE_PRECISION (TREE_TYPE (t))).low; +} + /* Return the most significant (sign) bit of T. */ int diff --git a/gcc/tree.h b/gcc/tree.h index 7a0046b8260..2ea03a092f6 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4428,6 +4428,7 @@ tree_low_cst (const_tree t, int pos) return TREE_INT_CST_LOW (t); } #endif +extern HOST_WIDE_INT size_low_cst (const_tree); extern int tree_int_cst_sgn (const_tree); extern int tree_int_cst_sign_bit (const_tree); extern unsigned int tree_int_cst_min_precision (tree, bool);