[patch] rfa: fix problem with reassociating pointer additions

Eric Christopher echristo@redhat.com
Mon Oct 4 22:44:00 GMT 2004


So, in this testcase:

int *
foo (void)
{
  char *a;
  int b, c;
  int *z;
 
  z  = (int *) (a + (b + sizeof (c)));
 
  return z; 
}

(or even changing out the sizeof(c) for the actual constant)

We end up reassociating the constant addition into either

(a+(sizeof (c))) + b or
(a+b) + sizeof(c).

either could be a problem when dealing with pointer arithmetic near the
boundaries of addressable memory. The following patch disables
reassociation for pointers and deletes some old code that should have
been unused as we should handle it in fold. (Just the fix to fold-const
wouldn't work because then the second code would activate though).

OK? Comments?

-eric

-- 
Eric Christopher <echristo@redhat.com>

2004-10-04  Eric Christopher  <echristo@redhat.com>

	* c-common.c (pointer_int_sum): Remove code to reassociate
	additions.
	* fold-const.c (fold): Don't reassociate if we are
	working with pointer arithmetic.

Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.576
diff -u -p -w -r1.576 c-common.c
--- c-common.c	3 Oct 2004 20:52:59 -0000	1.576
+++ c-common.c	4 Oct 2004 22:11:31 -0000
@@ -2253,37 +2253,6 @@ pointer_int_sum (enum tree_code resultco
   else
     size_exp = size_in_bytes (TREE_TYPE (result_type));
 
-  /* If what we are about to multiply by the size of the elements
-     contains a constant term, apply distributive law
-     and multiply that constant term separately.
-     This helps produce common subexpressions.  */
-
-  if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) ==
MINUS_EXPR)
-      && !TREE_CONSTANT (intop)
-      && TREE_CONSTANT (TREE_OPERAND (intop, 1))
-      && TREE_CONSTANT (size_exp)
-      /* If the constant comes from pointer subtraction,
-	 skip this optimization--it would cause an error.  */
-      && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) ==
INTEGER_TYPE
-      /* If the constant is unsigned, and smaller than the pointer
size,
-	 then we must skip this optimization.  This is because it could cause
-	 an overflow error if the constant is negative but INTOP is not.  */
-      && (!TYPE_UNSIGNED (TREE_TYPE (intop))
-	  || (TYPE_PRECISION (TREE_TYPE (intop))
-	      == TYPE_PRECISION (TREE_TYPE (ptrop)))))
-    {
-      enum tree_code subcode = resultcode;
-      tree int_type = TREE_TYPE (intop);
-      if (TREE_CODE (intop) == MINUS_EXPR)
-	subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
-      /* Convert both subexpression types to the type of intop,
-	 because weird cases involving pointer arithmetic
-	 can result in a sum or difference with different type args.  */
-      ptrop = build_binary_op (subcode, ptrop,
-			       convert (int_type, TREE_OPERAND (intop, 1)), 1);
-      intop = convert (int_type, TREE_OPERAND (intop, 0));
-    }
-
   /* Convert the integer argument to a type the same size as sizetype
      so the multiply won't overflow spuriously.  */
 
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.466
diff -u -p -w -r1.466 fold-const.c
--- fold-const.c	3 Oct 2004 15:31:50 -0000	1.466
+++ fold-const.c	4 Oct 2004 22:11:33 -0000
@@ -6787,7 +6787,8 @@ fold (tree expr)
 	 -funsafe-math-optimizations.  */
 
       if (! wins
-	  && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
+	  && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+	  && (! POINTER_TYPE_P (type)))
 	{
 	  tree var0, con0, lit0, minus_lit0;
 	  tree var1, con1, lit1, minus_lit1;




More information about the Gcc-patches mailing list