[PATCH] Fix overflows in get_ref_base_and_extent (PR tree-optimization/59779)

Richard Biener rguenther@suse.de
Thu Mar 13 18:58:00 GMT 2014


On March 13, 2014 6:50:53 PM CET, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>The outer-1.c testcase apparently fails on 32-bit HWI targets, the
>problem
>is that the int x[10000][10000]; array has bitsize that fits into uhwi,
>but
>not shwi, so we get negative maxsize that isn't -1.
>
>After discussions with Richard on IRC, I've implemented computation of
>bitsize and maxsize in double_int.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, with
>bootstrap/regtest time changes in the noise.  Ok for trunk?

OK.
Thanks,
Richard.

>John, could you please test this on some 32-bit HWI target with
>bootstrap/regtest?
>
>2014-03-13  Jakub Jelinek  <jakub@redhat.com>
>
>	PR tree-optimization/59779
>	* tree-dfa.c (get_ref_base_and_extent): Use double_int
>	type for bitsize and maxsize instead of HOST_WIDE_INT.
>
>--- gcc/tree-dfa.c.jj	2014-01-03 11:40:57.000000000 +0100
>+++ gcc/tree-dfa.c	2014-03-13 12:10:46.367886640 +0100
>@@ -389,11 +389,10 @@ get_ref_base_and_extent (tree exp, HOST_
> 			 HOST_WIDE_INT *psize,
> 			 HOST_WIDE_INT *pmax_size)
> {
>-  HOST_WIDE_INT bitsize = -1;
>-  HOST_WIDE_INT maxsize = -1;
>+  double_int bitsize = double_int_minus_one;
>+  double_int maxsize;
>   tree size_tree = NULL_TREE;
>   double_int bit_offset = double_int_zero;
>-  HOST_WIDE_INT hbit_offset;
>   bool seen_variable_array_ref = false;
> 
>/* First get the final access size from just the outermost expression. 
>*/
>@@ -407,15 +406,11 @@ get_ref_base_and_extent (tree exp, HOST_
>       if (mode == BLKmode)
> 	size_tree = TYPE_SIZE (TREE_TYPE (exp));
>       else
>-	bitsize = GET_MODE_BITSIZE (mode);
>-    }
>-  if (size_tree != NULL_TREE)
>-    {
>-      if (! tree_fits_uhwi_p (size_tree))
>-	bitsize = -1;
>-      else
>-	bitsize = tree_to_uhwi (size_tree);
>+	bitsize = double_int::from_uhwi (GET_MODE_BITSIZE (mode));
>     }
>+  if (size_tree != NULL_TREE
>+      && TREE_CODE (size_tree) == INTEGER_CST)
>+    bitsize = tree_to_double_int (size_tree);
> 
>   /* Initially, maxsize is the same as the accessed element size.
>      In the following it will only grow (or become -1).  */
>@@ -448,7 +443,7 @@ get_ref_base_and_extent (tree exp, HOST_
> 		   referenced the last field of a struct or a union member
> 		   then we have to adjust maxsize by the padding at the end
> 		   of our field.  */
>-		if (seen_variable_array_ref && maxsize != -1)
>+		if (seen_variable_array_ref && !maxsize.is_minus_one ())
> 		  {
> 		    tree stype = TREE_TYPE (TREE_OPERAND (exp, 0));
> 		    tree next = DECL_CHAIN (field);
>@@ -459,15 +454,22 @@ get_ref_base_and_extent (tree exp, HOST_
> 		      {
> 			tree fsize = DECL_SIZE_UNIT (field);
> 			tree ssize = TYPE_SIZE_UNIT (stype);
>-			if (tree_fits_shwi_p (fsize)
>-			    && tree_fits_shwi_p (ssize)
>-			    && doffset.fits_shwi ())
>-			  maxsize += ((tree_to_shwi (ssize)
>-				       - tree_to_shwi (fsize))
>-				      * BITS_PER_UNIT
>-					- doffset.to_shwi ());
>+			if (fsize == NULL
>+			    || TREE_CODE (fsize) != INTEGER_CST
>+			    || ssize == NULL
>+			    || TREE_CODE (ssize) != INTEGER_CST)
>+			  maxsize = double_int_minus_one;
> 			else
>-			  maxsize = -1;
>+			  {
>+			    double_int tem = tree_to_double_int (ssize)
>+					     - tree_to_double_int (fsize);
>+			    if (BITS_PER_UNIT == 8)
>+			      tem = tem.lshift (3);
>+			    else
>+			      tem *= double_int::from_uhwi (BITS_PER_UNIT);
>+			    tem -= doffset;
>+			    maxsize += tem;
>+			  }
> 		      }
> 		  }
> 	      }
>@@ -477,13 +479,12 @@ get_ref_base_and_extent (tree exp, HOST_
> 		/* We need to adjust maxsize to the whole structure bitsize.
> 		   But we can subtract any constant offset seen so far,
> 		   because that would get us out of the structure otherwise.  */
>-		if (maxsize != -1
>+		if (!maxsize.is_minus_one ()
> 		    && csize
>-		    && tree_fits_uhwi_p (csize)
>-		    && bit_offset.fits_shwi ())
>-		  maxsize = tree_to_uhwi (csize) - bit_offset.to_shwi ();
>+		    && TREE_CODE (csize) == INTEGER_CST)
>+		  maxsize = tree_to_double_int (csize) - bit_offset;
> 		else
>-		  maxsize = -1;
>+		  maxsize = double_int_minus_one;
> 	      }
> 	  }
> 	  break;
>@@ -520,13 +521,12 @@ get_ref_base_and_extent (tree exp, HOST_
> 		/* We need to adjust maxsize to the whole array bitsize.
> 		   But we can subtract any constant offset seen so far,
> 		   because that would get us outside of the array otherwise.  */
>-		if (maxsize != -1
>+		if (!maxsize.is_minus_one ()
> 		    && asize
>-		    && tree_fits_uhwi_p (asize)
>-		    && bit_offset.fits_shwi ())
>-		  maxsize = tree_to_uhwi (asize) - bit_offset.to_shwi ();
>+		    && TREE_CODE (asize) == INTEGER_CST)
>+		  maxsize = tree_to_double_int (asize) - bit_offset;
> 		else
>-		  maxsize = -1;
>+		  maxsize = double_int_minus_one;
> 
> 		/* Remember that we have seen an array ref with a variable
> 		   index.  */
>@@ -539,7 +539,7 @@ get_ref_base_and_extent (tree exp, HOST_
> 	  break;
> 
> 	case IMAGPART_EXPR:
>-	  bit_offset += double_int::from_uhwi (bitsize);
>+	  bit_offset += bitsize;
> 	  break;
> 
> 	case VIEW_CONVERT_EXPR:
>@@ -553,7 +553,7 @@ get_ref_base_and_extent (tree exp, HOST_
> 	    {
> 	      exp = TREE_OPERAND (TMR_BASE (exp), 0);
> 	      bit_offset = double_int_zero;
>-	      maxsize = -1;
>+	      maxsize = double_int_minus_one;
> 	      goto done;
> 	    }
> 	  /* Fallthru.  */
>@@ -569,13 +569,12 @@ get_ref_base_and_extent (tree exp, HOST_
> 	     base type boundary.  This needs to include possible trailing
> 	     padding that is there for alignment purposes.  */
> 	  if (seen_variable_array_ref
>-	      && maxsize != -1
>-	      && (!bit_offset.fits_shwi ()
>-		  || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp)))
>-		  || (bit_offset.to_shwi () + maxsize
>-		      == (HOST_WIDE_INT) tree_to_uhwi
>-		            (TYPE_SIZE (TREE_TYPE (exp))))))
>-	    maxsize = -1;
>+	      && !maxsize.is_minus_one ()
>+	      && (TYPE_SIZE (TREE_TYPE (exp)) == NULL_TREE
>+		  || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
>+		  || (bit_offset + maxsize
>+		      == tree_to_double_int (TYPE_SIZE (TREE_TYPE (exp))))))
>+	    maxsize = double_int_minus_one;
> 
> 	  /* Hand back the decl for MEM[&decl, off].  */
> 	  if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
>@@ -606,25 +605,32 @@ get_ref_base_and_extent (tree exp, HOST_
> 
>   /* We need to deal with variable arrays ending structures.  */
>   if (seen_variable_array_ref
>-      && maxsize != -1
>-      && (!bit_offset.fits_shwi ()
>-	  || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp)))
>-	  || (bit_offset.to_shwi () + maxsize
>-	      == (HOST_WIDE_INT) tree_to_uhwi
>-	           (TYPE_SIZE (TREE_TYPE (exp))))))
>-    maxsize = -1;
>+      && !maxsize.is_minus_one ()
>+      && (TYPE_SIZE (TREE_TYPE (exp)) == NULL_TREE
>+	  || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
>+	  || (bit_offset + maxsize
>+	      == tree_to_double_int (TYPE_SIZE (TREE_TYPE (exp))))))
>+    maxsize = double_int_minus_one;
> 
>  done:
>-  if (!bit_offset.fits_shwi ())
>+  if (!bitsize.fits_shwi () || bitsize.is_negative ())
>     {
>       *poffset = 0;
>-      *psize = bitsize;
>+      *psize = -1;
>       *pmax_size = -1;
> 
>       return exp;
>     }
> 
>-  hbit_offset = bit_offset.to_shwi ();
>+  *psize = bitsize.to_shwi ();
>+
>+  if (!bit_offset.fits_shwi ())
>+    {
>+      *poffset = 0;
>+      *pmax_size = -1;
>+
>+      return exp;
>+    }
> 
>   /* In case of a decl or constant base object we can do better.  */
> 
>@@ -632,25 +638,30 @@ get_ref_base_and_extent (tree exp, HOST_
>     {
>       /* If maxsize is unknown adjust it according to the size of the
>          base decl.  */
>-      if (maxsize == -1
>-	  && tree_fits_uhwi_p (DECL_SIZE (exp)))
>-	maxsize = tree_to_uhwi (DECL_SIZE (exp)) - hbit_offset;
>+      if (maxsize.is_minus_one ()
>+	  && DECL_SIZE (exp)
>+	  && TREE_CODE (DECL_SIZE (exp)) == INTEGER_CST)
>+	maxsize = tree_to_double_int (DECL_SIZE (exp)) - bit_offset;
>     }
>   else if (CONSTANT_CLASS_P (exp))
>     {
>       /* If maxsize is unknown adjust it according to the size of the
>          base type constant.  */
>-      if (maxsize == -1
>-	  && tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp))))
>-	maxsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp))) - hbit_offset;
>+      if (maxsize.is_minus_one ()
>+	  && TYPE_SIZE (TREE_TYPE (exp))
>+	  && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST)
>+	maxsize = tree_to_double_int (TYPE_SIZE (TREE_TYPE (exp)))
>+		  - bit_offset;
>     }
> 
>   /* ???  Due to negative offsets in ARRAY_REF we can end up with
>      negative bit_offset here.  We might want to store a zero offset
>      in this case.  */
>-  *poffset = hbit_offset;
>-  *psize = bitsize;
>-  *pmax_size = maxsize;
>+  *poffset = bit_offset.to_shwi ();
>+  if (!maxsize.fits_shwi () || maxsize.is_negative ())
>+    *pmax_size = -1;
>+  else
>+    *pmax_size = maxsize.to_shwi ();
> 
>   return exp;
> }
>
>	Jakub




More information about the Gcc-patches mailing list