diff mbox

Fix PR51750

Message ID alpine.LNX.2.00.1201041421040.4999@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Jan. 4, 2012, 1:22 p.m. UTC
Another manifestation about the issue we have wrt sizetypes
implicitly sign-extending but types-compatible types not.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

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.
diff mbox

Patch

Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 182867)
+++ gcc/tree.c	(working copy)
@@ -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: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 182867)
+++ gcc/tree.h	(working copy)
@@ -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);
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 182867)
+++ gcc/fold-const.c	(working copy)
@@ -8886,13 +8886,16 @@  fold_comparison (location_t loc, enum tr
 	      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 tr
 	      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;
+		}
 	    }
 	}