This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR24851 (2nd version)


On Tue, 15 Nov 2005, Richard Guenther wrote:

> I have a patch along Andrews that fixes both testcases.  I'll post it as
> soon as testing finishes.

Here it is.  It fixes fold and fold_stmt to use signed division in
recombining pointer + offset to an ARRAY_REF.  I'm not sure this is
a correct fix, but it passes bootstrap and regtesting (32 and 64 bit)
on x86_64-unknown-linux-gnu for all default languages.

What do you think?

Richard.


2005-11-15  Richard Guenther  <rguenther@suse.de>

	PR middle-end/24851
	* fold-const.c (try_move_mult_to_index): Make sure to
	use a signed division for ptr-offset / element-size.
	* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Likewise.

	* gcc.c-torture/execute/pr24851.c: New testcase.

Index: fold-const.c
===================================================================
--- fold-const.c	(revision 106944)
+++ fold-const.c	(working copy)
@@ -6450,11 +6450,16 @@ try_move_mult_to_index (enum tree_code c
 	    }
 	  else
 	    {
-	      /* Try if delta is a multiple of step.  */
-	      tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, delta, step);
+	      /* Try if delta is a multiple of step.  Make sure to
+		 use a signed division to correctly handle addition of
+		 -4B which is represented as unsigned 4294967292B.
+		 ???  This may break deliberate use of such large
+		 unsigned offsets.  */
+	      tree sdelta = fold_convert (signed_type_for (TREE_TYPE (step)), delta);
+	      tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, sdelta, step);
 	      if (! tmp)
 		continue;
-	      delta = tmp;
+	      delta = fold_convert (TREE_TYPE (delta), tmp);
 	    }
 
 	  break;
Index: tree-ssa-ccp.c
===================================================================
--- tree-ssa-ccp.c	(revision 106944)
+++ tree-ssa-ccp.c	(working copy)
@@ -1522,18 +1522,24 @@ maybe_fold_offset_to_array_ref (tree bas
     {
       unsigned HOST_WIDE_INT lquo, lrem;
       HOST_WIDE_INT hquo, hrem;
+      tree stype = signed_type_for (TREE_TYPE (elt_size));
+      tree soffset = fold_convert (stype, offset);
 
+      /* Make sure we do the divide in a singed mode to handle
+	 negative offsets represented as unsigned, like -4B.
+	 ???  This may break deliberate use of such large
+	 unsigned offsets.  */
       if (TREE_CODE (elt_size) != INTEGER_CST
-	  || div_and_round_double (TRUNC_DIV_EXPR, 1,
-				   TREE_INT_CST_LOW (offset),
-				   TREE_INT_CST_HIGH (offset),
+	  || div_and_round_double (TRUNC_DIV_EXPR, 0,
+				   TREE_INT_CST_LOW (soffset),
+				   TREE_INT_CST_HIGH (soffset),
 				   TREE_INT_CST_LOW (elt_size),
 				   TREE_INT_CST_HIGH (elt_size),
 				   &lquo, &hquo, &lrem, &hrem)
 	  || lrem || hrem)
 	return NULL_TREE;
 
-      idx = build_int_cst_wide (NULL_TREE, lquo, hquo);
+      idx = build_int_cst_wide (stype, lquo, hquo);
     }
 
   /* Assume the low bound is zero.  If there is a domain type, get the


/* We used to handle pointer addition wrongly
   at the time of recombining to an ARRAY_REF
   in the case of
     p + -4B
   where -4B is represented as unsigned.  */

void abort(void);
int main()
{
  int a[10], *p, *q;
  q = &a[1];
  p = &q[-1];
  if (p >= &a[9])
    abort ();
  return 0;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]