OSDN Git Service

2012-01-04 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Jan 2012 13:25:28 +0000 (13:25 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Jan 2012 13:25:28 +0000 (13:25 +0000)
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

gcc/ChangeLog
gcc/fold-const.c
gcc/tree.c
gcc/tree.h

index e34cfa0..33caab1 100644 (file)
@@ -1,3 +1,11 @@
+2012-01-04  Richard Guenther  <rguenther@suse.de>
+
+       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  <avr@gjlay.de>
 
        Fix clearing ZERO_REG
index b88b5d7..40a0986 100644 (file)
@@ -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;
+               }
            }
        }
 
index d7bbae3..76488f7 100644 (file)
@@ -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
index 7a0046b..2ea03a0 100644 (file)
@@ -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);