Pointer Plus Patch

Andrew Pinski pinskia@gmail.com
Wed Jun 13 09:40:00 GMT 2007


Since I don't know if I got the official go ahead to just merge this
branch or not (I am a bit worried to merge it and then getting told I
did the wrong thing), I am sending the (big) patch for review (it
includes a new changelog for each directory which contained a
changelog before).  This is latest and greatest patch from the branch.
 The patch contains a couple of new testcases which could go in
seperate if need be.  But most of the changes are mechanical
s/PLUS_EXPR/POINTER_PLUS_EXPR/ .  There are a couple of places where
it is not.  Scalar evolution for an example has a change such that
when you have a pointer type, the increment is not in that pointer
type but is in sizetype.  In VRP, we only support now MIN_EXPR,
MAX_EXPR, and POINTER_PLUS_EXPR for pointers and we will get ICEs if
we have any other tree code.  Alias is better because we now know
which side is a pointer type (this is also true for restrict for rtl
aliasing too).

Even though this patch is large, it removes a lot of code dealing with
how the index could be either operand of PLUS_EXPR.  It only adds a
small bit of extra folding (cross folding between PLUS_EXPR and
POINTER_PLUS_EXPR).

I think I added enough checks in both build2_stat and in the tree cfg
checking code to make sure we only get POINTER_PLUS_EXPR and no
PLUS_EXPR for pointers.

There is only one part which I have been worried about and that is the
C++ front-end when dealing with templates, this patch does a build2
with a NULL operand 0 to get around checking for pointer type with
PLUS_EXPR.  I did not change to change more code in the C++ front-end
than I wantted to.  I did forget one thing I need to change for the
C++ front-end, the diagnostic code; I only thought of this now.

What should I do about the ChangeLog, should I keep ChangeLog.ptr or
write a new one and when I commit, commit it with that one?

This branch has been bootstrapped and tested on powerpc64-linux-gnu,
i686-linux-gnu, powerpc-darwin, sh4-linux-gnu, sparc-solaris,
ia64-linux-gnu.  Built and tested for arm-elf, mips-elf, spu-elf.  And
some more which I forgot now.  This was tested with Ada turned on at
least on i686-linux-gnu.

Should I just go ahead and merge it tomorrow or wait for review of the patch?

Thanks,
Andrew Pinski
-------------- next part --------------
Index: tree-vrp.c
===================================================================
*** tree-vrp.c	(.../trunk/gcc)	(revision 125658)
--- tree-vrp.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** compare_values_warnv (tree val1, tree va
*** 766,771 ****
--- 766,775 ----
       both integers.  */
    gcc_assert (POINTER_TYPE_P (TREE_TYPE (val1))
  	      == POINTER_TYPE_P (TREE_TYPE (val2)));
+   /* Convert the two values into the same type, this is needed because
+      sizetype causes sign extension even for unsigned types.  */
+   val2 = fold_convert (TREE_TYPE (val1), val2);
+   STRIP_USELESS_TYPE_CONVERSION (val2);
  
    if ((TREE_CODE (val1) == SSA_NAME
         || TREE_CODE (val1) == PLUS_EXPR
*************** extract_range_from_assert (value_range_t
*** 1494,1503 ****
  		    }
  		  max = negative_overflow_infinity (TREE_TYPE (var_vr->min));
  		}
! 	      else
  		max = fold_build2 (MINUS_EXPR, TREE_TYPE (var_vr->min),
  				   anti_min,
  				   build_int_cst (TREE_TYPE (var_vr->min), 1));
  	      min = real_min;
  	      set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
  	    }
--- 1498,1511 ----
  		    }
  		  max = negative_overflow_infinity (TREE_TYPE (var_vr->min));
  		}
! 	      else if (!POINTER_TYPE_P (TREE_TYPE (var_vr->min)))
  		max = fold_build2 (MINUS_EXPR, TREE_TYPE (var_vr->min),
  				   anti_min,
  				   build_int_cst (TREE_TYPE (var_vr->min), 1));
+ 	      else
+ 		max = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (var_vr->min),
+ 				   anti_min,
+ 				   size_int (-1));
  	      min = real_min;
  	      set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
  	    }
*************** extract_range_from_binary_expr (value_ra
*** 1693,1698 ****
--- 1701,1707 ----
       meaningful way.  Handle only arithmetic operations.  */
    if (code != PLUS_EXPR
        && code != MINUS_EXPR
+       && code != POINTER_PLUS_EXPR
        && code != MULT_EXPR
        && code != TRUNC_DIV_EXPR
        && code != FLOOR_DIV_EXPR
*************** extract_range_from_binary_expr (value_ra
*** 1763,1788 ****
        || POINTER_TYPE_P (TREE_TYPE (op0))
        || POINTER_TYPE_P (TREE_TYPE (op1)))
      {
!       /* For pointer types, we are really only interested in asserting
! 	 whether the expression evaluates to non-NULL.  FIXME, we used
! 	 to gcc_assert (code == PLUS_EXPR || code == MINUS_EXPR), but
! 	 ivopts is generating expressions with pointer multiplication
! 	 in them.  */
!       if (code == PLUS_EXPR)
  	{
! 	  if (range_is_nonnull (&vr0) || range_is_nonnull (&vr1))
  	    set_value_range_to_nonnull (vr, TREE_TYPE (expr));
  	  else if (range_is_null (&vr0) && range_is_null (&vr1))
  	    set_value_range_to_null (vr, TREE_TYPE (expr));
  	  else
  	    set_value_range_to_varying (vr);
  	}
        else
! 	{
! 	  /* Subtracting from a pointer, may yield 0, so just drop the
! 	     resulting range to varying.  */
! 	  set_value_range_to_varying (vr);
! 	}
  
        return;
      }
--- 1772,1801 ----
        || POINTER_TYPE_P (TREE_TYPE (op0))
        || POINTER_TYPE_P (TREE_TYPE (op1)))
      {
!       if (code == MIN_EXPR || code == MAX_EXPR)
  	{
! 	  /* For MIN/MAX expressions with pointers, we only care about
! 	     nullness, if both are non null, then the result is nonnull.
! 	     If both are null, then the result is null. Other wise they
! 	     are varrying.  */
! 	  if (range_is_nonnull (&vr0) && range_is_nonnull (&vr1))
  	    set_value_range_to_nonnull (vr, TREE_TYPE (expr));
  	  else if (range_is_null (&vr0) && range_is_null (&vr1))
  	    set_value_range_to_null (vr, TREE_TYPE (expr));
  	  else
  	    set_value_range_to_varying (vr);
+ 
+ 	  return;
  	}
+       gcc_assert (code == POINTER_PLUS_EXPR);
+       /* For pointer types, we are really only interested in asserting
+ 	 whether the expression evaluates to non-NULL.  */
+       if (range_is_nonnull (&vr0) || range_is_nonnull (&vr1))
+ 	set_value_range_to_nonnull (vr, TREE_TYPE (expr));
+       else if (range_is_null (&vr0) && range_is_null (&vr1))
+ 	set_value_range_to_null (vr, TREE_TYPE (expr));
        else
! 	set_value_range_to_varying (vr);
  
        return;
      }
Index: doc/c-tree.texi
===================================================================
*** doc/c-tree.texi	(.../trunk/gcc)	(revision 125658)
--- doc/c-tree.texi	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** This macro returns the attributes on the
*** 1918,1923 ****
--- 1918,1924 ----
  @tindex TRUTH_AND_EXPR
  @tindex TRUTH_OR_EXPR
  @tindex TRUTH_XOR_EXPR
+ @tindex POINTER_PLUS_EXPR
  @tindex PLUS_EXPR
  @tindex MINUS_EXPR
  @tindex MULT_EXPR
*************** generate these expressions anyhow, if it
*** 2292,2297 ****
--- 2293,2304 ----
  not matter.  The type of the operands and that of the result are
  always of @code{BOOLEAN_TYPE} or @code{INTEGER_TYPE}.
  
+ @itemx POINTER_PLUS_EXPR
+ This node represents pointer arithmetic.  The first operand is always
+ a pointer/reference type.  The second operand is always an unsigned
+ integer type compatiable with sizetype.  This is the only binary
+ arthemetic operand that can operate on pointer types.
+ 
  @itemx PLUS_EXPR
  @itemx MINUS_EXPR
  @itemx MULT_EXPR
Index: tree-ssa-loop-niter.c
===================================================================
*** tree-ssa-loop-niter.c	(.../trunk/gcc)	(revision 125658)
--- tree-ssa-loop-niter.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** split_to_var_and_offset (tree expr, tree
*** 85,90 ****
--- 85,91 ----
        /* Fallthru.  */
  
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
        op0 = TREE_OPERAND (expr, 0);
        op1 = TREE_OPERAND (expr, 1);
  
*************** number_of_iterations_lt_to_ne (tree type
*** 678,689 ****
    mpz_t mmod;
    tree assumption = boolean_true_node, bound, noloop;
    bool ret = false;
  
    if (TREE_CODE (mod) != INTEGER_CST)
      return false;
    if (integer_nonzerop (mod))
      mod = fold_build2 (MINUS_EXPR, niter_type, step, mod);
!   tmod = fold_convert (type, mod);
  
    mpz_init (mmod);
    mpz_set_double_int (mmod, tree_to_double_int (mod), true);
--- 679,693 ----
    mpz_t mmod;
    tree assumption = boolean_true_node, bound, noloop;
    bool ret = false;
+   tree type1 = type;
+   if (POINTER_TYPE_P (type))
+     type1 = sizetype;
  
    if (TREE_CODE (mod) != INTEGER_CST)
      return false;
    if (integer_nonzerop (mod))
      mod = fold_build2 (MINUS_EXPR, niter_type, step, mod);
!   tmod = fold_convert (type1, mod);
  
    mpz_init (mmod);
    mpz_set_double_int (mmod, tree_to_double_int (mod), true);
*************** number_of_iterations_lt_to_ne (tree type
*** 697,703 ****
        if (!iv1->no_overflow && !integer_zerop (mod))
  	{
  	  bound = fold_build2 (MINUS_EXPR, type,
! 			       TYPE_MAX_VALUE (type), tmod);
  	  assumption = fold_build2 (LE_EXPR, boolean_type_node,
  				    iv1->base, bound);
  	  if (integer_zerop (assumption))
--- 701,707 ----
        if (!iv1->no_overflow && !integer_zerop (mod))
  	{
  	  bound = fold_build2 (MINUS_EXPR, type,
! 			       TYPE_MAX_VALUE (type1), tmod);
  	  assumption = fold_build2 (LE_EXPR, boolean_type_node,
  				    iv1->base, bound);
  	  if (integer_zerop (assumption))
*************** number_of_iterations_lt_to_ne (tree type
*** 708,714 ****
        else
  	noloop = fold_build2 (GT_EXPR, boolean_type_node,
  			      iv0->base,
! 			      fold_build2 (PLUS_EXPR, type,
  					   iv1->base, tmod));
      }
    else
--- 712,718 ----
        else
  	noloop = fold_build2 (GT_EXPR, boolean_type_node,
  			      iv0->base,
! 			      fold_build2 (PLUS_EXPR, type1,
  					   iv1->base, tmod));
      }
    else
*************** number_of_iterations_lt_to_ne (tree type
*** 718,725 ****
  	 iv0->base - MOD <= iv1->base. */
        if (!iv0->no_overflow && !integer_zerop (mod))
  	{
! 	  bound = fold_build2 (PLUS_EXPR, type,
! 			       TYPE_MIN_VALUE (type), tmod);
  	  assumption = fold_build2 (GE_EXPR, boolean_type_node,
  				    iv0->base, bound);
  	  if (integer_zerop (assumption))
--- 722,729 ----
  	 iv0->base - MOD <= iv1->base. */
        if (!iv0->no_overflow && !integer_zerop (mod))
  	{
! 	  bound = fold_build2 (PLUS_EXPR, type1,
! 			       TYPE_MIN_VALUE (type1), tmod);
  	  assumption = fold_build2 (GE_EXPR, boolean_type_node,
  				    iv0->base, bound);
  	  if (integer_zerop (assumption))
*************** number_of_iterations_lt_to_ne (tree type
*** 729,735 ****
  	noloop = boolean_false_node;
        else
  	noloop = fold_build2 (GT_EXPR, boolean_type_node,
! 			      fold_build2 (MINUS_EXPR, type,
  					   iv0->base, tmod),
  			      iv1->base);
      }
--- 733,739 ----
  	noloop = boolean_false_node;
        else
  	noloop = fold_build2 (GT_EXPR, boolean_type_node,
! 			      fold_build2 (MINUS_EXPR, type1,
  					   iv0->base, tmod),
  			      iv1->base);
      }
*************** assert_loop_rolls_lt (tree type, affine_
*** 830,836 ****
  		      struct tree_niter_desc *niter, bounds *bnds)
  {
    tree assumption = boolean_true_node, bound, diff;
!   tree mbz, mbzl, mbzr;
    bool rolls_p, no_overflow_p;
    double_int dstep;
    mpz_t mstep, max;
--- 834,840 ----
  		      struct tree_niter_desc *niter, bounds *bnds)
  {
    tree assumption = boolean_true_node, bound, diff;
!   tree mbz, mbzl, mbzr, type1;
    bool rolls_p, no_overflow_p;
    double_int dstep;
    mpz_t mstep, max;
*************** assert_loop_rolls_lt (tree type, affine_
*** 888,908 ****
  
    if (rolls_p && no_overflow_p)
      return;
! 
    /* Now the hard part; we must formulate the assumption(s) as expressions, and
       we must be careful not to introduce overflow.  */
  
    if (integer_nonzerop (iv0->step))
      {
!       diff = fold_build2 (MINUS_EXPR, type,
! 			  iv0->step, build_int_cst (type, 1));
  
        /* We need to know that iv0->base >= MIN + iv0->step - 1.  Since
  	 0 address never belongs to any object, we can assume this for
  	 pointers.  */
        if (!POINTER_TYPE_P (type))
  	{
! 	  bound = fold_build2 (PLUS_EXPR, type,
  			       TYPE_MIN_VALUE (type), diff);
  	  assumption = fold_build2 (GE_EXPR, boolean_type_node,
  				    iv0->base, bound);
--- 892,915 ----
  
    if (rolls_p && no_overflow_p)
      return;
!   
!   type1 = type;
!   if (POINTER_TYPE_P (type))
!     type1 = sizetype;
    /* Now the hard part; we must formulate the assumption(s) as expressions, and
       we must be careful not to introduce overflow.  */
  
    if (integer_nonzerop (iv0->step))
      {
!       diff = fold_build2 (MINUS_EXPR, type1,
! 			  iv0->step, build_int_cst (type1, 1));
  
        /* We need to know that iv0->base >= MIN + iv0->step - 1.  Since
  	 0 address never belongs to any object, we can assume this for
  	 pointers.  */
        if (!POINTER_TYPE_P (type))
  	{
! 	  bound = fold_build2 (PLUS_EXPR, type1,
  			       TYPE_MIN_VALUE (type), diff);
  	  assumption = fold_build2 (GE_EXPR, boolean_type_node,
  				    iv0->base, bound);
*************** assert_loop_rolls_lt (tree type, affine_
*** 910,933 ****
  
        /* And then we can compute iv0->base - diff, and compare it with
  	 iv1->base.  */      
!       mbzl = fold_build2 (MINUS_EXPR, type, iv0->base, diff);
        mbzr = iv1->base;
      }
    else
      {
!       diff = fold_build2 (PLUS_EXPR, type,
! 			  iv1->step, build_int_cst (type, 1));
  
        if (!POINTER_TYPE_P (type))
  	{
! 	  bound = fold_build2 (PLUS_EXPR, type,
  			       TYPE_MAX_VALUE (type), diff);
  	  assumption = fold_build2 (LE_EXPR, boolean_type_node,
  				    iv1->base, bound);
  	}
  
        mbzl = iv0->base;
!       mbzr = fold_build2 (MINUS_EXPR, type, iv1->base, diff);
      }
  
    if (!integer_nonzerop (assumption))
--- 917,940 ----
  
        /* And then we can compute iv0->base - diff, and compare it with
  	 iv1->base.  */      
!       mbzl = fold_build2 (MINUS_EXPR, type1, iv0->base, diff);
        mbzr = iv1->base;
      }
    else
      {
!       diff = fold_build2 (PLUS_EXPR, type1,
! 			  iv1->step, build_int_cst (type1, 1));
  
        if (!POINTER_TYPE_P (type))
  	{
! 	  bound = fold_build2 (PLUS_EXPR, type1,
  			       TYPE_MAX_VALUE (type), diff);
  	  assumption = fold_build2 (LE_EXPR, boolean_type_node,
  				    iv1->base, bound);
  	}
  
        mbzl = iv0->base;
!       mbzr = fold_build2 (MINUS_EXPR, type1, iv1->base, diff);
      }
  
    if (!integer_nonzerop (assumption))
*************** number_of_iterations_le (tree type, affi
*** 1062,1067 ****
--- 1069,1077 ----
  			 bounds *bnds)
  {
    tree assumption;
+   tree type1 = type;
+   if (POINTER_TYPE_P (type))
+     type1 = sizetype;
  
    /* Say that IV0 is the control variable.  Then IV0 <= IV1 iff
       IV0 < IV1 + 1, assuming that IV1 is not equal to the greatest
*************** number_of_iterations_le (tree type, affi
*** 1072,1081 ****
      {
        if (integer_nonzerop (iv0->step))
  	assumption = fold_build2 (NE_EXPR, boolean_type_node,
! 				  iv1->base, TYPE_MAX_VALUE (type));
        else
  	assumption = fold_build2 (NE_EXPR, boolean_type_node,
! 				  iv0->base, TYPE_MIN_VALUE (type));
  
        if (integer_zerop (assumption))
  	return false;
--- 1082,1091 ----
      {
        if (integer_nonzerop (iv0->step))
  	assumption = fold_build2 (NE_EXPR, boolean_type_node,
! 				  iv1->base, TYPE_MAX_VALUE (type1));
        else
  	assumption = fold_build2 (NE_EXPR, boolean_type_node,
! 				  iv0->base, TYPE_MIN_VALUE (type1));
  
        if (integer_zerop (assumption))
  	return false;
*************** number_of_iterations_le (tree type, affi
*** 1085,1097 ****
      }
  
    if (integer_nonzerop (iv0->step))
!     iv1->base = fold_build2 (PLUS_EXPR, type,
! 			     iv1->base, build_int_cst (type, 1));
    else
!     iv0->base = fold_build2 (MINUS_EXPR, type,
! 			     iv0->base, build_int_cst (type, 1));
  
!   bounds_add (bnds, double_int_one, type);
  
    return number_of_iterations_lt (type, iv0, iv1, niter, never_infinite, bnds);
  }
--- 1095,1107 ----
      }
  
    if (integer_nonzerop (iv0->step))
!     iv1->base = fold_build2 (PLUS_EXPR, type1,
! 			     iv1->base, build_int_cst (type1, 1));
    else
!     iv0->base = fold_build2 (MINUS_EXPR, type1,
! 			     iv0->base, build_int_cst (type1, 1));
  
!   bounds_add (bnds, double_int_one, type1);
  
    return number_of_iterations_lt (type, iv0, iv1, niter, never_infinite, bnds);
  }
*************** expand_simple_operations (tree expr)
*** 1433,1439 ****
        && !is_gimple_min_invariant (e)
        /* And increments and decrements by a constant are simple.  */
        && !((TREE_CODE (e) == PLUS_EXPR
! 	    || TREE_CODE (e) == MINUS_EXPR)
  	   && is_gimple_min_invariant (TREE_OPERAND (e, 1))))
      return expr;
  
--- 1443,1450 ----
        && !is_gimple_min_invariant (e)
        /* And increments and decrements by a constant are simple.  */
        && !((TREE_CODE (e) == PLUS_EXPR
! 	    || TREE_CODE (e) == MINUS_EXPR
! 	    || TREE_CODE (e) == POINTER_PLUS_EXPR)
  	   && is_gimple_min_invariant (TREE_OPERAND (e, 1))))
      return expr;
  
*************** derive_constant_upper_bound (tree val)
*** 2205,2210 ****
--- 2216,2222 ----
        return bnd;
  
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
      case MINUS_EXPR:
        op0 = TREE_OPERAND (val, 0);
        op1 = TREE_OPERAND (val, 1);
Index: tree-pretty-print.c
===================================================================
*** tree-pretty-print.c	(.../trunk/gcc)	(revision 125658)
--- tree-pretty-print.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** dump_generic_node (pretty_printer *buffe
*** 1233,1238 ****
--- 1233,1239 ----
      case WIDEN_MULT_EXPR:
      case MULT_EXPR:
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
      case MINUS_EXPR:
      case TRUNC_DIV_EXPR:
      case CEIL_DIV_EXPR:
*************** op_prio (tree op)
*** 2328,2333 ****
--- 2329,2335 ----
  
      case WIDEN_SUM_EXPR:
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
      case MINUS_EXPR:
        return 12;
  
*************** op_symbol_code (enum tree_code code)
*** 2486,2491 ****
--- 2488,2496 ----
  
      case VEC_RSHIFT_EXPR:
        return "v>>";
+ 
+     case POINTER_PLUS_EXPR:
+       return "p+";
   
      case PLUS_EXPR:
        return "+";
Index: java/class.c
===================================================================
*** java/class.c	(.../trunk/gcc)	(revision 125658)
--- java/class.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** make_class_data (tree type)
*** 1669,1676 ****
    tree id_class = get_identifier("java.lang.Class");
    /** Offset from start of virtual function table declaration
        to where objects actually point at, following new g++ ABI. */
!   tree dtable_start_offset = build_int_cst (NULL_TREE,
! 					    2 * POINTER_SIZE / BITS_PER_UNIT);
    VEC(int, heap) *field_indexes;
    tree first_real_field;
  
--- 1669,1675 ----
    tree id_class = get_identifier("java.lang.Class");
    /** Offset from start of virtual function table declaration
        to where objects actually point at, following new g++ ABI. */
!   tree dtable_start_offset = size_int (2 * POINTER_SIZE / BITS_PER_UNIT);
    VEC(int, heap) *field_indexes;
    tree first_real_field;
  
*************** make_class_data (tree type)
*** 1957,1963 ****
    PUSH_FIELD_VALUE (temp, "vtable",
  		    (flag_indirect_classes 
  		     ? null_pointer_node
! 		     : build2 (PLUS_EXPR, dtable_ptr_type,
  			       build1 (ADDR_EXPR, dtable_ptr_type,
  				       class_dtable_decl),
  			       dtable_start_offset)));
--- 1956,1962 ----
    PUSH_FIELD_VALUE (temp, "vtable",
  		    (flag_indirect_classes 
  		     ? null_pointer_node
! 		     : build2 (POINTER_PLUS_EXPR, dtable_ptr_type,
  			       build1 (ADDR_EXPR, dtable_ptr_type,
  				       class_dtable_decl),
  			       dtable_start_offset)));
*************** make_class_data (tree type)
*** 2005,2011 ****
    else
      PUSH_FIELD_VALUE (cons, "vtable",
  		      dtable_decl == NULL_TREE ? null_pointer_node
! 		      : build2 (PLUS_EXPR, dtable_ptr_type,
  				build1 (ADDR_EXPR, dtable_ptr_type,
  					dtable_decl),
  				dtable_start_offset));
--- 2004,2010 ----
    else
      PUSH_FIELD_VALUE (cons, "vtable",
  		      dtable_decl == NULL_TREE ? null_pointer_node
! 		      : build2 (POINTER_PLUS_EXPR, dtable_ptr_type,
  				build1 (ADDR_EXPR, dtable_ptr_type,
  					dtable_decl),
  				dtable_start_offset));
*************** build_symbol_entry (tree decl, tree spec
*** 2807,2813 ****
       system that this is a "special" symbol, i.e. one that should
       bypass access controls.  */
    if (special != NULL_TREE)
!     signature = build2 (PLUS_EXPR, TREE_TYPE (signature), signature, special);
        
    START_RECORD_CONSTRUCTOR (sym, symbol_type);
    PUSH_FIELD_VALUE (sym, "clname", clname);
--- 2806,2813 ----
       system that this is a "special" symbol, i.e. one that should
       bypass access controls.  */
    if (special != NULL_TREE)
!     signature = build2 (POINTER_PLUS_EXPR, TREE_TYPE (signature), signature,
! 			fold_convert (sizetype, special));
        
    START_RECORD_CONSTRUCTOR (sym, symbol_type);
    PUSH_FIELD_VALUE (sym, "clname", clname);
Index: java/except.c
===================================================================
*** java/except.c	(.../trunk/gcc)	(revision 125658)
--- java/except.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** build_exception_object_ref (tree type)
*** 467,474 ****
    /* Java only passes object via pointer and doesn't require adjusting.
       The java object is immediately before the generic exception header.  */
    obj = build0 (EXC_PTR_EXPR, build_pointer_type (type));
!   obj = build2 (MINUS_EXPR, TREE_TYPE (obj), obj,
! 		TYPE_SIZE_UNIT (TREE_TYPE (obj)));
    obj = build1 (INDIRECT_REF, type, obj);
  
    return obj;
--- 467,474 ----
    /* Java only passes object via pointer and doesn't require adjusting.
       The java object is immediately before the generic exception header.  */
    obj = build0 (EXC_PTR_EXPR, build_pointer_type (type));
!   obj = build2 (POINTER_PLUS_EXPR, TREE_TYPE (obj), obj,
! 		build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (TREE_TYPE (obj))));
    obj = build1 (INDIRECT_REF, type, obj);
  
    return obj;
Index: java/ChangeLog.ptr
===================================================================
*** java/ChangeLog.ptr	(.../trunk/gcc)	(revision 0)
--- java/ChangeLog.ptr	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,14 ----
+ 2007-05-12  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* class.c (make_class_data): Build the index in sizetype.
+ 	Use POINTER_PLUS_EXPR instead of PLUS_EXPR when
+ 	adding to a pointer type.
+ 	(build_symbol_entry): Likewise.
+ 	* expr.c (build_java_arrayaccess): Likewise.
+ 	(build_field_ref): Likewise.
+ 	(build_known_method_ref): Likewise.
+ 	(build_invokevirtual): Likewise.
+ 	* except.c (build_exception_object_ref): Do a
+ 	NEGATIVE and then a POINTER_PLUS_EXPR instead
+ 	of a MINUS_EXPR.
+ 
Index: java/expr.c
===================================================================
*** java/expr.c	(.../trunk/gcc)	(revision 125658)
--- java/expr.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** build_java_arrayaccess (tree array, tree
*** 929,941 ****
  
    /* Multiply the index by the size of an element to obtain a byte
       offset.  Convert the result to a pointer to the element type.  */
!   index = fold_convert (TREE_TYPE (node),
! 			build2 (MULT_EXPR, sizetype, 
! 				fold_convert (sizetype, index), 
! 				size_exp));
  
    /* Sum the byte offset and the address of the data field.  */
!   node = fold_build2 (PLUS_EXPR, TREE_TYPE (node), node, index);
  
    /* Finally, return
  
--- 929,940 ----
  
    /* Multiply the index by the size of an element to obtain a byte
       offset.  Convert the result to a pointer to the element type.  */
!   index = build2 (MULT_EXPR, sizetype, 
! 		  fold_convert (sizetype, index), 
! 		  size_exp);
  
    /* Sum the byte offset and the address of the data field.  */
!   node = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (node), node, index);
  
    /* Finally, return
  
*************** build_field_ref (tree self_value, tree s
*** 1744,1750 ****
  	  field_offset = fold (convert (sizetype, field_offset));
  	  self_value = java_check_reference (self_value, check);
  	  address 
! 	    = fold_build2 (PLUS_EXPR, 
  			   build_pointer_type (TREE_TYPE (field_decl)),
  			   self_value, field_offset);
  	  return fold_build1 (INDIRECT_REF, TREE_TYPE (field_decl), address);
--- 1743,1749 ----
  	  field_offset = fold (convert (sizetype, field_offset));
  	  self_value = java_check_reference (self_value, check);
  	  address 
! 	    = fold_build2 (POINTER_PLUS_EXPR, 
  			   build_pointer_type (TREE_TYPE (field_decl)),
  			   self_value, field_offset);
  	  return fold_build1 (INDIRECT_REF, TREE_TYPE (field_decl), address);
*************** build_known_method_ref (tree method, tre
*** 2228,2235 ****
  	  method_index++;
  	}
        method_index *= int_size_in_bytes (method_type_node);
!       ref = fold_build2 (PLUS_EXPR, method_ptr_type_node,
! 			 ref, build_int_cst (NULL_TREE, method_index));
        ref = build1 (INDIRECT_REF, method_type_node, ref);
        func = build3 (COMPONENT_REF, nativecode_ptr_type_node,
  		     ref, lookup_field (&method_type_node, ncode_ident),
--- 2227,2234 ----
  	  method_index++;
  	}
        method_index *= int_size_in_bytes (method_type_node);
!       ref = fold_build2 (POINTER_PLUS_EXPR, method_ptr_type_node,
! 			 ref, size_int (method_index));
        ref = build1 (INDIRECT_REF, method_type_node, ref);
        func = build3 (COMPONENT_REF, nativecode_ptr_type_node,
  		     ref, lookup_field (&method_type_node, ncode_ident),
*************** build_invokevirtual (tree dtable, tree m
*** 2333,2340 ****
  				   size_int (TARGET_VTABLE_USES_DESCRIPTORS));
      }
  
!   func = fold_build2 (PLUS_EXPR, nativecode_ptr_ptr_type_node, dtable,
! 		      convert (nativecode_ptr_ptr_type_node, method_index));
  
    if (TARGET_VTABLE_USES_DESCRIPTORS)
      func = build1 (NOP_EXPR, nativecode_ptr_type_node, func);
--- 2332,2339 ----
  				   size_int (TARGET_VTABLE_USES_DESCRIPTORS));
      }
  
!   func = fold_build2 (POINTER_PLUS_EXPR, nativecode_ptr_ptr_type_node, dtable,
! 		      convert (sizetype, method_index));
  
    if (TARGET_VTABLE_USES_DESCRIPTORS)
      func = build1 (NOP_EXPR, nativecode_ptr_type_node, func);
Index: optabs.c
===================================================================
*** optabs.c	(.../trunk/gcc)	(revision 125658)
--- optabs.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** optab_for_tree_code (enum tree_code code
*** 372,377 ****
--- 372,378 ----
    trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
    switch (code)
      {
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        return trapv ? addv_optab : add_optab;
  
Index: tree-ssa-loop-manip.c
===================================================================
*** tree-ssa-loop-manip.c	(.../trunk/gcc)	(revision 125658)
--- tree-ssa-loop-manip.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** create_iv (tree base, tree step, tree va
*** 96,102 ****
  	    }
  	}
      }
! 
    /* Gimplify the step if necessary.  We put the computations in front of the
       loop (i.e. the step should be loop invariant).  */
    step = force_gimple_operand (step, &stmts, true, var);
--- 96,108 ----
  	    }
  	}
      }
!   if (POINTER_TYPE_P (TREE_TYPE (base)))
!     {
!       step = fold_convert (sizetype, step);
!       if (incr_op == MINUS_EXPR)
! 	step = fold_build1 (NEGATE_EXPR, sizetype, step);
!       incr_op = POINTER_PLUS_EXPR;
!     }
    /* Gimplify the step if necessary.  We put the computations in front of the
       loop (i.e. the step should be loop invariant).  */
    step = force_gimple_operand (step, &stmts, true, var);
Index: tree-tailcall.c
===================================================================
*** tree-tailcall.c	(.../trunk/gcc)	(revision 125658)
--- tree-tailcall.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** process_assignment (tree ass, tree stmt,
*** 347,353 ****
        *ass_var = dest;
        return true;
  
!       /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR).  */
  
      default:
        return false;
--- 347,353 ----
        *ass_var = dest;
        return true;
  
!       /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR, POINTER_PLUS_EXPR).  */
  
      default:
        return false;
Index: tree.c
===================================================================
*** tree.c	(.../trunk/gcc)	(revision 125658)
--- tree.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** build2_stat (enum tree_code code, tree t
*** 3069,3074 ****
--- 3069,3084 ----
    gcc_assert (code != GIMPLE_MODIFY_STMT);
  #endif
  
+   if ((code == MINUS_EXPR || code == PLUS_EXPR || code == MULT_EXPR)
+       && arg0 && arg1 && tt && POINTER_TYPE_P (tt))
+     gcc_assert (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST);
+ 
+   if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt)
+     gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
+ 		&& TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
+ 		&& tree_ssa_useless_type_conversion_1 (sizetype,
+ 						       TREE_TYPE (arg1)));
+ 
    t = make_node_stat (code PASS_MEM_STAT);
    TREE_TYPE (t) = tt;
  
Index: tree-scalar-evolution.c
===================================================================
*** tree-scalar-evolution.c	(.../trunk/gcc)	(revision 125658)
--- tree-scalar-evolution.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** add_to_evolution_1 (unsigned loop_nb, tr
*** 665,672 ****
  	    }
  
  	  to_add = chrec_convert (type, to_add, at_stmt);
! 	  right = chrec_convert (type, right, at_stmt);
! 	  right = chrec_fold_plus (type, right, to_add);
  	  return build_polynomial_chrec (var, left, right);
  	}
        else
--- 665,672 ----
  	    }
  
  	  to_add = chrec_convert (type, to_add, at_stmt);
! 	  right = chrec_convert_rhs (type, right, at_stmt);
! 	  right = chrec_fold_plus (chrec_type (right), right, to_add);
  	  return build_polynomial_chrec (var, left, right);
  	}
        else
*************** add_to_evolution_1 (unsigned loop_nb, tr
*** 677,683 ****
  	  left = add_to_evolution_1 (loop_nb, CHREC_LEFT (chrec_before),
  				     to_add, at_stmt);
  	  right = CHREC_RIGHT (chrec_before);
! 	  right = chrec_convert (chrec_type (left), right, at_stmt);
  	  return build_polynomial_chrec (CHREC_VARIABLE (chrec_before),
  					 left, right);
  	}
--- 677,683 ----
  	  left = add_to_evolution_1 (loop_nb, CHREC_LEFT (chrec_before),
  				     to_add, at_stmt);
  	  right = CHREC_RIGHT (chrec_before);
! 	  right = chrec_convert_rhs (chrec_type (left), right, at_stmt);
  	  return build_polynomial_chrec (CHREC_VARIABLE (chrec_before),
  					 left, right);
  	}
*************** add_to_evolution_1 (unsigned loop_nb, tr
*** 688,694 ****
  	return chrec_dont_know;
  
        left = chrec_before;
!       right = chrec_convert (chrec_type (left), to_add, at_stmt);
        return build_polynomial_chrec (loop_nb, left, right);
      }
  }
--- 688,694 ----
  	return chrec_dont_know;
  
        left = chrec_before;
!       right = chrec_convert_rhs (chrec_type (left), to_add, at_stmt);
        return build_polynomial_chrec (loop_nb, left, right);
      }
  }
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1014,1028 ****
    tree rhs0, rhs1;
    tree type_rhs = TREE_TYPE (rhs);
    tree evol;
    
    /* The RHS is one of the following cases:
       - an SSA_NAME, 
       - an INTEGER_CST,
       - a PLUS_EXPR, 
       - a MINUS_EXPR,
       - an ASSERT_EXPR,
       - other cases are not yet handled.  */
!   switch (TREE_CODE (rhs))
      {
      case NOP_EXPR:
        /* This assignment is under the form "a_1 = (cast) rhs.  */
--- 1014,1031 ----
    tree rhs0, rhs1;
    tree type_rhs = TREE_TYPE (rhs);
    tree evol;
+   enum tree_code code;
    
    /* The RHS is one of the following cases:
       - an SSA_NAME, 
       - an INTEGER_CST,
       - a PLUS_EXPR, 
+      - a POINTER_PLUS_EXPR, 
       - a MINUS_EXPR,
       - an ASSERT_EXPR,
       - other cases are not yet handled.  */
!   code = TREE_CODE (rhs);
!   switch (code)
      {
      case NOP_EXPR:
        /* This assignment is under the form "a_1 = (cast) rhs.  */
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1043,1048 ****
--- 1046,1052 ----
  	(loop, SSA_NAME_DEF_STMT (rhs), halting_phi, evolution_of_loop, limit);
        break;
        
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        /* This case is under the form "rhs0 + rhs1".  */
        rhs0 = TREE_OPERAND (rhs, 0);
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1071,1077 ****
  		*evolution_of_loop = add_to_evolution 
  		  (loop->num, 
  		   chrec_convert (type_rhs, evol, at_stmt), 
! 		   PLUS_EXPR, rhs1, at_stmt);
  	      
  	      else if (res == t_false)
  		{
--- 1075,1081 ----
  		*evolution_of_loop = add_to_evolution 
  		  (loop->num, 
  		   chrec_convert (type_rhs, evol, at_stmt), 
! 		   code, rhs1, at_stmt);
  	      
  	      else if (res == t_false)
  		{
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1083,1089 ****
  		    *evolution_of_loop = add_to_evolution 
  		      (loop->num, 
  		       chrec_convert (type_rhs, *evolution_of_loop, at_stmt), 
! 		       PLUS_EXPR, rhs0, at_stmt);
  
  		  else if (res == t_dont_know)
  		    *evolution_of_loop = chrec_dont_know;
--- 1087,1093 ----
  		    *evolution_of_loop = add_to_evolution 
  		      (loop->num, 
  		       chrec_convert (type_rhs, *evolution_of_loop, at_stmt), 
! 		       code, rhs0, at_stmt);
  
  		  else if (res == t_dont_know)
  		    *evolution_of_loop = chrec_dont_know;
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1104,1110 ****
  		*evolution_of_loop = add_to_evolution 
  		  (loop->num, chrec_convert (type_rhs, *evolution_of_loop,
  					     at_stmt),
! 		   PLUS_EXPR, rhs1, at_stmt);
  
  	      else if (res == t_dont_know)
  		*evolution_of_loop = chrec_dont_know;
--- 1108,1114 ----
  		*evolution_of_loop = add_to_evolution 
  		  (loop->num, chrec_convert (type_rhs, *evolution_of_loop,
  					     at_stmt),
! 		   code, rhs1, at_stmt);
  
  	      else if (res == t_dont_know)
  		*evolution_of_loop = chrec_dont_know;
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1122,1128 ****
  	    *evolution_of_loop = add_to_evolution 
  	      (loop->num, chrec_convert (type_rhs, *evolution_of_loop,
  					 at_stmt),
! 	       PLUS_EXPR, rhs0, at_stmt);
  
  	  else if (res == t_dont_know)
  	    *evolution_of_loop = chrec_dont_know;
--- 1126,1132 ----
  	    *evolution_of_loop = add_to_evolution 
  	      (loop->num, chrec_convert (type_rhs, *evolution_of_loop,
  					 at_stmt),
! 	       code, rhs0, at_stmt);
  
  	  else if (res == t_dont_know)
  	    *evolution_of_loop = chrec_dont_know;
*************** interpret_rhs_modify_stmt (struct loop *
*** 1611,1616 ****
--- 1615,1630 ----
  
    switch (TREE_CODE (opnd1))
      {
+     case POINTER_PLUS_EXPR:
+       opnd10 = TREE_OPERAND (opnd1, 0);
+       opnd11 = TREE_OPERAND (opnd1, 1);
+       chrec10 = analyze_scalar_evolution (loop, opnd10);
+       chrec11 = analyze_scalar_evolution (loop, opnd11);
+       chrec10 = chrec_convert (type, chrec10, at_stmt);
+       chrec11 = chrec_convert (sizetype, chrec11, at_stmt);
+       res = chrec_fold_plus (type, chrec10, chrec11);
+       break;
+ 
      case PLUS_EXPR:
        opnd10 = TREE_OPERAND (opnd1, 0);
        opnd11 = TREE_OPERAND (opnd1, 1);
*************** compute_scalar_evolution_in_loop (struct
*** 1702,1888 ****
    return analyze_scalar_evolution_1 (wrto_loop, res, chrec_not_analyzed_yet);
  }
  
- /* Folds EXPR, if it is a cast to pointer, assuming that the created
-    polynomial_chrec does not wrap.  */
- 
- static tree
- fold_used_pointer_cast (tree expr)
- {
-   tree op;
-   tree type, inner_type;
- 
-   if (TREE_CODE (expr) != NOP_EXPR && TREE_CODE (expr) != CONVERT_EXPR)
-     return expr;
- 
-   op = TREE_OPERAND (expr, 0);
-   if (TREE_CODE (op) != POLYNOMIAL_CHREC)
-     return expr;
- 
-   type = TREE_TYPE (expr);
-   inner_type = TREE_TYPE (op);
- 
-   if (!INTEGRAL_TYPE_P (inner_type)
-       || TYPE_PRECISION (inner_type) != TYPE_PRECISION (type))
-     return expr;
- 
-   return build_polynomial_chrec (CHREC_VARIABLE (op),
- 		chrec_convert (type, CHREC_LEFT (op), NULL_TREE),
- 		chrec_convert (type, CHREC_RIGHT (op), NULL_TREE));
- }
- 
- /* Returns true if EXPR is an expression corresponding to offset of pointer
-    in p + offset.  */
- 
- static bool
- pointer_offset_p (tree expr)
- {
-   if (TREE_CODE (expr) == INTEGER_CST)
-     return true;
- 
-   if ((TREE_CODE (expr) == NOP_EXPR || TREE_CODE (expr) == CONVERT_EXPR)
-       && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0))))
-     return true;
- 
-   return false;
- }
- 
- /* EXPR is a scalar evolution of a pointer that is dereferenced or used in
-    comparison.  This means that it must point to a part of some object in
-    memory, which enables us to argue about overflows and possibly simplify
-    the EXPR.  AT_STMT is the statement in which this conversion has to be
-    performed.  Returns the simplified value.
- 
-    Currently, for
- 
-    int i, n;
-    int *p;
- 
-    for (i = -n; i < n; i++)
-      *(p + i) = ...;
- 
-    We generate the following code (assuming that size of int and size_t is
-    4 bytes):
- 
-    for (i = -n; i < n; i++)
-      {
-        size_t tmp1, tmp2;
-        int *tmp3, *tmp4;
- 
-        tmp1 = (size_t) i;	(1)
-        tmp2 = 4 * tmp1;		(2)
-        tmp3 = (int *) tmp2;	(3)
-        tmp4 = p + tmp3;		(4)
- 
-        *tmp4 = ...;
-      }
- 
-    We in general assume that pointer arithmetics does not overflow (since its
-    behavior is undefined in that case).  One of the problems is that our
-    translation does not capture this property very well -- (int *) is
-    considered unsigned, hence the computation in (4) does overflow if i is
-    negative.
- 
-    This impreciseness creates complications in scev analysis.  The scalar
-    evolution of i is [-n, +, 1].  Since int and size_t have the same precision
-    (in this example), and size_t is unsigned (so we do not care about
-    overflows), we succeed to derive that scev of tmp1 is [(size_t) -n, +, 1]
-    and scev of tmp2 is [4 * (size_t) -n, +, 4].  With tmp3, we run into
-    problem -- [(int *) (4 * (size_t) -n), +, 4] wraps, and since we on several
-    places assume that this is not the case for scevs with pointer type, we
-    cannot use this scev for tmp3; hence, its scev is
-    (int *) [(4 * (size_t) -n), +, 4], and scev of tmp4 is
-    p + (int *) [(4 * (size_t) -n), +, 4].  Most of the optimizers are unable to
-    work with scevs of this shape.
- 
-    However, since tmp4 is dereferenced, all its values must belong to a single
-    object, and taking into account that the precision of int * and size_t is
-    the same, it is impossible for its scev to wrap.  Hence, we can derive that
-    its evolution is [p + (int *) (4 * (size_t) -n), +, 4], which the optimizers
-    can work with.
- 
-    ??? Maybe we should use different representation for pointer arithmetics,
-    however that is a long-term project with a lot of potential for creating
-    bugs.  */
- 
- static tree
- fold_used_pointer (tree expr, tree at_stmt)
- {
-   tree op0, op1, new0, new1;
-   enum tree_code code = TREE_CODE (expr);
- 
-   if (code == PLUS_EXPR
-       || code == MINUS_EXPR)
-     {
-       op0 = TREE_OPERAND (expr, 0);
-       op1 = TREE_OPERAND (expr, 1);
- 
-       if (pointer_offset_p (op1))
- 	{
- 	  new0 = fold_used_pointer (op0, at_stmt);
- 	  new1 = fold_used_pointer_cast (op1);
- 	}
-       else if (code == PLUS_EXPR && pointer_offset_p (op0))
- 	{
- 	  new0 = fold_used_pointer_cast (op0);
- 	  new1 = fold_used_pointer (op1, at_stmt);
- 	}
-       else
- 	return expr;
- 
-       if (new0 == op0 && new1 == op1)
- 	return expr;
- 
-       new0 = chrec_convert (TREE_TYPE (expr), new0, at_stmt);
-       new1 = chrec_convert (TREE_TYPE (expr), new1, at_stmt);
- 
-       if (code == PLUS_EXPR)
- 	expr = chrec_fold_plus (TREE_TYPE (expr), new0, new1);
-       else
- 	expr = chrec_fold_minus (TREE_TYPE (expr), new0, new1);
- 
-       return expr;
-     }
-   else
-     return fold_used_pointer_cast (expr);
- }
- 
- /* Returns true if PTR is dereferenced, or used in comparison.  */
- 
- static bool
- pointer_used_p (tree ptr)
- {
-   use_operand_p use_p;
-   imm_use_iterator imm_iter;
-   tree stmt, rhs;
-   struct ptr_info_def *pi = get_ptr_info (ptr);
- 
-   /* Check whether the pointer has a memory tag; if it does, it is
-      (or at least used to be) dereferenced.  */
-   if ((pi != NULL && pi->name_mem_tag != NULL)
-       || symbol_mem_tag (SSA_NAME_VAR (ptr)))
-     return true;
- 
-   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ptr)
-     {
-       stmt = USE_STMT (use_p);
-       if (TREE_CODE (stmt) == COND_EXPR)
- 	return true;
- 
-       if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
- 	continue;
- 
-       rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-       if (!COMPARISON_CLASS_P (rhs))
- 	continue;
- 
-       if (GIMPLE_STMT_OPERAND (stmt, 0) == ptr
- 	  || GIMPLE_STMT_OPERAND (stmt, 1) == ptr)
- 	return true;
-     }
- 
-   return false;
- }
- 
  /* Helper recursive function.  */
  
  static tree
--- 1716,1721 ----
*************** analyze_scalar_evolution_1 (struct loop 
*** 1932,1942 ****
      case GIMPLE_MODIFY_STMT:
        res = interpret_rhs_modify_stmt (loop, def,
  	  			       GIMPLE_STMT_OPERAND (def, 1), type);
- 
-       if (POINTER_TYPE_P (type)
- 	  && !automatically_generated_chrec_p (res)
- 	  && pointer_used_p (var))
- 	res = fold_used_pointer (res, def);
        break;
  
      case PHI_NODE:
--- 1765,1770 ----
*************** instantiate_parameters_1 (struct loop *l
*** 2220,2230 ****
        if (CHREC_LEFT (chrec) != op0
  	  || CHREC_RIGHT (chrec) != op1)
  	{
! 	  op1 = chrec_convert (chrec_type (op0), op1, NULL_TREE);
  	  chrec = build_polynomial_chrec (CHREC_VARIABLE (chrec), op0, op1);
  	}
        return chrec;
  
      case PLUS_EXPR:
        op0 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 0),
  				      flags, cache, size_expr);
--- 2048,2059 ----
        if (CHREC_LEFT (chrec) != op0
  	  || CHREC_RIGHT (chrec) != op1)
  	{
! 	  op1 = chrec_convert_rhs (TREE_TYPE (op0), op1, NULL_TREE);
  	  chrec = build_polynomial_chrec (CHREC_VARIABLE (chrec), op0, op1);
  	}
        return chrec;
  
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        op0 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 0),
  				      flags, cache, size_expr);
*************** instantiate_parameters_1 (struct loop *l
*** 2240,2246 ****
  	  || TREE_OPERAND (chrec, 1) != op1)
  	{
  	  op0 = chrec_convert (type, op0, NULL_TREE);
! 	  op1 = chrec_convert (type, op1, NULL_TREE);
  	  chrec = chrec_fold_plus (type, op0, op1);
  	}
        return chrec;
--- 2069,2075 ----
  	  || TREE_OPERAND (chrec, 1) != op1)
  	{
  	  op0 = chrec_convert (type, op0, NULL_TREE);
! 	  op1 = chrec_convert_rhs (type, op1, NULL_TREE);
  	  chrec = chrec_fold_plus (type, op0, op1);
  	}
        return chrec;
Index: builtins.c
===================================================================
*** builtins.c	(.../trunk/gcc)	(revision 125658)
--- builtins.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** get_pointer_alignment (tree exp, unsigne
*** 291,297 ****
  	  align = MIN (inner, max_align);
  	  break;
  
! 	case PLUS_EXPR:
  	  /* If sum of pointer + int, restrict our maximum alignment to that
  	     imposed by the integer.  If not, we can't do any better than
  	     ALIGN.  */
--- 291,297 ----
  	  align = MIN (inner, max_align);
  	  break;
  
! 	case POINTER_PLUS_EXPR:
  	  /* If sum of pointer + int, restrict our maximum alignment to that
  	     imposed by the integer.  If not, we can't do any better than
  	     ALIGN.  */
*************** expand_builtin_strcat (tree fndecl, tree
*** 4433,4441 ****
  
  	  /* Create strlen (dst).  */
  	  newdst = build_call_expr (strlen_fn, 1, dst);
! 	  /* Create (dst + (cast) strlen (dst)).  */
! 	  newdst = fold_convert (TREE_TYPE (dst), newdst);
! 	  newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
  
  	  newdst = builtin_save_expr (newdst);
  
--- 4433,4440 ----
  
  	  /* Create strlen (dst).  */
  	  newdst = build_call_expr (strlen_fn, 1, dst);
! 	  /* Create (dst p+ strlen (dst)).  */
! 	  newdst = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
  
  	  newdst = builtin_save_expr (newdst);
  
*************** void
*** 4650,4658 ****
  std_expand_builtin_va_start (tree valist, rtx nextarg)
  {
    tree t;
  
!   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
! 	      make_tree (ptr_type_node, nextarg));
    TREE_SIDE_EFFECTS (t) = 1;
  
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
--- 4649,4658 ----
  std_expand_builtin_va_start (tree valist, rtx nextarg)
  {
    tree t;
+   t = make_tree (sizetype, nextarg);
+   t = fold_convert (ptr_type_node, t);
  
!   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,t);
    TREE_SIDE_EFFECTS (t) = 1;
  
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
*************** std_gimplify_va_arg_expr (tree valist, t
*** 4719,4732 ****
    if (boundary > align
        && !integer_zerop (TYPE_SIZE (type)))
      {
-       t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
        t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
! 		  build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
        gimplify_and_add (t, pre_p);
  
!       t = fold_convert (TREE_TYPE (valist), size_int (-boundary));
        t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
! 		  build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, t));
        gimplify_and_add (t, pre_p);
      }
    else
--- 4719,4734 ----
    if (boundary > align
        && !integer_zerop (TYPE_SIZE (type)))
      {
        t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
! 		  fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist),
! 			       valist_tmp, size_int (boundary - 1)));
        gimplify_and_add (t, pre_p);
  
!       t = fold_convert (sizetype, valist_tmp);
        t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
! 		  fold_convert (TREE_TYPE (valist),
! 				fold_build2 (BIT_AND_EXPR, sizetype, t,
! 					     size_int (-boundary))));
        gimplify_and_add (t, pre_p);
      }
    else
*************** std_gimplify_va_arg_expr (tree valist, t
*** 4757,4769 ****
        t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
        t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
  		       size_binop (MINUS_EXPR, rounded_size, type_size));
!       t = fold_convert (TREE_TYPE (addr), t);
!       addr = fold_build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t);
      }
  
    /* Compute new value for AP.  */
!   t = fold_convert (TREE_TYPE (valist), rounded_size);
!   t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t);
    t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
    gimplify_and_add (t, pre_p);
  
--- 4759,4769 ----
        t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
        t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
  		       size_binop (MINUS_EXPR, rounded_size, type_size));
!       addr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr), addr, t);
      }
  
    /* Compute new value for AP.  */
!   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist_tmp, rounded_size);
    t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
    gimplify_and_add (t, pre_p);
  
*************** fold_builtin_memory_op (tree dest, tree 
*** 8607,8614 ****
      len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
  		       ssize_int (1));
  
!   len = fold_convert (TREE_TYPE (dest), len);
!   dest = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
    dest = fold_convert (type, dest);
    if (expr)
      dest = omit_one_operand (type, dest, expr);
--- 8607,8613 ----
      len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
  		       ssize_int (1));
  
!   dest = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
    dest = fold_convert (type, dest);
    if (expr)
      dest = omit_one_operand (type, dest, expr);
*************** fold_builtin_memchr (tree arg1, tree arg
*** 8731,8738 ****
  	  if (r == NULL)
  	    return build_int_cst (TREE_TYPE (arg1), 0);
  
! 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (arg1), arg1,
! 			     build_int_cst (TREE_TYPE (arg1), r - p1));
  	  return fold_convert (type, tem);
  	}
        return NULL_TREE;
--- 8730,8737 ----
  	  if (r == NULL)
  	    return build_int_cst (TREE_TYPE (arg1), 0);
  
! 	  tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (arg1), arg1,
! 			     size_int (r - p1));
  	  return fold_convert (type, tem);
  	}
        return NULL_TREE;
*************** fold_builtin_strstr (tree s1, tree s2, t
*** 10609,10616 ****
  	    return build_int_cst (TREE_TYPE (s1), 0);
  
  	  /* Return an offset into the constant string argument.  */
! 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
! 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
  	  return fold_convert (type, tem);
  	}
  
--- 10608,10615 ----
  	    return build_int_cst (TREE_TYPE (s1), 0);
  
  	  /* Return an offset into the constant string argument.  */
! 	  tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
! 			     s1, build_int_cst (sizetype, r - p1));
  	  return fold_convert (type, tem);
  	}
  
*************** fold_builtin_strchr (tree s1, tree s2, t
*** 10679,10686 ****
  	    return build_int_cst (TREE_TYPE (s1), 0);
  
  	  /* Return an offset into the constant string argument.  */
! 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
! 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
  	  return fold_convert (type, tem);
  	}
        return NULL_TREE;
--- 10678,10685 ----
  	    return build_int_cst (TREE_TYPE (s1), 0);
  
  	  /* Return an offset into the constant string argument.  */
! 	  tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
! 			     s1, build_int_cst (sizetype, r - p1));
  	  return fold_convert (type, tem);
  	}
        return NULL_TREE;
*************** fold_builtin_strrchr (tree s1, tree s2, 
*** 10735,10742 ****
  	    return build_int_cst (TREE_TYPE (s1), 0);
  
  	  /* Return an offset into the constant string argument.  */
! 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
! 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
  	  return fold_convert (type, tem);
  	}
  
--- 10734,10741 ----
  	    return build_int_cst (TREE_TYPE (s1), 0);
  
  	  /* Return an offset into the constant string argument.  */
! 	  tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
! 			     s1, build_int_cst (sizetype, r - p1));
  	  return fold_convert (type, tem);
  	}
  
*************** fold_builtin_strpbrk (tree s1, tree s2, 
*** 10795,10802 ****
  	    return build_int_cst (TREE_TYPE (s1), 0);
  
  	  /* Return an offset into the constant string argument.  */
! 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
! 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
  	  return fold_convert (type, tem);
  	}
  
--- 10794,10801 ----
  	    return build_int_cst (TREE_TYPE (s1), 0);
  
  	  /* Return an offset into the constant string argument.  */
! 	  tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
! 			     s1, build_int_cst (sizetype, r - p1));
  	  return fold_convert (type, tem);
  	}
  
*************** expand_builtin_memory_chk (tree exp, rtx
*** 11382,11389 ****
  	      return expand_expr (dest, target, mode, EXPAND_NORMAL);
  	    }
  
! 	  len = fold_convert (TREE_TYPE (dest), len);
! 	  expr = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
  	  return expand_expr (expr, target, mode, EXPAND_NORMAL);
  	}
  
--- 11381,11387 ----
  	      return expand_expr (dest, target, mode, EXPAND_NORMAL);
  	    }
  
! 	  expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
  	  return expand_expr (expr, target, mode, EXPAND_NORMAL);
  	}
  
*************** fold_builtin_memory_chk (tree fndecl,
*** 11630,11637 ****
  	return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
        else
  	{
! 	  tree temp = fold_convert (TREE_TYPE (dest), len);
! 	  temp = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp);
  	  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
  	}
      }
--- 11628,11634 ----
  	return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
        else
  	{
! 	  tree temp = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
  	  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
  	}
      }
Index: fold-const.c
===================================================================
*** fold-const.c	(.../trunk/gcc)	(revision 125658)
--- fold-const.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** build_range_check (tree type, tree exp, 
*** 4439,4444 ****
--- 4439,4458 ----
  
    value = const_binop (MINUS_EXPR, high, low, 0);
  
+ 
+   if (POINTER_TYPE_P (etype))
+     {
+       if (value != 0 && !TREE_OVERFLOW (value))
+ 	{
+ 	  low = fold_convert (sizetype, low);
+ 	  low = fold_build1 (NEGATE_EXPR, sizetype, low);
+           return build_range_check (type,
+ 			     	    fold_build2 (POINTER_PLUS_EXPR, etype, exp, low),
+ 			            1, build_int_cst (etype, 0), value);
+ 	}
+       return 0;
+     }
+ 
    if (value != 0 && !TREE_OVERFLOW (value))
      return build_range_check (type,
  			      fold_build2 (MINUS_EXPR, etype, exp, low),
*************** constant_boolean_node (int value, tree t
*** 5992,5998 ****
     offset is set to NULL_TREE.  Base will be canonicalized to
     something you can get the element type from using
     TREE_TYPE (TREE_TYPE (base)).  Offset will be the offset
!    in bytes to the base.  */
  
  static bool
  extract_array_ref (tree expr, tree *base, tree *offset)
--- 6006,6012 ----
     offset is set to NULL_TREE.  Base will be canonicalized to
     something you can get the element type from using
     TREE_TYPE (TREE_TYPE (base)).  Offset will be the offset
!    in bytes to the base in sizetype.  */
  
  static bool
  extract_array_ref (tree expr, tree *base, tree *offset)
*************** extract_array_ref (tree expr, tree *base
*** 6000,6020 ****
    /* One canonical form is a PLUS_EXPR with the first
       argument being an ADDR_EXPR with a possible NOP_EXPR
       attached.  */
!   if (TREE_CODE (expr) == PLUS_EXPR)
      {
        tree op0 = TREE_OPERAND (expr, 0);
        tree inner_base, dummy1;
        /* Strip NOP_EXPRs here because the C frontends and/or
! 	 folders present us (int *)&x.a + 4B possibly.  */
        STRIP_NOPS (op0);
        if (extract_array_ref (op0, &inner_base, &dummy1))
  	{
  	  *base = inner_base;
! 	  if (dummy1 == NULL_TREE)
! 	    *offset = TREE_OPERAND (expr, 1);
! 	  else
! 	    *offset = fold_build2 (PLUS_EXPR, TREE_TYPE (expr),
! 				   dummy1, TREE_OPERAND (expr, 1));
  	  return true;
  	}
      }
--- 6014,6033 ----
    /* One canonical form is a PLUS_EXPR with the first
       argument being an ADDR_EXPR with a possible NOP_EXPR
       attached.  */
!   if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
      {
        tree op0 = TREE_OPERAND (expr, 0);
        tree inner_base, dummy1;
        /* Strip NOP_EXPRs here because the C frontends and/or
! 	 folders present us (int *)&x.a p+ 4 possibly.  */
        STRIP_NOPS (op0);
        if (extract_array_ref (op0, &inner_base, &dummy1))
  	{
  	  *base = inner_base;
! 	  *offset = fold_convert (sizetype, TREE_OPERAND (expr, 1));
! 	  if (dummy1 != NULL_TREE)
! 	    *offset = fold_build2 (PLUS_EXPR, sizetype,
! 				   dummy1, *offset);
  	  return true;
  	}
      }
*************** extract_array_ref (tree expr, tree *base
*** 6032,6037 ****
--- 6045,6051 ----
  	  *base = TREE_OPERAND (op0, 0);
  	  *offset = fold_build2 (MULT_EXPR, TREE_TYPE (idx), idx,
  				 array_ref_element_size (op0)); 
+ 	  *offset = fold_convert (sizetype, *offset);
  	}
        else
  	{
*************** fold_sign_changed_comparison (enum tree_
*** 6866,6872 ****
    return fold_build2 (code, type, arg0_inner, arg1);
  }
  
! /* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
     step of the array.  Reconstructs s and delta in the case of s * delta
     being an integer constant (and thus already folded).
     ADDR is the address. MULT is the multiplicative expression.
--- 6880,6886 ----
    return fold_build2 (code, type, arg0_inner, arg1);
  }
  
! /* Tries to replace &a[idx] p+ s * delta with &a[idx + delta], if s is
     step of the array.  Reconstructs s and delta in the case of s * delta
     being an integer constant (and thus already folded).
     ADDR is the address. MULT is the multiplicative expression.
*************** fold_sign_changed_comparison (enum tree_
*** 6874,6880 ****
     NULL_TREE is returned.  */
  
  static tree
! try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
  {
    tree s, delta, step;
    tree ref = TREE_OPERAND (addr, 0), pref;
--- 6888,6894 ----
     NULL_TREE is returned.  */
  
  static tree
! try_move_mult_to_index (tree addr, tree op1)
  {
    tree s, delta, step;
    tree ref = TREE_OPERAND (addr, 0), pref;
*************** try_move_mult_to_index (enum tree_code c
*** 6882,6887 ****
--- 6896,6904 ----
    tree itype;
    bool mdim = false;
  
+   /*  Stip the nops that might be added when converting op1 to sizetype. */
+   STRIP_NOPS (op1);
+ 
    /* Canonicalize op1 into a possibly non-constant delta
       and an INTEGER_CST s.  */
    if (TREE_CODE (op1) == MULT_EXPR)
*************** try_move_mult_to_index (enum tree_code c
*** 6958,6964 ****
  		  || TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST)
  		continue;
  
! 	      tmp = fold_binary (code, itype,
  				 fold_convert (itype,
  					       TREE_OPERAND (ref, 1)),
  				 fold_convert (itype, delta));
--- 6975,6981 ----
  		  || TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST)
  		continue;
  
! 	      tmp = fold_binary (PLUS_EXPR, itype,
  				 fold_convert (itype,
  					       TREE_OPERAND (ref, 1)),
  				 fold_convert (itype, delta));
*************** try_move_mult_to_index (enum tree_code c
*** 6991,6997 ****
        pos = TREE_OPERAND (pos, 0);
      }
  
!   TREE_OPERAND (pos, 1) = fold_build2 (code, itype,
  				       fold_convert (itype,
  						     TREE_OPERAND (pos, 1)),
  				       fold_convert (itype, delta));
--- 7008,7014 ----
        pos = TREE_OPERAND (pos, 0);
      }
  
!   TREE_OPERAND (pos, 1) = fold_build2 (PLUS_EXPR, itype,
  				       fold_convert (itype,
  						     TREE_OPERAND (pos, 1)),
  				       fold_convert (itype, delta));
*************** fold_to_nonsharp_ineq_using_bound (tree 
*** 7037,7045 ****
    if (TREE_TYPE (a1) != typea)
      return NULL_TREE;
  
!   diff = fold_build2 (MINUS_EXPR, typea, a1, a);
!   if (!integer_onep (diff))
!     return NULL_TREE;
  
    return fold_build2 (GE_EXPR, type, a, y);
  }
--- 7054,7074 ----
    if (TREE_TYPE (a1) != typea)
      return NULL_TREE;
  
!   if (POINTER_TYPE_P (typea))
!     {
!       /* Convert the pointer types into integer before taking the difference.  */
!       tree ta = fold_convert (ssizetype, a);
!       tree ta1 = fold_convert (ssizetype, a1);
!       diff = fold_binary (MINUS_EXPR, ssizetype, ta1, ta);
!       if (!diff || !integer_onep (diff))
!         return NULL_TREE;
!     }
!   else
!     {
!       diff = fold_binary (MINUS_EXPR, typea, a1, a);
!       if (!diff || !integer_onep (diff))
!         return NULL_TREE;
!     }
  
    return fold_build2 (GE_EXPR, type, a, y);
  }
*************** fold_unary (enum tree_code code, tree ty
*** 7830,7840 ****
  	    }
  	}
  
!       /* Convert (T1)(X op Y) into ((T1)X op (T1)Y), for pointer type,
           when one of the new casts will fold away. Conservatively we assume
! 	 that this happens when X or Y is NOP_EXPR or Y is INTEGER_CST.  */
!       if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (arg0))
! 	  && BINARY_CLASS_P (arg0)
  	  && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
  	      || TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
  	      || TREE_CODE (TREE_OPERAND (arg0, 1)) == NOP_EXPR))
--- 7859,7869 ----
  	    }
  	}
  
!       /* Convert (T1)(X p+ Y) into ((T1)X p+ Y), for pointer type,
           when one of the new casts will fold away. Conservatively we assume
! 	 that this happens when X or Y is NOP_EXPR or Y is INTEGER_CST. */
!       if (POINTER_TYPE_P (type)
! 	  && TREE_CODE (arg0) == POINTER_PLUS_EXPR
  	  && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
  	      || TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
  	      || TREE_CODE (TREE_OPERAND (arg0, 1)) == NOP_EXPR))
*************** fold_unary (enum tree_code code, tree ty
*** 7843,7849 ****
  	  tree arg01 = TREE_OPERAND (arg0, 1);
  
  	  return fold_build2 (TREE_CODE (arg0), type, fold_convert (type, arg00),
! 			      fold_convert (type, arg01));
  	}
  
        /* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types
--- 7872,7878 ----
  	  tree arg01 = TREE_OPERAND (arg0, 1);
  
  	  return fold_build2 (TREE_CODE (arg0), type, fold_convert (type, arg00),
! 			      fold_convert (sizetype, arg01));
  	}
  
        /* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types
*************** fold_binary (enum tree_code code, tree t
*** 9066,9072 ****
--- 9095,9162 ----
  
    switch (code)
      {
+     case POINTER_PLUS_EXPR:
+       /* 0 +p index -> (type)index */
+       if (integer_zerop (arg0))
+ 	return non_lvalue (fold_convert (type, arg1));
+ 
+       /* PTR +p 0 -> PTR */
+       if (integer_zerop (arg1))
+ 	return non_lvalue (fold_convert (type, arg0));
+ 
+       /* INT +p INT -> (PTR)(INT + INT), this happens because of stripping types. */
+       if (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
+ 	   && INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+         return fold_convert (type, fold_build2 (PLUS_EXPR, sizetype,
+ 						fold_convert (sizetype, arg1),
+ 						fold_convert (sizetype, arg0)));
+ 
+       /* index +p PTR -> PTR +p index */
+       if (POINTER_TYPE_P (TREE_TYPE (arg1))
+ 	  && INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+         return fold_build2 (POINTER_PLUS_EXPR, type,
+ 	                    fold_convert (type, arg1), fold_convert (sizetype, arg0));
+ 
+       /* (PTR +p B) +p A -> PTR +p (B + A) */
+       if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
+ 	{
+ 	  tree inner;
+ 	  tree arg01 = fold_convert (sizetype, TREE_OPERAND (arg0, 1));
+ 	  tree arg00 = TREE_OPERAND (arg0, 0);
+ 	  inner = fold_build2 (PLUS_EXPR, sizetype, arg01, fold_convert (sizetype, arg1));
+ 	  return fold_build2 (POINTER_PLUS_EXPR, type, arg00, inner);
+ 	}
+ 
+       /* PTR_CST +p CST -> CST1 */
+       if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
+ 	return fold_build2 (PLUS_EXPR, type, arg0, fold_convert (type, arg1));
+ 
+      /* Try replacing &a[i1] +p c * i2 with &a[i1 + i2], if c is step
+ 	of the array.  Loop optimizer sometimes produce this type of
+ 	expressions.  */
+       if (TREE_CODE (arg0) == ADDR_EXPR)
+ 	{
+ 	  tem = try_move_mult_to_index (arg0, fold_convert (sizetype, arg1));
+ 	  if (tem)
+ 	    return fold_convert (type, tem);
+ 	}
+ 
+       return NULL_TREE;
      case PLUS_EXPR:
+       /* PTR + INT -> (INT)(PTR p+ INT) */
+       if (POINTER_TYPE_P (TREE_TYPE (arg0))
+ 	  && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
+ 	return fold_convert (type, fold_build2 (POINTER_PLUS_EXPR,
+ 						TREE_TYPE (arg0),
+ 						arg0,
+ 						fold_convert (sizetype, arg1)));
+       /* INT + PTR -> (INT)(PTR p+ INT) */
+       if (POINTER_TYPE_P (TREE_TYPE (arg1))
+ 	  && INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+ 	return fold_convert (type, fold_build2 (POINTER_PLUS_EXPR,
+ 						TREE_TYPE (arg1),
+ 						arg1,
+ 						fold_convert (sizetype, arg0)));
        /* A + (-B) -> A - B */
        if (TREE_CODE (arg1) == NEGATE_EXPR)
  	return fold_build2 (MINUS_EXPR, type,
*************** fold_binary (enum tree_code code, tree t
*** 9173,9194 ****
  						 fold_convert (type,
  							       parg1)));
  	    }
- 
- 	  /* Try replacing &a[i1] + c * i2 with &a[i1 + i2], if c is step
- 	     of the array.  Loop optimizer sometimes produce this type of
- 	     expressions.  */
- 	  if (TREE_CODE (arg0) == ADDR_EXPR)
- 	    {
- 	      tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
- 	      if (tem)
- 		return fold_convert (type, tem);
- 	    }
- 	  else if (TREE_CODE (arg1) == ADDR_EXPR)
- 	    {
- 	      tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
- 	      if (tem)
- 		return fold_convert (type, tem);
- 	    }
  	}
        else
  	{
--- 9263,9268 ----
*************** fold_binary (enum tree_code code, tree t
*** 9465,9470 ****
--- 9539,9569 ----
        return NULL_TREE;
  
      case MINUS_EXPR:
+       /* Pointer simplifications for subtraction, simple reassiocations. */
+       if (POINTER_TYPE_P (TREE_TYPE (arg1)) && POINTER_TYPE_P (TREE_TYPE (arg0)))
+ 	{
+ 	  /* (PTR0 p+ A) - (PTR1 p+ B) -> (PTR0 - PTR1) + (A - B) */
+ 	  if (TREE_CODE (arg0) == POINTER_PLUS_EXPR
+ 	      && TREE_CODE (arg1) == POINTER_PLUS_EXPR)
+ 	    {
+ 	      tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
+ 	      tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
+ 	      tree arg10 = fold_convert (type, TREE_OPERAND (arg1, 0));
+ 	      tree arg11 = fold_convert (type, TREE_OPERAND (arg1, 1));
+ 	      return fold_build2 (PLUS_EXPR, type,
+ 				  fold_build2 (MINUS_EXPR, type, arg00, arg10),
+ 				  fold_build2 (MINUS_EXPR, type, arg01, arg11));
+ 	    }
+ 	  /* (PTR0 p+ A) - PTR1 -> (PTR0 - PTR1) + A, assuming PTR0 - PTR1 simplifies. */
+ 	  else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
+ 	    {
+ 	      tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
+ 	      tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
+ 	      tree tmp = fold_binary (MINUS_EXPR, type, arg00, fold_convert (type, arg1));
+ 	      if (tmp)
+ 	        return fold_build2 (PLUS_EXPR, type, tmp, arg01);
+ 	    }
+ 	}
        /* A - (-B) -> A + B */
        if (TREE_CODE (arg1) == NEGATE_EXPR)
  	return fold_build2 (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0));
*************** fold_binary (enum tree_code code, tree t
*** 9634,9649 ****
  	    }
  	}
  
-       /* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step
- 	 of the array.  Loop optimizer sometimes produce this type of
- 	 expressions.  */
-       if (TREE_CODE (arg0) == ADDR_EXPR)
- 	{
- 	  tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
- 	  if (tem)
- 	    return fold_convert (type, tem);
- 	}
- 
        if (flag_unsafe_math_optimizations
  	  && (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR)
  	  && (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR)
--- 9733,9738 ----
*************** tree_expr_nonnegative_warnv_p (tree t, b
*** 13231,13236 ****
--- 13320,13326 ----
      case REAL_CST:
        return ! REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
  
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        if (FLOAT_TYPE_P (TREE_TYPE (t)))
  	return (tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 0),
*************** tree_expr_nonzero_warnv_p (tree t, bool 
*** 13586,13591 ****
--- 13676,13682 ----
      case INTEGER_CST:
        return !integer_zerop (t);
  
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        if (TYPE_OVERFLOW_UNDEFINED (type))
  	{
*************** fold_indirect_ref_1 (tree type, tree op0
*** 14178,14184 ****
      }
  
    /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
!   if (TREE_CODE (sub) == PLUS_EXPR
        && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
      {
        tree op00 = TREE_OPERAND (sub, 0);
--- 14269,14275 ----
      }
  
    /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
!   if (TREE_CODE (sub) == POINTER_PLUS_EXPR
        && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
      {
        tree op00 = TREE_OPERAND (sub, 0);
Index: tree-chrec.c
===================================================================
*** tree-chrec.c	(.../trunk/gcc)	(revision 125658)
--- tree-chrec.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** chrec_fold_plus_poly_poly (enum tree_cod
*** 101,112 ****
    tree left, right;
    struct loop *loop0 = get_chrec_loop (poly0);
    struct loop *loop1 = get_chrec_loop (poly1);
  
    gcc_assert (poly0);
    gcc_assert (poly1);
    gcc_assert (TREE_CODE (poly0) == POLYNOMIAL_CHREC);
    gcc_assert (TREE_CODE (poly1) == POLYNOMIAL_CHREC);
!   gcc_assert (chrec_type (poly0) == chrec_type (poly1));
    gcc_assert (type == chrec_type (poly0));
    
    /*
--- 101,116 ----
    tree left, right;
    struct loop *loop0 = get_chrec_loop (poly0);
    struct loop *loop1 = get_chrec_loop (poly1);
+   tree rtype = code == POINTER_PLUS_EXPR ? sizetype : type;
  
    gcc_assert (poly0);
    gcc_assert (poly1);
    gcc_assert (TREE_CODE (poly0) == POLYNOMIAL_CHREC);
    gcc_assert (TREE_CODE (poly1) == POLYNOMIAL_CHREC);
!   if (POINTER_TYPE_P (chrec_type (poly0)))
!     gcc_assert (chrec_type (poly1) == sizetype);
!   else
!     gcc_assert (chrec_type (poly0) == chrec_type (poly1));
    gcc_assert (type == chrec_type (poly0));
    
    /*
*************** chrec_fold_plus_poly_poly (enum tree_cod
*** 115,121 ****
      {a, +, b}_x + {c, +, d}_x  ->  {a+c, +, b+d}_x.  */
    if (flow_loop_nested_p (loop0, loop1))
      {
!       if (code == PLUS_EXPR)
  	return build_polynomial_chrec 
  	  (CHREC_VARIABLE (poly1), 
  	   chrec_fold_plus (type, poly0, CHREC_LEFT (poly1)),
--- 119,125 ----
      {a, +, b}_x + {c, +, d}_x  ->  {a+c, +, b+d}_x.  */
    if (flow_loop_nested_p (loop0, loop1))
      {
!       if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
  	return build_polynomial_chrec 
  	  (CHREC_VARIABLE (poly1), 
  	   chrec_fold_plus (type, poly0, CHREC_LEFT (poly1)),
*************** chrec_fold_plus_poly_poly (enum tree_cod
*** 132,138 ****
    
    if (flow_loop_nested_p (loop1, loop0))
      {
!       if (code == PLUS_EXPR)
  	return build_polynomial_chrec 
  	  (CHREC_VARIABLE (poly0), 
  	   chrec_fold_plus (type, CHREC_LEFT (poly0), poly1),
--- 136,142 ----
    
    if (flow_loop_nested_p (loop1, loop0))
      {
!       if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
  	return build_polynomial_chrec 
  	  (CHREC_VARIABLE (poly0), 
  	   chrec_fold_plus (type, CHREC_LEFT (poly0), poly1),
*************** chrec_fold_plus_poly_poly (enum tree_cod
*** 148,159 ****
       do not belong to the same loop nest.  */
    gcc_assert (loop0 == loop1);
  
!   if (code == PLUS_EXPR)
      {
        left = chrec_fold_plus 
  	(type, CHREC_LEFT (poly0), CHREC_LEFT (poly1));
        right = chrec_fold_plus 
! 	(type, CHREC_RIGHT (poly0), CHREC_RIGHT (poly1));
      }
    else
      {
--- 152,163 ----
       do not belong to the same loop nest.  */
    gcc_assert (loop0 == loop1);
  
!   if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
      {
        left = chrec_fold_plus 
  	(type, CHREC_LEFT (poly0), CHREC_LEFT (poly1));
        right = chrec_fold_plus 
! 	(rtype, CHREC_RIGHT (poly0), CHREC_RIGHT (poly1));
      }
    else
      {
*************** static tree
*** 264,269 ****
--- 268,275 ----
  chrec_fold_plus_1 (enum tree_code code, tree type, 
  		   tree op0, tree op1)
  {
+   tree op1_type = code == POINTER_PLUS_EXPR ? sizetype : type;
+ 
    if (automatically_generated_chrec_p (op0)
        || automatically_generated_chrec_p (op1))
      return chrec_fold_automatically_generated_operands (op0, op1);
*************** chrec_fold_plus_1 (enum tree_code code, 
*** 277,283 ****
  	  return chrec_fold_plus_poly_poly (code, type, op0, op1);
  
  	default:
! 	  if (code == PLUS_EXPR)
  	    return build_polynomial_chrec 
  	      (CHREC_VARIABLE (op0), 
  	       chrec_fold_plus (type, CHREC_LEFT (op0), op1),
--- 283,289 ----
  	  return chrec_fold_plus_poly_poly (code, type, op0, op1);
  
  	default:
! 	  if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
  	    return build_polynomial_chrec 
  	      (CHREC_VARIABLE (op0), 
  	       chrec_fold_plus (type, CHREC_LEFT (op0), op1),
*************** chrec_fold_plus_1 (enum tree_code code, 
*** 293,299 ****
        switch (TREE_CODE (op1))
  	{
  	case POLYNOMIAL_CHREC:
! 	  if (code == PLUS_EXPR)
  	    return build_polynomial_chrec 
  	      (CHREC_VARIABLE (op1), 
  	       chrec_fold_plus (type, op0, CHREC_LEFT (op1)),
--- 299,305 ----
        switch (TREE_CODE (op1))
  	{
  	case POLYNOMIAL_CHREC:
! 	  if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
  	    return build_polynomial_chrec 
  	      (CHREC_VARIABLE (op1), 
  	       chrec_fold_plus (type, op0, CHREC_LEFT (op1)),
*************** chrec_fold_plus_1 (enum tree_code code, 
*** 317,323 ****
  	    else if (size < PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
  	      return fold_build2 (code, type,
  				  fold_convert (type, op0),
! 				  fold_convert (type, op1));
  	    else
  	      return chrec_dont_know;
  	  }
--- 323,329 ----
  	    else if (size < PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
  	      return fold_build2 (code, type,
  				  fold_convert (type, op0),
! 				  fold_convert (op1_type, op1));
  	    else
  	      return chrec_dont_know;
  	  }
*************** chrec_fold_plus (tree type, 
*** 332,347 ****
  		 tree op0,
  		 tree op1)
  {
    if (automatically_generated_chrec_p (op0)
        || automatically_generated_chrec_p (op1))
      return chrec_fold_automatically_generated_operands (op0, op1);
  
    if (integer_zerop (op0))
!     return op1;
    if (integer_zerop (op1))
!     return op0;
    
!   return chrec_fold_plus_1 (PLUS_EXPR, type, op0, op1);
  }
  
  /* Fold the subtraction of two chrecs.  */
--- 338,359 ----
  		 tree op0,
  		 tree op1)
  {
+   enum tree_code code;
    if (automatically_generated_chrec_p (op0)
        || automatically_generated_chrec_p (op1))
      return chrec_fold_automatically_generated_operands (op0, op1);
  
    if (integer_zerop (op0))
!     return chrec_convert (type, op1, NULL_TREE);
    if (integer_zerop (op1))
!     return chrec_convert (type, op0, NULL_TREE);
! 
!   if (POINTER_TYPE_P (type))
!     code = POINTER_PLUS_EXPR;
!   else
!     code = PLUS_EXPR;
    
!   return chrec_fold_plus_1 (code, type, op0, op1);
  }
  
  /* Fold the subtraction of two chrecs.  */
*************** chrec_apply (unsigned var,
*** 566,573 ****
    if (evolution_function_is_affine_p (chrec))
      {
        /* "{a, +, b} (x)"  ->  "a + b*x".  */
!       x = chrec_convert (type, x, NULL_TREE);
!       res = chrec_fold_multiply (type, CHREC_RIGHT (chrec), x);
        if (!integer_zerop (CHREC_LEFT (chrec)))
  	res = chrec_fold_plus (type, CHREC_LEFT (chrec), res);
      }
--- 578,585 ----
    if (evolution_function_is_affine_p (chrec))
      {
        /* "{a, +, b} (x)"  ->  "a + b*x".  */
!       x = chrec_convert_rhs (type, x, NULL_TREE);
!       res = chrec_fold_multiply (TREE_TYPE (x), CHREC_RIGHT (chrec), x);
        if (!integer_zerop (CHREC_LEFT (chrec)))
  	res = chrec_fold_plus (type, CHREC_LEFT (chrec), res);
      }
*************** reset_evolution_in_loop (unsigned loop_n
*** 767,773 ****
  {
    struct loop *loop = get_loop (loop_num);
  
!   gcc_assert (chrec_type (chrec) == chrec_type (new_evol));
  
    if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
        && flow_loop_nested_p (loop, get_chrec_loop (chrec)))
--- 779,788 ----
  {
    struct loop *loop = get_loop (loop_num);
  
!   if (POINTER_TYPE_P (chrec_type (chrec)))
!     gcc_assert (sizetype == chrec_type (new_evol));
!   else
!     gcc_assert (chrec_type (chrec) == chrec_type (new_evol));
  
    if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
        && flow_loop_nested_p (loop, get_chrec_loop (chrec)))
*************** convert_affine_scev (struct loop *loop, 
*** 1119,1124 ****
--- 1134,1140 ----
    bool enforce_overflow_semantics;
    bool must_check_src_overflow, must_check_rslt_overflow;
    tree new_base, new_step;
+   tree step_type = POINTER_TYPE_P (type) ? sizetype : type;
  
    /* If we cannot perform arithmetic in TYPE, avoid creating an scev.  */
    if (avoid_arithmetics_in_type_p (type))
*************** convert_affine_scev (struct loop *loop, 
*** 1188,1197 ****
       [100, +, 255] with values 100, 355, ...; the sign-extension is 
       performed by default when CT is signed.  */
    new_step = *step;
!   if (TYPE_PRECISION (type) > TYPE_PRECISION (ct) && TYPE_UNSIGNED (ct))
      new_step = chrec_convert_1 (signed_type_for (ct), new_step, at_stmt,
  				use_overflow_semantics);
!   new_step = chrec_convert_1 (type, new_step, at_stmt, use_overflow_semantics);
  
    if (automatically_generated_chrec_p (new_base)
        || automatically_generated_chrec_p (new_step))
--- 1204,1213 ----
       [100, +, 255] with values 100, 355, ...; the sign-extension is 
       performed by default when CT is signed.  */
    new_step = *step;
!   if (TYPE_PRECISION (step_type) > TYPE_PRECISION (ct) && TYPE_UNSIGNED (ct))
      new_step = chrec_convert_1 (signed_type_for (ct), new_step, at_stmt,
  				use_overflow_semantics);
!   new_step = chrec_convert_1 (step_type, new_step, at_stmt, use_overflow_semantics);
  
    if (automatically_generated_chrec_p (new_base)
        || automatically_generated_chrec_p (new_step))
*************** convert_affine_scev (struct loop *loop, 
*** 1209,1214 ****
--- 1225,1240 ----
  }
  

  
+ /* Convert CHREC for the right hand side of a CREC.
+    The increment for a pointer type is always sizetype.  */
+ tree 
+ chrec_convert_rhs (tree type, tree chrec, tree at_stmt)
+ {
+   if (POINTER_TYPE_P (type))
+    type = sizetype;
+   return chrec_convert (type, chrec, at_stmt);
+ }
+ 
  /* Convert CHREC to TYPE.  When the analyzer knows the context in
     which the CHREC is built, it sets AT_STMT to the statement that
     contains the definition of the analyzed variable, otherwise the
*************** keep_cast:
*** 1306,1312 ****
  tree
  chrec_convert_aggressive (tree type, tree chrec)
  {
!   tree inner_type, left, right, lc, rc;
  
    if (automatically_generated_chrec_p (chrec)
        || TREE_CODE (chrec) != POLYNOMIAL_CHREC)
--- 1332,1338 ----
  tree
  chrec_convert_aggressive (tree type, tree chrec)
  {
!   tree inner_type, left, right, lc, rc, rtype;
  
    if (automatically_generated_chrec_p (chrec)
        || TREE_CODE (chrec) != POLYNOMIAL_CHREC)
*************** chrec_convert_aggressive (tree type, tre
*** 1320,1333 ****
    if (avoid_arithmetics_in_type_p (type))
      return NULL_TREE;
  
    left = CHREC_LEFT (chrec);
    right = CHREC_RIGHT (chrec);
    lc = chrec_convert_aggressive (type, left);
    if (!lc)
      lc = chrec_convert (type, left, NULL_TREE);
!   rc = chrec_convert_aggressive (type, right);
    if (!rc)
!     rc = chrec_convert (type, right, NULL_TREE);
   
    return build_polynomial_chrec (CHREC_VARIABLE (chrec), lc, rc);
  }
--- 1346,1361 ----
    if (avoid_arithmetics_in_type_p (type))
      return NULL_TREE;
  
+   rtype = POINTER_TYPE_P (type) ? sizetype : type;
+ 
    left = CHREC_LEFT (chrec);
    right = CHREC_RIGHT (chrec);
    lc = chrec_convert_aggressive (type, left);
    if (!lc)
      lc = chrec_convert (type, left, NULL_TREE);
!   rc = chrec_convert_aggressive (rtype, right);
    if (!rc)
!     rc = chrec_convert (rtype, right, NULL_TREE);
   
    return build_polynomial_chrec (CHREC_VARIABLE (chrec), lc, rc);
  }
Index: tree-chrec.h
===================================================================
*** tree-chrec.h	(.../trunk/gcc)	(revision 125658)
--- tree-chrec.h	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** extern tree chrec_fold_plus (tree, tree,
*** 59,64 ****
--- 59,65 ----
  extern tree chrec_fold_minus (tree, tree, tree);
  extern tree chrec_fold_multiply (tree, tree, tree);
  extern tree chrec_convert (tree, tree, tree);
+ extern tree chrec_convert_rhs (tree, tree, tree);
  extern tree chrec_convert_aggressive (tree, tree);
  
  /* Operations.  */
*************** build_polynomial_chrec (unsigned loop_nu
*** 108,114 ****
        || right == chrec_dont_know)
      return chrec_dont_know;
  
!   gcc_assert (TREE_TYPE (left) == TREE_TYPE (right));
  
    if (chrec_zerop (right))
      return left;
--- 109,118 ----
        || right == chrec_dont_know)
      return chrec_dont_know;
  
!   if (POINTER_TYPE_P (TREE_TYPE (left)))
!     gcc_assert (sizetype == TREE_TYPE (right));
!   else
!     gcc_assert (TREE_TYPE (left) == TREE_TYPE (right));
  
    if (chrec_zerop (right))
      return left;
Index: testsuite/gcc.c-torture/compile/20070520-1.c
===================================================================
*** testsuite/gcc.c-torture/compile/20070520-1.c	(.../trunk/gcc)	(revision 0)
--- testsuite/gcc.c-torture/compile/20070520-1.c	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,35 ----
+ typedef unsigned char uint8_t;
+ extern uint8_t ff_cropTbl[256 + 2 * 1024];
+ 
+ void ff_pred8x8_plane_c(uint8_t *src, int stride){
+   int j, k;
+   int a;
+   uint8_t *cm = ff_cropTbl + 1024;
+   const uint8_t * const src0 = src+3-stride;
+   const uint8_t *src1 = src+4*stride-1;
+   const uint8_t *src2 = src1-2*stride;
+   int H = src0[1] - src0[-1];
+   int V = src1[0] - src2[ 0];
+   for(k=2; k<=4; ++k) {
+     src1 += stride; src2 -= stride;
+     H += k*(src0[k] - src0[-k]);
+     V += k*(src1[0] - src2[ 0]);
+   }
+   H = ( 17*H+16 ) >> 5;
+   V = ( 17*V+16 ) >> 5;
+ 
+   a = 16*(src1[0] + src2[8]+1) - 3*(V+H);
+   for(j=8; j>0; --j) {
+     int b = a;
+     a += V;
+     src[0] = cm[ (b ) >> 5 ];
+     src[1] = cm[ (b+ H) >> 5 ];
+     src[2] = cm[ (b+2*H) >> 5 ];
+     src[3] = cm[ (b+3*H) >> 5 ];
+     src[4] = cm[ (b+4*H) >> 5 ];
+     src[5] = cm[ (b+5*H) >> 5 ];
+     src[6] = cm[ (b+6*H) >> 5 ];
+     src[7] = cm[ (b+7*H) >> 5 ];
+     src += stride;
+   }
+ }
Index: testsuite/gcc.c-torture/compile/20070529-1.c
===================================================================
*** testsuite/gcc.c-torture/compile/20070529-1.c	(.../trunk/gcc)	(revision 0)
--- testsuite/gcc.c-torture/compile/20070529-1.c	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,16 ----
+ /* ICE in chrec_fold_plus_poly_poly. */
+ 
+ typedef unsigned short __u16;
+ typedef unsigned int u32;
+ typedef __u16 __be16;
+ struct hfs_extent {
+  __be16 count;
+ };
+ int hfs_free_fork( int type)
+ {
+  u32 total_blocks, blocks, start;
+  struct hfs_extent *extent;
+  int res, i;
+  for (i = 0; i < 3; extent++, i++)
+   blocks += __fswab16((( __u16)(__be16)(extent[i].count)));
+ }
Index: testsuite/gcc.c-torture/compile/20070529-2.c
===================================================================
*** testsuite/gcc.c-torture/compile/20070529-2.c	(.../trunk/gcc)	(revision 0)
--- testsuite/gcc.c-torture/compile/20070529-2.c	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,11 ----
+ void xfs_dir2_grow_inode(void)
+ {
+  int map;
+  int *mapp;
+  int nmap;
+  mapp = ↦
+  if (nmap == 0 )
+   mapp = ((void *)0);
+  if (mapp != &map)
+   kmem_free(mapp);
+ }
Index: testsuite/gcc.c-torture/compile/20070603-1.c
===================================================================
*** testsuite/gcc.c-torture/compile/20070603-1.c	(.../trunk/gcc)	(revision 0)
--- testsuite/gcc.c-torture/compile/20070603-1.c	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,9 ----
+ 
+ int f(_Complex double *a, unsigned int n)
+ {
+   unsigned int i;
+   for(i = 0; i< n; i++)
+     {
+       a[i] = __real__ a[i+1] + __real__ a[i];
+     }
+ }
Index: testsuite/gcc.c-torture/compile/20070531-1.c
===================================================================
*** testsuite/gcc.c-torture/compile/20070531-1.c	(.../trunk/gcc)	(revision 0)
--- testsuite/gcc.c-torture/compile/20070531-1.c	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,11 ----
+ /* MIN_EXPR/MAX_EXPR caused an ICE in VRP. */
+ int *f(int *a, int *b)
+ {
+  *a = 1;
+  *b = 2;
+  int *c = a < b ? a : b;
+  if (c)
+    return c;
+  else
+    return a;
+ }
Index: testsuite/gcc.c-torture/compile/20070603-2.c
===================================================================
*** testsuite/gcc.c-torture/compile/20070603-2.c	(.../trunk/gcc)	(revision 0)
--- testsuite/gcc.c-torture/compile/20070603-2.c	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,9 ----
+ typedef _Complex double ar[];
+ int f(ar *a, unsigned int n)
+ {
+   unsigned int i;
+   for(i = 0; i< n; i++)
+     {
+       (*a)[i*4] = __real__ (*a)[(i+1)*4] + __real__ (*a)[i*4];
+     }
+ }
Index: testsuite/gcc.c-torture/compile/20070531-2.c
===================================================================
*** testsuite/gcc.c-torture/compile/20070531-2.c	(.../trunk/gcc)	(revision 0)
--- testsuite/gcc.c-torture/compile/20070531-2.c	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,6 ----
+ int f(void)
+ {
+   int *a = 0;
+   for(a = 0; a < (int*)32767;a++)
+    ;
+ }
Index: testsuite/gcc.c-torture/compile/20070605-1.c
===================================================================
*** testsuite/gcc.c-torture/compile/20070605-1.c	(.../trunk/gcc)	(revision 0)
--- testsuite/gcc.c-torture/compile/20070605-1.c	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,10 ----
+ quantize_fs_dither (unsigned width, short *errorptr, int dir)
+ {
+   short bpreverr;
+   unsigned col;
+   for (col = width; col > 0; col--) 
+     errorptr += dir;
+   errorptr[0] = (short) bpreverr;
+ }
+ 
+ 
Index: testsuite/gcc.dg/max-1.c
===================================================================
*** testsuite/gcc.dg/max-1.c	(.../trunk/gcc)	(revision 125658)
--- testsuite/gcc.dg/max-1.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** void f(long a, long b)
*** 24,33 ****
     fff[i] = a;
  }
  
  int main(void)
  {
    int i;
-   long a = 10;
    f((long)(&a)-1,0);
    for(i = 0;i<10;i++)
     if (fff[i]!=10)
--- 24,36 ----
     fff[i] = a;
  }
  
+ /* The variable a cannot be a local variable as we get better aliasing
+    now and decide that the store to a is dead.  The better aliasing comes
+    from better representation of pointer arthimetic. */
+ long a = 10;
  int main(void)
  {
    int i;
    f((long)(&a)-1,0);
    for(i = 0;i<10;i++)
     if (fff[i]!=10)
Index: testsuite/gcc.dg/tree-ssa/20030815-1.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/20030815-1.c	(.../trunk/gcc)	(revision 125658)
--- testsuite/gcc.dg/tree-ssa/20030815-1.c	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 1,43 ****
- /* { dg-do compile } */
- /* { dg-options "-O1 -fdump-tree-dom3" } */
- 
- extern void abort (void);
- typedef unsigned int size_t;
- struct rtx_def;
- typedef struct rtx_def *rtx;
- typedef union varray_data_tag
- {
-   struct reg_info_def *reg[1];
- } varray_data;
- struct varray_head_tag
- {
-   size_t num_elements;
-   varray_data data;
- };
- typedef struct varray_head_tag *varray_type;
- typedef struct reg_info_def
- {
- } reg_info;
- extern varray_type reg_n_info;
- static rtx *reg_base_value;
- static rtx *new_reg_base_value;
- 
- rtx
- blah (unsigned int regno)
- {
-   if (new_reg_base_value[regno] && ((*(
- 					{
- 					if (regno >=
- 					    reg_n_info->
- 					    num_elements)
- 					abort ();
- 					&reg_n_info->data.reg[regno];}
- 				     ))))
-     return reg_base_value[regno];
- }
- 
- /* If we have more than 1 cast to a struct rtx_def * *, then we failed to
-    eliminate some useless typecasting.  The first type cast is needed
-    to convert the unsigned int regno parameter into a struct rtx_def **.  */
- /* { dg-final { scan-tree-dump-times "\\(struct rtx_def \\* \\*\\)" 1 "dom3"} } */
- /* { dg-final { cleanup-tree-dump "dom3" } } */
--- 0 ----
Index: testsuite/gcc.dg/tree-ssa/ssa-pre-8.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/ssa-pre-8.c	(.../trunk/gcc)	(revision 125658)
--- testsuite/gcc.dg/tree-ssa/ssa-pre-8.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** foo (__SIZE_TYPE__ i, struct s *array)
*** 16,21 ****
      }
    return 0;
  }
! /* We should eliminate two address calculations, one cast, and one load.  */
! /* { dg-final { scan-tree-dump-times "Eliminated: 4" 1 "fre"} } */
  /* { dg-final { cleanup-tree-dump "fre" } } */
--- 16,23 ----
      }
    return 0;
  }
! /* We should eliminate two address calculations, and one load.  */
! /* We used to eliminate a cast but that was before POINTER_PLUS_EXPR
!    was added.  */
! /* { dg-final { scan-tree-dump-times "Eliminated: 3" 1 "fre"} } */
  /* { dg-final { cleanup-tree-dump "fre" } } */
Index: testsuite/gcc.dg/vect/vect-106.c
===================================================================
*** testsuite/gcc.dg/vect/vect-106.c	(.../trunk/gcc)	(revision 125658)
--- testsuite/gcc.dg/vect/vect-106.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** int main1 () {
*** 17,25 ****
  
    p1 = p; q1 = q;
  
!   /* Not vectorizable: because of the redundant cast (caused by ponter
!      arithmetics), alias analysis fails to distinguish between 
!      the pointers.  */
    for (i = 0; i < N; i++)
      {
        *(q + i) = a[i];
--- 17,25 ----
  
    p1 = p; q1 = q;
  
!   /* Vectorizable, before pointer plus we would get a redundant cast
!      (caused by ponter arithmetics), alias analysis fails to distinguish
!      between the pointers.  */
    for (i = 0; i < N; i++)
      {
        *(q + i) = a[i];
*************** int main (void)
*** 67,73 ****
    return main1 ();
  }
  
! /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
! /* { dg-final { scan-tree-dump-times "can't determine dependence" 1 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */
  
--- 67,72 ----
    return main1 ();
  }
  
! /* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */
  
Index: testsuite/ChangeLog.ptr
===================================================================
*** testsuite/ChangeLog.ptr	(.../trunk/gcc)	(revision 0)
--- testsuite/ChangeLog.ptr	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,53 ----
+ 2007-06-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	PR tree-opt/32225
+ 	* gcc.c-torture/compile/20070605-1.c: New test.
+ 
+ 2007-06-03  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* gcc.c-torture/compile/20070603-1.c: New testcase.
+ 	* gcc.c-torture/compile/20070603-2.c: New testcase.
+ 
+ 2007-05-31  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* gcc.c-torture/compile/20070531-1.c: New test.
+ 
+ 	PR tree-opt/32167
+ 	* gcc.c-torture/compile/20070531-2.c: New test.
+ 
+ 2007-05-28  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	PR tree-opt/32144
+ 	* gcc.c-torture/compile/20070529-1.c: New test.
+ 
+ 	PR tree-opt/32145
+ 	* gcc.c-torture/compile/20070529-2.c: New test.
+ 
+ 2007-05-21  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	PR tree-opt/32015
+ 	* gcc.c-torture/compile/20070520-1.c: New test.
+ 
+ 2007-05-12  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	 * g++.dg/ext/java-1.C: New test.
+ 
+ 2007-05-09  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* gcc.dg/vect/vect-106.c: We are now able to vectorize two
+ 	loops instead of one. Remove the "can't determine dependence"
+ 	check.
+ 
+ 2007-05-04  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* gcc.dg/tree-ssa/20030815-1.c: Remove testcase which is no longer
+ 	needed as the cast is gone in the first place.
+ 
+ 2007-05-04  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* gcc.dg/max-1.c: Change local variable a to be a global one.
+ 
+ 2006-11-23  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* gcc.dg/tree-ssa/ssa-pre-8.c: Update testcase since we don't
+ 	have a cast which is PREd.
Index: testsuite/g++.dg/ext/java-1.C
===================================================================
*** testsuite/g++.dg/ext/java-1.C	(.../trunk/gcc)	(revision 0)
--- testsuite/g++.dg/ext/java-1.C	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,26 ----
+ // { dg-do compile }
+ // { dg-options "" }
+ // Test extern "java" and some throwing of the objects.
+ 
+ extern "Java"
+   namespace java
+   {
+     namespace lang
+     {
+       class Throwable;
+       class Class;
+   }
+ }
+ typedef class java::lang::Throwable* jthrowable;
+ typedef class java::lang::Class* jclass;
+ class java::lang::Throwable {
+ public:
+   static jclass class$;
+ };
+ int
+ _Jv_FindClassFromSignature ( )
+   try 
+     {
+     }
+   catch (java::lang::Throwable *ncdfe) {} 
+ 
Index: cp/typeck.c
===================================================================
*** cp/typeck.c	(.../trunk/gcc)	(revision 125658)
--- cp/typeck.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** get_member_function_from_ptrfunc (tree *
*** 2627,2634 ****
  	    return error_mark_node;
  	}
        /* ...and then the delta in the PMF.  */
!       instance_ptr = build2 (PLUS_EXPR, TREE_TYPE (instance_ptr),
! 			     instance_ptr, delta);
  
        /* Hand back the adjusted 'this' argument to our caller.  */
        *instance_ptrptr = instance_ptr;
--- 2627,2634 ----
  	    return error_mark_node;
  	}
        /* ...and then the delta in the PMF.  */
!       instance_ptr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (instance_ptr),
! 			     instance_ptr, fold_convert (sizetype, delta));
  
        /* Hand back the adjusted 'this' argument to our caller.  */
        *instance_ptrptr = instance_ptr;
*************** get_member_function_from_ptrfunc (tree *
*** 2639,2645 ****
        vtbl = build_indirect_ref (vtbl, NULL);
  
        /* Finally, extract the function pointer from the vtable.  */
!       e2 = fold_build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx);
        e2 = build_indirect_ref (e2, NULL);
        TREE_CONSTANT (e2) = 1;
        TREE_INVARIANT (e2) = 1;
--- 2639,2646 ----
        vtbl = build_indirect_ref (vtbl, NULL);
  
        /* Finally, extract the function pointer from the vtable.  */
!       e2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
! 			fold_convert (sizetype, idx));
        e2 = build_indirect_ref (e2, NULL);
        TREE_CONSTANT (e2) = 1;
        TREE_INVARIANT (e2) = 1;
*************** build_binary_op (enum tree_code code, tr
*** 3578,3586 ****
    /* If we're in a template, the only thing we need to know is the
       RESULT_TYPE.  */
    if (processing_template_decl)
!     return build2 (resultcode,
! 		   build_type ? build_type : result_type,
! 		   op0, op1);
  
    if (arithmetic_types_p)
      {
--- 3579,3595 ----
    /* If we're in a template, the only thing we need to know is the
       RESULT_TYPE.  */
    if (processing_template_decl)
!     {
!       /* Since the middle-end checks the type when doing a build2, we
! 	 need to build the tree in pieces.  This built tree will never
! 	 get out of the front-end as we replace it when instantiating
! 	 the template.  */
!       tree tmp = build2 (resultcode,
! 			 build_type ? build_type : result_type,
! 			 NULL_TREE, op1);
!       TREE_OPERAND (tmp, 0) = op0;
!       return tmp;
!     }
  
    if (arithmetic_types_p)
      {
Index: cp/init.c
===================================================================
*** cp/init.c	(.../trunk/gcc)	(revision 125658)
--- cp/init.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** expand_virtual_init (tree binfo, tree de
*** 786,792 ****
  
        /* Compute the value to use, when there's a VTT.  */
        vtt_parm = current_vtt_parm;
!       vtbl2 = build2 (PLUS_EXPR,
  		      TREE_TYPE (vtt_parm),
  		      vtt_parm,
  		      vtt_index);
--- 786,792 ----
  
        /* Compute the value to use, when there's a VTT.  */
        vtt_parm = current_vtt_parm;
!       vtbl2 = build2 (POINTER_PLUS_EXPR,
  		      TREE_TYPE (vtt_parm),
  		      vtt_parm,
  		      vtt_index);
*************** build_new_1 (tree placement, tree type, 
*** 1919,1932 ****
        tree cookie_ptr;
  
        /* Adjust so we're pointing to the start of the object.  */
!       data_addr = get_target_expr (build2 (PLUS_EXPR, full_pointer_type,
  					   alloc_node, cookie_size));
  
        /* Store the number of bytes allocated so that we can know how
  	 many elements to destroy later.  We use the last sizeof
  	 (size_t) bytes to store the number of elements.  */
!       cookie_ptr = build2 (MINUS_EXPR, build_pointer_type (sizetype),
! 			   data_addr, size_in_bytes (sizetype));
        cookie = build_indirect_ref (cookie_ptr, NULL);
  
        cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
--- 1919,1933 ----
        tree cookie_ptr;
  
        /* Adjust so we're pointing to the start of the object.  */
!       data_addr = get_target_expr (build2 (POINTER_PLUS_EXPR, full_pointer_type,
  					   alloc_node, cookie_size));
  
        /* Store the number of bytes allocated so that we can know how
  	 many elements to destroy later.  We use the last sizeof
  	 (size_t) bytes to store the number of elements.  */
!       cookie_ptr = build1 (NEGATE_EXPR, sizetype, size_in_bytes (sizetype));
!       cookie_ptr = build2 (POINTER_PLUS_EXPR, build_pointer_type (sizetype),
! 			   data_addr, cookie_ptr);
        cookie = build_indirect_ref (cookie_ptr, NULL);
  
        cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
*************** build_vec_delete_1 (tree base, tree maxi
*** 2301,2306 ****
--- 2302,2308 ----
       executing any other code in the loop.
       This is also the containing expression returned by this function.  */
    tree controller = NULL_TREE;
+   tree tmp;
  
    /* We should only have 1-D arrays here.  */
    gcc_assert (TREE_CODE (type) != ARRAY_TYPE);
*************** build_vec_delete_1 (tree base, tree maxi
*** 2314,2320 ****
  
    tbase = create_temporary_var (ptype);
    tbase_init = build_modify_expr (tbase, NOP_EXPR,
! 				  fold_build2 (PLUS_EXPR, ptype,
  					       base,
  					       virtual_size));
    DECL_REGISTER (tbase) = 1;
--- 2316,2322 ----
  
    tbase = create_temporary_var (ptype);
    tbase_init = build_modify_expr (tbase, NOP_EXPR,
! 				  fold_build2 (POINTER_PLUS_EXPR, ptype,
  					       base,
  					       virtual_size));
    DECL_REGISTER (tbase) = 1;
*************** build_vec_delete_1 (tree base, tree maxi
*** 2325,2333 ****
    body = build1 (EXIT_EXPR, void_type_node,
  		 build2 (EQ_EXPR, boolean_type_node, tbase,
  			 fold_convert (ptype, base)));
    body = build_compound_expr
      (body, build_modify_expr (tbase, NOP_EXPR,
! 			      build2 (MINUS_EXPR, ptype, tbase, size_exp)));
    body = build_compound_expr
      (body, build_delete (ptype, tbase, sfk_complete_destructor,
  			 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1));
--- 2327,2336 ----
    body = build1 (EXIT_EXPR, void_type_node,
  		 build2 (EQ_EXPR, boolean_type_node, tbase,
  			 fold_convert (ptype, base)));
+   tmp = build1 (NEGATE_EXPR, sizetype, size_exp);
    body = build_compound_expr
      (body, build_modify_expr (tbase, NOP_EXPR,
! 			      build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp)));
    body = build_compound_expr
      (body, build_delete (ptype, tbase, sfk_complete_destructor,
  			 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1));
*************** build_vec_delete (tree base, tree maxind
*** 3048,3057 ****
  	  base = TARGET_EXPR_SLOT (base_init);
  	}
        type = strip_array_types (TREE_TYPE (type));
!       cookie_addr = build2 (MINUS_EXPR,
  			    build_pointer_type (sizetype),
  			    base,
! 			    TYPE_SIZE_UNIT (sizetype));
        maxindex = build_indirect_ref (cookie_addr, NULL);
      }
    else if (TREE_CODE (type) == ARRAY_TYPE)
--- 3051,3061 ----
  	  base = TARGET_EXPR_SLOT (base_init);
  	}
        type = strip_array_types (TREE_TYPE (type));
!       cookie_addr = fold_build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (sizetype));
!       cookie_addr = build2 (POINTER_PLUS_EXPR,
  			    build_pointer_type (sizetype),
  			    base,
! 			    cookie_addr);
        maxindex = build_indirect_ref (cookie_addr, NULL);
      }
    else if (TREE_CODE (type) == ARRAY_TYPE)
Index: cp/class.c
===================================================================
*** cp/class.c	(.../trunk/gcc)	(revision 125658)
--- cp/class.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** build_base_path (enum tree_code code,
*** 367,374 ****
  	v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
  				     TREE_TYPE (TREE_TYPE (expr)));
  
!       v_offset = build2 (PLUS_EXPR, TREE_TYPE (v_offset),
! 			 v_offset,  BINFO_VPTR_FIELD (v_binfo));
        v_offset = build1 (NOP_EXPR,
  			 build_pointer_type (ptrdiff_type_node),
  			 v_offset);
--- 367,374 ----
  	v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
  				     TREE_TYPE (TREE_TYPE (expr)));
  
!       v_offset = build2 (POINTER_PLUS_EXPR, TREE_TYPE (v_offset),
! 			 v_offset, fold_convert (sizetype, BINFO_VPTR_FIELD (v_binfo)));
        v_offset = build1 (NOP_EXPR,
  			 build_pointer_type (ptrdiff_type_node),
  			 v_offset);
*************** build_base_path (enum tree_code code,
*** 406,412 ****
    expr = build1 (NOP_EXPR, ptr_target_type, expr);
  
    if (!integer_zerop (offset))
!     expr = build2 (code, ptr_target_type, expr, offset);
    else
      null_test = NULL;
  
--- 406,417 ----
    expr = build1 (NOP_EXPR, ptr_target_type, expr);
  
    if (!integer_zerop (offset))
!     {
!       offset = fold_convert (sizetype, offset);
!       if (code == MINUS_EXPR)
! 	offset = build1 (NEGATE_EXPR, sizetype, offset);
!       expr = build2 (POINTER_PLUS_EXPR, ptr_target_type, expr, offset);
!     }
    else
      null_test = NULL;
  
*************** convert_to_base_statically (tree expr, t
*** 539,546 ****
        gcc_assert (!processing_template_decl);
        expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
        if (!integer_zerop (BINFO_OFFSET (base)))
!         expr = fold_build2 (PLUS_EXPR, pointer_type, expr,
! 			    fold_convert (pointer_type, BINFO_OFFSET (base)));
        expr = fold_convert (build_pointer_type (BINFO_TYPE (base)), expr);
        expr = build_fold_indirect_ref (expr);
      }
--- 544,551 ----
        gcc_assert (!processing_template_decl);
        expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
        if (!integer_zerop (BINFO_OFFSET (base)))
!         expr = fold_build2 (POINTER_PLUS_EXPR, pointer_type, expr,
! 			    fold_convert (sizetype, BINFO_OFFSET (base)));
        expr = fold_convert (build_pointer_type (BINFO_TYPE (base)), expr);
        expr = build_fold_indirect_ref (expr);
      }
*************** fixed_type_or_null (tree instance, int* 
*** 5275,5280 ****
--- 5280,5286 ----
  	}
        return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
  
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
      case MINUS_EXPR:
        if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
*************** get_vtbl_decl_for_binfo (tree binfo)
*** 6327,6333 ****
    tree decl;
  
    decl = BINFO_VTABLE (binfo);
!   if (decl && TREE_CODE (decl) == PLUS_EXPR)
      {
        gcc_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR);
        decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
--- 6333,6339 ----
    tree decl;
  
    decl = BINFO_VTABLE (binfo);
!   if (decl && TREE_CODE (decl) == POINTER_PLUS_EXPR)
      {
        gcc_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR);
        decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
*************** dfs_accumulate_vtbl_inits (tree binfo,
*** 7113,7119 ****
        index = size_binop (MULT_EXPR,
  			  TYPE_SIZE_UNIT (vtable_entry_type),
  			  index);
!       vtbl = build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
      }
  
    if (ctor_vtbl_p)
--- 7119,7125 ----
        index = size_binop (MULT_EXPR,
  			  TYPE_SIZE_UNIT (vtable_entry_type),
  			  index);
!       vtbl = build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
      }
  
    if (ctor_vtbl_p)
Index: cp/call.c
===================================================================
*** cp/call.c	(.../trunk/gcc)	(revision 125658)
--- cp/call.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** build_special_member_call (tree instance
*** 5321,5327 ****
  		    current_vtt_parm,
  		    vtt);
        gcc_assert (BINFO_SUBVTT_INDEX (binfo));
!       sub_vtt = build2 (PLUS_EXPR, TREE_TYPE (vtt), vtt,
  			BINFO_SUBVTT_INDEX (binfo));
  
        args = tree_cons (NULL_TREE, sub_vtt, args);
--- 5321,5327 ----
  		    current_vtt_parm,
  		    vtt);
        gcc_assert (BINFO_SUBVTT_INDEX (binfo));
!       sub_vtt = build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtt), vtt,
  			BINFO_SUBVTT_INDEX (binfo));
  
        args = tree_cons (NULL_TREE, sub_vtt, args);
Index: cp/method.c
===================================================================
*** cp/method.c	(.../trunk/gcc)	(revision 125658)
--- cp/method.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** thunk_adjust (tree ptr, bool this_adjust
*** 220,227 ****
  {
    if (this_adjusting)
      /* Adjust the pointer by the constant.  */
!     ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr,
! 		       ssize_int (fixed_offset));
  
    /* If there's a virtual offset, look up that value in the vtable and
       adjust the pointer again.  */
--- 220,227 ----
  {
    if (this_adjusting)
      /* Adjust the pointer by the constant.  */
!     ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr,
! 		       size_int (fixed_offset));
  
    /* If there's a virtual offset, look up that value in the vtable and
       adjust the pointer again.  */
*************** thunk_adjust (tree ptr, bool this_adjust
*** 238,254 ****
        /* Form the vtable address.  */
        vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
        /* Find the entry with the vcall offset.  */
!       vtable = build2 (PLUS_EXPR, TREE_TYPE (vtable), vtable, virtual_offset);
        /* Get the offset itself.  */
        vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
        /* Adjust the `this' pointer.  */
!       ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, vtable);
      }
  
    if (!this_adjusting)
      /* Adjust the pointer by the constant.  */
!     ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr,
! 		       ssize_int (fixed_offset));
  
    return ptr;
  }
--- 238,256 ----
        /* Form the vtable address.  */
        vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
        /* Find the entry with the vcall offset.  */
!       vtable = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtable), vtable,
! 		       fold_convert (sizetype, virtual_offset));
        /* Get the offset itself.  */
        vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
        /* Adjust the `this' pointer.  */
!       ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr,
! 			 fold_convert (sizetype, vtable));
      }
  
    if (!this_adjusting)
      /* Adjust the pointer by the constant.  */
!     ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr,
! 		       size_int (fixed_offset));
  
    return ptr;
  }
Index: cp/rtti.c
===================================================================
*** cp/rtti.c	(.../trunk/gcc)	(revision 125658)
--- cp/rtti.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** build_headof (tree exp)
*** 180,187 ****
  
    type = build_qualified_type (ptr_type_node,
  			       cp_type_quals (TREE_TYPE (exp)));
!   return build2 (PLUS_EXPR, type, exp,
! 		 convert_to_integer (ptrdiff_type_node, offset));
  }
  
  /* Get a bad_cast node for the program to throw...
--- 180,187 ----
  
    type = build_qualified_type (ptr_type_node,
  			       cp_type_quals (TREE_TYPE (exp)));
!   return build2 (POINTER_PLUS_EXPR, type, exp,
! 		 convert_to_integer (sizetype, offset));
  }
  
  /* Get a bad_cast node for the program to throw...
*************** tinfo_base_init (tinfo_s *ti, tree targe
*** 856,862 ****
  
        /* We need to point into the middle of the vtable.  */
        vtable_ptr = build2
! 	(PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
  	 size_binop (MULT_EXPR,
  		     size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
  		     TYPE_SIZE_UNIT (vtable_entry_type)));
--- 856,862 ----
  
        /* We need to point into the middle of the vtable.  */
        vtable_ptr = build2
! 	(POINTER_PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
  	 size_binop (MULT_EXPR,
  		     size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
  		     TYPE_SIZE_UNIT (vtable_entry_type)));
Index: cp/except.c
===================================================================
*** cp/except.c	(.../trunk/gcc)	(revision 125658)
--- cp/except.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** expand_start_catch_block (tree decl)
*** 426,433 ****
  	 generic exception header.  */
        exp = build_exc_ptr ();
        exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
!       exp = build2 (MINUS_EXPR, TREE_TYPE (exp), exp,
! 		    TYPE_SIZE_UNIT (TREE_TYPE (exp)));
        exp = build_indirect_ref (exp, NULL);
        initialize_handler_parm (decl, exp);
        return type;
--- 426,434 ----
  	 generic exception header.  */
        exp = build_exc_ptr ();
        exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
!       exp = build2 (POINTER_PLUS_EXPR, TREE_TYPE (exp), exp,
! 		    build1 (NEGATE_EXPR, sizetype,
! 			    TYPE_SIZE_UNIT (TREE_TYPE (exp))));
        exp = build_indirect_ref (exp, NULL);
        initialize_handler_parm (decl, exp);
        return type;
Index: cp/ChangeLog.ptr
===================================================================
*** cp/ChangeLog.ptr	(.../trunk/gcc)	(revision 0)
--- cp/ChangeLog.ptr	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,60 ----
+ 2007-05-28  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* typeck.c (build_binary_op): Add a comment on why creating
+ 	the tree in pieces while processing templates.
+ 
+ 2007-05-12  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* except.c (expand_start_catch_block):  Do a
+ 	NEGATIVE and then a POINTER_PLUS_EXPR instead
+ 	of a MINUS_EXPR.
+ 
+ 2007-05-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* cp-gimplify.c (cxx_omp_clause_apply_fn): Convert
+ 	PLUS_EXPR on pointer types over to use
+ 	POINTER_PLUS_EXPR and remove the conversion
+ 	to the pointer types.
+ 
+ 2007-05-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* typeck.c (build_unary_op): Remove code that used to
+ 	handle non lvalue increments/decrements as we now error
+ 	out all ways.
+ 
+ 2007-05-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* typeck.c (get_member_function_from_ptrfunc):
+ 	Change over to using POINTER_PLUS_EXPR and convert
+ 	the second operand to sizetype.
+ 	* typeck2.c (build_m_component_ref): Likewise.
+ 	* rtti.c (build_headof): Use sizetype instead of
+ 	ptrdiff_type_node.
+ 
+ 2007-05-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* method.c (thunk_adjust): Use POINTER_PLUS_EXPR for
+ 	adding to a pointer type. Use size_int instead of
+ 	ssize_int. Convert the index to sizetype before
+ 	adding it to the pointer.
+ 
+ 2006-11-23  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* typeck.c (build_binary_op): For templates build the
+ 	expression in pieces to avoid the assert in build2_stat.
+ 	* init.c (expand_virtual_init): Create a POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR for pointers.
+ 	(build_new_1): Likewise.
+ 	(build_vec_delete_1): Likewise.
+ 	(build_vec_delete): Likewise.
+ 	* class.c (build_base_path): Likewise.
+ 	(build_base_path): Likewise.
+ 	(convert_to_base_statically): Likewise.
+ 	(fixed_type_or_null): Handle POINTER_PLUS_EXPR.
+ 	(get_vtbl_decl_for_binfo): Handle POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR.
+ 	(dfs_accumulate_vtbl_inits): Create a POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR for pointers.
+ 	* call.c (build_special_member_call): Likewise.
+ 	* rtti.c (build_headof): Likewise.
+ 	(tinfo_base_init): Likewise.
Index: cp/cp-gimplify.c
===================================================================
*** cp/cp-gimplify.c	(.../trunk/gcc)	(revision 125658)
--- cp/cp-gimplify.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** cxx_omp_clause_apply_fn (tree fn, tree a
*** 802,809 ****
  	start2 = build_fold_addr_expr (start2);
  
        end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
!       end1 = fold_convert (TREE_TYPE (start1), end1);
!       end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
  
        p1 = create_tmp_var (TREE_TYPE (start1), NULL);
        t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, start1);
--- 802,808 ----
  	start2 = build_fold_addr_expr (start2);
  
        end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
!       end1 = build2 (POINTER_PLUS_EXPR, TREE_TYPE (start1), start1, end1);
  
        p1 = create_tmp_var (TREE_TYPE (start1), NULL);
        t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, start1);
*************** cxx_omp_clause_apply_fn (tree fn, tree a
*** 830,844 ****
        t = build_call_a (fn, i, argarray);
        append_to_statement_list (t, &ret);
  
!       t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
!       t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
        t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, t);
        append_to_statement_list (t, &ret);
  
        if (arg2)
  	{
! 	  t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
! 	  t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
  	  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p2, t);
  	  append_to_statement_list (t, &ret);
  	}
--- 829,843 ----
        t = build_call_a (fn, i, argarray);
        append_to_statement_list (t, &ret);
  
!       t = TYPE_SIZE_UNIT (inner_type);
!       t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p1), p1, t);
        t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, t);
        append_to_statement_list (t, &ret);
  
        if (arg2)
  	{
! 	  t = TYPE_SIZE_UNIT (inner_type);
! 	  t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p2), p2, t);
  	  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p2, t);
  	  append_to_statement_list (t, &ret);
  	}
Index: cp/typeck2.c
===================================================================
*** cp/typeck2.c	(.../trunk/gcc)	(revision 125658)
--- cp/typeck2.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** build_m_component_ref (tree datum, tree 
*** 1277,1284 ****
  
        /* Build an expression for "object + offset" where offset is the
  	 value stored in the pointer-to-data-member.  */
!       datum = build2 (PLUS_EXPR, build_pointer_type (type),
! 		      datum, build_nop (ptrdiff_type_node, component));
        return build_indirect_ref (datum, 0);
      }
    else
--- 1277,1284 ----
  
        /* Build an expression for "object + offset" where offset is the
  	 value stored in the pointer-to-data-member.  */
!       datum = build2 (POINTER_PLUS_EXPR, build_pointer_type (type),
! 		      datum, build_nop (sizetype, component));
        return build_indirect_ref (datum, 0);
      }
    else
Index: tree-ssa-ccp.c
===================================================================
*** tree-ssa-ccp.c	(.../trunk/gcc)	(revision 125658)
--- tree-ssa-ccp.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** maybe_fold_stmt_indirect (tree expr, tre
*** 1853,1860 ****
    if (t)
      return t;
  
!   /* Add in any offset from a PLUS_EXPR.  */
!   if (TREE_CODE (base) == PLUS_EXPR)
      {
        tree offset2;
  
--- 1853,1860 ----
    if (t)
      return t;
  
!   /* Add in any offset from a POINTER_PLUS_EXPR.  */
!   if (TREE_CODE (base) == POINTER_PLUS_EXPR)
      {
        tree offset2;
  
*************** maybe_fold_stmt_indirect (tree expr, tre
*** 1863,1869 ****
  	return NULL_TREE;
        base = TREE_OPERAND (base, 0);
  
!       offset = int_const_binop (PLUS_EXPR, offset, offset2, 1);
      }
  
    if (TREE_CODE (base) == ADDR_EXPR)
--- 1863,1870 ----
  	return NULL_TREE;
        base = TREE_OPERAND (base, 0);
  
!       offset = fold_convert (sizetype,
! 			     int_const_binop (PLUS_EXPR, offset, offset2, 1));
      }
  
    if (TREE_CODE (base) == ADDR_EXPR)
*************** maybe_fold_stmt_indirect (tree expr, tre
*** 1923,1929 ****
  }
  
  
! /* A subroutine of fold_stmt_r.  EXPR is a PLUS_EXPR.
  
     A quaint feature extant in our address arithmetic is that there
     can be hidden type changes here.  The type of the result need
--- 1924,1930 ----
  }
  
  
! /* A subroutine of fold_stmt_r.  EXPR is a POINTER_PLUS_EXPR.
  
     A quaint feature extant in our address arithmetic is that there
     can be hidden type changes here.  The type of the result need
*************** maybe_fold_stmt_indirect (tree expr, tre
*** 1932,1938 ****
     What we're after here is an expression of the form
  	(T *)(&array + const)
     where the cast doesn't actually exist, but is implicit in the
!    type of the PLUS_EXPR.  We'd like to turn this into
  	&array[x]
     which may be able to propagate further.  */
  
--- 1933,1939 ----
     What we're after here is an expression of the form
  	(T *)(&array + const)
     where the cast doesn't actually exist, but is implicit in the
!    type of the POINTER_PLUS_EXPR.  We'd like to turn this into
  	&array[x]
     which may be able to propagate further.  */
  
*************** maybe_fold_stmt_addition (tree expr)
*** 1944,1961 ****
    tree ptr_type = TREE_TYPE (expr);
    tree ptd_type;
    tree t;
-   bool subtract = (TREE_CODE (expr) == MINUS_EXPR);
  
-   /* We're only interested in pointer arithmetic.  */
-   if (!POINTER_TYPE_P (ptr_type))
-     return NULL_TREE;
-   /* Canonicalize the integral operand to op1.  */
-   if (INTEGRAL_TYPE_P (TREE_TYPE (op0)))
-     {
-       if (subtract)
- 	return NULL_TREE;
-       t = op0, op0 = op1, op1 = t;
-     }
    /* It had better be a constant.  */
    if (TREE_CODE (op1) != INTEGER_CST)
      return NULL_TREE;
--- 1945,1951 ----
*************** maybe_fold_stmt_addition (tree expr)
*** 2001,2032 ****
        array_idx = int_const_binop (MULT_EXPR, array_idx, elt_size, 0);
  
        /* Update the operands for the next round, or for folding.  */
!       /* If we're manipulating unsigned types, then folding into negative
! 	 values can produce incorrect results.  Particularly if the type
! 	 is smaller than the width of the pointer.  */
!       if (subtract
! 	  && TYPE_UNSIGNED (TREE_TYPE (op1))
! 	  && tree_int_cst_lt (array_idx, op1))
! 	return NULL;
!       op1 = int_const_binop (subtract ? MINUS_EXPR : PLUS_EXPR,
  			     array_idx, op1, 0);
-       subtract = false;
        op0 = array_obj;
      }
  
-   /* If we weren't able to fold the subtraction into another array reference,
-      canonicalize the integer for passing to the array and component ref
-      simplification functions.  */
-   if (subtract)
-     {
-       if (TYPE_UNSIGNED (TREE_TYPE (op1)))
- 	return NULL;
-       op1 = fold_unary (NEGATE_EXPR, TREE_TYPE (op1), op1);
-       /* ??? In theory fold should always produce another integer.  */
-       if (op1 == NULL || TREE_CODE (op1) != INTEGER_CST)
- 	return NULL;
-     }
- 
    ptd_type = TREE_TYPE (ptr_type);
  
    /* At which point we can try some of the same things as for indirects.  */
--- 1991,2001 ----
        array_idx = int_const_binop (MULT_EXPR, array_idx, elt_size, 0);
  
        /* Update the operands for the next round, or for folding.  */
!       op1 = int_const_binop (PLUS_EXPR,
  			     array_idx, op1, 0);
        op0 = array_obj;
      }
  
    ptd_type = TREE_TYPE (ptr_type);
  
    /* At which point we can try some of the same things as for indirects.  */
*************** fold_stmt_r (tree *expr_p, int *walk_sub
*** 2116,2123 ****
          recompute_tree_invariant_for_addr_expr (expr);
        return NULL_TREE;
  
!     case PLUS_EXPR:
!     case MINUS_EXPR:
        t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
        if (t)
  	return t;
--- 2085,2091 ----
          recompute_tree_invariant_for_addr_expr (expr);
        return NULL_TREE;
  
!     case POINTER_PLUS_EXPR:
        t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
        if (t)
  	return t;
Index: tree-ssa-loop-ivopts.c
===================================================================
*** tree-ssa-loop-ivopts.c	(.../trunk/gcc)	(revision 125658)
--- tree-ssa-loop-ivopts.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** static tree
*** 755,761 ****
  determine_base_object (tree expr)
  {
    enum tree_code code = TREE_CODE (expr);
!   tree base, obj, op0, op1;
  
    /* If this is a pointer casted to any type, we need to determine
       the base object for the pointer; so handle conversions before
--- 755,761 ----
  determine_base_object (tree expr)
  {
    enum tree_code code = TREE_CODE (expr);
!   tree base, obj;
  
    /* If this is a pointer casted to any type, we need to determine
       the base object for the pointer; so handle conversions before
*************** determine_base_object (tree expr)
*** 785,804 ****
        return fold_convert (ptr_type_node,
  		           build_fold_addr_expr (base));
  
      case PLUS_EXPR:
      case MINUS_EXPR:
!       op0 = determine_base_object (TREE_OPERAND (expr, 0));
!       op1 = determine_base_object (TREE_OPERAND (expr, 1));
!       
!       if (!op1)
! 	return op0;
! 
!       if (!op0)
! 	return (code == PLUS_EXPR
! 		? op1
! 		: fold_build1 (NEGATE_EXPR, ptr_type_node, op1));
! 
!       return fold_build2 (code, ptr_type_node, op0, op1);
  
      default:
        return fold_convert (ptr_type_node, expr);
--- 785,797 ----
        return fold_convert (ptr_type_node,
  		           build_fold_addr_expr (base));
  
+     case POINTER_PLUS_EXPR:
+       return determine_base_object (TREE_OPERAND (expr, 0));
+ 
      case PLUS_EXPR:
      case MINUS_EXPR:
!       /* Pointer adition is done solely using POINTER_PLUS_EXPR.  */
!       gcc_unreachable ();
  
      default:
        return fold_convert (ptr_type_node, expr);
*************** force_expr_to_var_cost (tree expr)
*** 3100,3108 ****
        symbol_cost = computation_cost (addr) + 1;
  
        address_cost
! 	= computation_cost (build2 (PLUS_EXPR, type,
  				    addr,
! 				    build_int_cst (type, 2000))) + 1;
        if (dump_file && (dump_flags & TDF_DETAILS))
  	{
  	  fprintf (dump_file, "force_expr_to_var_cost:\n");
--- 3093,3101 ----
        symbol_cost = computation_cost (addr) + 1;
  
        address_cost
! 	= computation_cost (build2 (POINTER_PLUS_EXPR, type,
  				    addr,
! 				    build_int_cst (sizetype, 2000))) + 1;
        if (dump_file && (dump_flags & TDF_DETAILS))
  	{
  	  fprintf (dump_file, "force_expr_to_var_cost:\n");
*************** force_expr_to_var_cost (tree expr)
*** 3141,3146 ****
--- 3134,3140 ----
  
    switch (TREE_CODE (expr))
      {
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
      case MINUS_EXPR:
      case MULT_EXPR:
*************** force_expr_to_var_cost (tree expr)
*** 3169,3174 ****
--- 3163,3169 ----
    mode = TYPE_MODE (TREE_TYPE (expr));
    switch (TREE_CODE (expr))
      {
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
      case MINUS_EXPR:
        cost = add_cost (mode);
Index: c-format.c
===================================================================
*** c-format.c	(.../trunk/gcc)	(revision 125658)
--- c-format.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** check_format_arg (void *ctx, tree format
*** 1313,1319 ****
      }
  
    offset = 0;
!   if (TREE_CODE (format_tree) == PLUS_EXPR)
      {
        tree arg0, arg1;
  
--- 1313,1319 ----
      }
  
    offset = 0;
!   if (TREE_CODE (format_tree) == POINTER_PLUS_EXPR)
      {
        tree arg0, arg1;
  
*************** check_format_arg (void *ctx, tree format
*** 1323,1333 ****
        STRIP_NOPS (arg1);
        if (TREE_CODE (arg1) == INTEGER_CST)
  	format_tree = arg0;
-       else if (TREE_CODE (arg0) == INTEGER_CST)
- 	{
- 	  format_tree = arg1;
- 	  arg1 = arg0;
- 	}
        else
  	{
  	  res->number_non_literal++;
--- 1323,1328 ----
Index: tree-stdarg.c
===================================================================
*** tree-stdarg.c	(.../trunk/gcc)	(revision 125658)
--- tree-stdarg.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** va_list_counter_bump (struct stdarg_info
*** 171,177 ****
  	  continue;
  	}
  
!       if (TREE_CODE (rhs) == PLUS_EXPR
  	  && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
  	  && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST
  	  && host_integerp (TREE_OPERAND (rhs, 1), 1))
--- 171,178 ----
  	  continue;
  	}
  
!       if ((TREE_CODE (rhs) == POINTER_PLUS_EXPR
! 	   || TREE_CODE (rhs) == PLUS_EXPR)
  	  && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
  	  && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST
  	  && host_integerp (TREE_OPERAND (rhs, 1), 1))
*************** va_list_counter_bump (struct stdarg_info
*** 229,235 ****
  	  continue;
  	}
  
!       if (TREE_CODE (rhs) == PLUS_EXPR
  	  && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
  	  && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST
  	  && host_integerp (TREE_OPERAND (rhs, 1), 1))
--- 230,237 ----
  	  continue;
  	}
  
!       if ((TREE_CODE (rhs) == POINTER_PLUS_EXPR
! 	   || TREE_CODE (rhs) == PLUS_EXPR)
  	  && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
  	  && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST
  	  && host_integerp (TREE_OPERAND (rhs, 1), 1))
*************** check_va_list_escapes (struct stdarg_inf
*** 447,456 ****
    if (! POINTER_TYPE_P (TREE_TYPE (rhs)))
      return;
  
!   if ((TREE_CODE (rhs) == PLUS_EXPR
!        && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
!       || TREE_CODE (rhs) == NOP_EXPR
!       || TREE_CODE (rhs) == CONVERT_EXPR)
      rhs = TREE_OPERAND (rhs, 0);
  
    if (TREE_CODE (rhs) != SSA_NAME
--- 449,459 ----
    if (! POINTER_TYPE_P (TREE_TYPE (rhs)))
      return;
  
!  if (((TREE_CODE (rhs) == POINTER_PLUS_EXPR
!        || TREE_CODE (rhs) == PLUS_EXPR)
!       && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
!      || TREE_CODE (rhs) == NOP_EXPR
!      || TREE_CODE (rhs) == CONVERT_EXPR)
      rhs = TREE_OPERAND (rhs, 0);
  
    if (TREE_CODE (rhs) != SSA_NAME
*************** check_all_va_list_escapes (struct stdarg
*** 555,561 ****
  		     other_ap_temp = (some_type *) ap_temp;
  		     ap = ap_temp;
  		     statements.  */
! 		  if ((TREE_CODE (rhs) == PLUS_EXPR
  		       && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
  		      || TREE_CODE (rhs) == NOP_EXPR
  		      || TREE_CODE (rhs) == CONVERT_EXPR)
--- 558,564 ----
  		     other_ap_temp = (some_type *) ap_temp;
  		     ap = ap_temp;
  		     statements.  */
! 		  if ((TREE_CODE (rhs) == POINTER_PLUS_EXPR
  		       && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
  		      || TREE_CODE (rhs) == NOP_EXPR
  		      || TREE_CODE (rhs) == CONVERT_EXPR)
Index: dwarf2out.c
===================================================================
*** dwarf2out.c	(.../trunk/gcc)	(revision 125658)
--- dwarf2out.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 9442,9447 ****
--- 9442,9448 ----
        op = (TYPE_UNSIGNED (TREE_TYPE (loc)) ? DW_OP_shr : DW_OP_shra);
        goto do_binop;
  
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
  	  && host_integerp (TREE_OPERAND (loc, 1), 0))
Index: expr.c
===================================================================
*** expr.c	(.../trunk/gcc)	(revision 125658)
--- expr.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** expand_expr_real_1 (tree exp, rtx target
*** 8036,8042 ****
--- 8036,8047 ----
  
        return op0;
  
+     case POINTER_PLUS_EXPR: 
+       /* Even though the sizetype mode and the pointer's mode can be different
+          expand is able to handle this correct and get the correct result out 
+          from the PLUS_EXPR code.  */
      case PLUS_EXPR:
+ 
        /* Check if this is a case for multiplication and addition.  */
        if (TREE_CODE (type) == INTEGER_TYPE
  	  && TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR)
*************** string_constant (tree arg, tree *ptr_off
*** 9255,9261 ****
        else
  	return 0;
      }
!   else if (TREE_CODE (arg) == PLUS_EXPR)
      {
        tree arg0 = TREE_OPERAND (arg, 0);
        tree arg1 = TREE_OPERAND (arg, 1);
--- 9260,9266 ----
        else
  	return 0;
      }
!   else if (TREE_CODE (arg) == PLUS_EXPR || TREE_CODE (arg) == POINTER_PLUS_EXPR)
      {
        tree arg0 = TREE_OPERAND (arg, 0);
        tree arg1 = TREE_OPERAND (arg, 1);
Index: ada/trans.c
===================================================================
*** ada/trans.c	(.../trunk/gcc)	(revision 125658)
--- ada/trans.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** Attribute_to_gnu (Node_Id gnat_node, tre
*** 829,839 ****
  	    tree gnu_char_ptr_type = build_pointer_type (char_type_node);
  	    tree gnu_pos = byte_position (TYPE_FIELDS (gnu_obj_type));
  	    tree gnu_byte_offset
! 	      = convert (gnu_char_ptr_type,
  			 size_diffop (size_zero_node, gnu_pos));
  
  	    gnu_ptr = convert (gnu_char_ptr_type, gnu_ptr);
! 	    gnu_ptr = build_binary_op (MINUS_EXPR, gnu_char_ptr_type,
  				       gnu_ptr, gnu_byte_offset);
  	  }
  
--- 829,840 ----
  	    tree gnu_char_ptr_type = build_pointer_type (char_type_node);
  	    tree gnu_pos = byte_position (TYPE_FIELDS (gnu_obj_type));
  	    tree gnu_byte_offset
! 	      = convert (sizetype,
  			 size_diffop (size_zero_node, gnu_pos));
+ 	    gnu_byte_offset = build1 (NEGATE_EXPR, sizetype, gnu_byte_offset);
  
  	    gnu_ptr = convert (gnu_char_ptr_type, gnu_ptr);
! 	    gnu_ptr = build_binary_op (POINTER_PLUS_EXPR, gnu_char_ptr_type,
  				       gnu_ptr, gnu_byte_offset);
  	  }
  
*************** gnat_to_gnu (Node_Id gnat_node)
*** 4571,4581 ****
  	      tree gnu_char_ptr_type = build_pointer_type (char_type_node);
  	      tree gnu_pos = byte_position (TYPE_FIELDS (gnu_obj_type));
  	      tree gnu_byte_offset
! 		= convert (gnu_char_ptr_type,
  			   size_diffop (size_zero_node, gnu_pos));
  
  	      gnu_ptr = convert (gnu_char_ptr_type, gnu_ptr);
! 	      gnu_ptr = build_binary_op (MINUS_EXPR, gnu_char_ptr_type,
  					 gnu_ptr, gnu_byte_offset);
  	    }
  
--- 4572,4583 ----
  	      tree gnu_char_ptr_type = build_pointer_type (char_type_node);
  	      tree gnu_pos = byte_position (TYPE_FIELDS (gnu_obj_type));
  	      tree gnu_byte_offset
! 		= convert (sizetype,
  			   size_diffop (size_zero_node, gnu_pos));
+ 	      gnu_byte_offset = build1 (NEGATE_EXPR, sizetype, gnu_byte_offset);
  
  	      gnu_ptr = convert (gnu_char_ptr_type, gnu_ptr);
! 	      gnu_ptr = build_binary_op (POINTER_PLUS_EXPR, gnu_char_ptr_type,
  					 gnu_ptr, gnu_byte_offset);
  	    }
  
Index: ada/ChangeLog.ptr
===================================================================
*** ada/ChangeLog.ptr	(.../trunk/gcc)	(revision 0)
--- ada/ChangeLog.ptr	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,15 ----
+ 2007-05-12  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* trans.c (Attribute_to_gnu): When subtracting an
+ 	offset from a pointer, use POINTER_PLUS_EXPR with
+ 	NEGATE_EXPR instead of MINUS_EXPR.
+ 	(gnat_to_gnu): Likewise.
+ 	* utils.c (convert): When converting between
+ 	thin pointers, use POINTER_PLUS_EXPR and sizetype
+ 	for the offset.
+ 	* utils2.c (known_alignment): POINTER_PLUS_EXPR
+ 	have the same semantics as PLUS_EXPR for alignment.
+ 	(build_binary_op): Add support for the semantics of
+ 	POINTER_PLUS_EXPR's operands.
+ 	When adding an offset to a pointer, use POINTER_PLUS_EXPR.
+ 
Index: ada/utils.c
===================================================================
*** ada/utils.c	(.../trunk/gcc)	(revision 125658)
--- ada/utils.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** convert (tree type, tree expr)
*** 3601,3608 ****
  	  if (integer_zerop (byte_diff))
  	    return expr;
  
! 	  return build_binary_op (PLUS_EXPR, type, expr,
! 				  fold (convert_to_pointer (type, byte_diff)));
  	}
  
        /* If converting to a thin pointer, handle specially.  */
--- 3601,3608 ----
  	  if (integer_zerop (byte_diff))
  	    return expr;
  
! 	  return build_binary_op (POINTER_PLUS_EXPR, type, expr,
! 				  fold (convert (sizetype, byte_diff)));
  	}
  
        /* If converting to a thin pointer, handle specially.  */
Index: ada/utils2.c
===================================================================
*** ada/utils2.c	(.../trunk/gcc)	(revision 125658)
--- ada/utils2.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** known_alignment (tree exp)
*** 172,177 ****
--- 172,178 ----
        break;
  
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
      case MINUS_EXPR:
        /* If two address are added, the alignment of the result is the
  	 minimum of the two alignments.  */
*************** build_binary_op (enum tree_code op_code,
*** 961,966 ****
--- 962,974 ----
        modulus = NULL_TREE;
        goto common;
  
+     case POINTER_PLUS_EXPR:
+       gcc_assert (operation_type == left_base_type
+ 		  && sizetype == right_base_type);
+       left_operand = convert (operation_type, left_operand);
+       right_operand = convert (sizetype, right_operand);
+       break;
+ 
      default:
      common:
        /* The result type should be the same as the base types of the
*************** build_unary_op (enum tree_code op_code, 
*** 1116,1123 ****
  		 type, if any.  */
  	      inner = build_unary_op (ADDR_EXPR, NULL_TREE, inner);
  	      inner = convert (ptr_void_type_node, inner);
! 	      offset = convert (ptr_void_type_node, offset);
! 	      result = build_binary_op (PLUS_EXPR, ptr_void_type_node,
  					inner, offset);
  	      result = convert (build_pointer_type (TREE_TYPE (operand)),
  				result);
--- 1124,1130 ----
  		 type, if any.  */
  	      inner = build_unary_op (ADDR_EXPR, NULL_TREE, inner);
  	      inner = convert (ptr_void_type_node, inner);
! 	      result = build_binary_op (POINTER_PLUS_EXPR, ptr_void_type_node,
  					inner, offset);
  	      result = convert (build_pointer_type (TREE_TYPE (operand)),
  				result);
Index: tree-ssa-address.c
===================================================================
*** tree-ssa-address.c	(.../trunk/gcc)	(revision 125658)
--- tree-ssa-address.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** tree_mem_ref_addr (tree type, tree mem_r
*** 290,298 ****
  
    if (addr_off)
      {
-       addr = fold_convert (type, addr_off);
        if (addr_base)
! 	addr = fold_build2 (PLUS_EXPR, type, addr_base, addr);
      }
    else if (addr_base)
      addr = addr_base;
--- 290,299 ----
  
    if (addr_off)
      {
        if (addr_base)
! 	addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off);
!       else
! 	addr = fold_convert (type, addr_off);
      }
    else if (addr_base)
      addr = addr_base;
*************** add_to_parts (struct mem_address *parts,
*** 410,416 ****
  
    if (!parts->index)
      {
!       parts->index = elt;
        return;
      }
  
--- 411,417 ----
  
    if (!parts->index)
      {
!       parts->index = fold_convert (sizetype, elt);
        return;
      }
  
*************** most_expensive_mult_to_index (struct mem
*** 482,488 ****
  	  j++;
  	  continue;
  	}
!   
        elt = fold_convert (sizetype, addr->elts[i].val);
        if (mult_elt)
  	mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
--- 483,489 ----
  	  j++;
  	  continue;
  	}
! 
        elt = fold_convert (sizetype, addr->elts[i].val);
        if (mult_elt)
  	mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
*************** create_mem_ref (block_stmt_iterator *bsi
*** 658,666 ****
  	{
  	  atype = TREE_TYPE (parts.base);
  	  parts.base = force_gimple_operand_bsi (bsi, 
! 			fold_build2 (PLUS_EXPR, atype,
  				     parts.base,
! 				     fold_convert (atype, parts.offset)),
  			true, NULL_TREE);
  	}
        else
--- 659,667 ----
  	{
  	  atype = TREE_TYPE (parts.base);
  	  parts.base = force_gimple_operand_bsi (bsi, 
! 			fold_build2 (POINTER_PLUS_EXPR, atype,
  				     parts.base,
! 				     fold_convert (sizetype, parts.offset)),
  			true, NULL_TREE);
  	}
        else
Index: matrix-reorg.c
===================================================================
*** matrix-reorg.c	(.../trunk/gcc)	(revision 125658)
--- matrix-reorg.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** collect_data_for_malloc_call (tree stmt,
*** 224,233 ****
     initial address and index of each dimension.  */
  struct access_site_info
  {
!   /* The statement (INDIRECT_REF or PLUS_EXPR).  */
    tree stmt;
  
!   /* In case of PLUS_EXPR, what is the offset.  */
    tree offset;
  
    /* The index which created the offset.  */
--- 224,233 ----
     initial address and index of each dimension.  */
  struct access_site_info
  {
!   /* The statement (INDIRECT_REF or POINTER_PLUS_EXPR).  */
    tree stmt;
  
!   /* In case of POINTER_PLUS_EXPR, what is the offset.  */
    tree offset;
  
    /* The index which created the offset.  */
*************** mark_min_matrix_escape_level (struct mat
*** 609,615 ****
  /* Find if the SSA variable is accessed inside the
     tree and record the tree containing it.
     The only relevant uses are the case of SSA_NAME, or SSA inside
!    INDIRECT_REF, CALL_EXPR, PLUS_EXPR, MULT_EXPR.  */
  static void
  ssa_accessed_in_tree (tree t, struct ssa_acc_in_tree *a)
  {
--- 609,615 ----
  /* Find if the SSA variable is accessed inside the
     tree and record the tree containing it.
     The only relevant uses are the case of SSA_NAME, or SSA inside
!    INDIRECT_REF, CALL_EXPR, PLUS_EXPR, POINTER_PLUS_EXPR, MULT_EXPR.  */
  static void
  ssa_accessed_in_tree (tree t, struct ssa_acc_in_tree *a)
  {
*************** ssa_accessed_in_tree (tree t, struct ssa
*** 644,649 ****
--- 644,650 ----
  	  }
        }
        break;
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
      case MULT_EXPR:
        op1 = TREE_OPERAND (t, 0);
*************** analyze_transpose (void **slot, void *da
*** 903,909 ****
    for (i = 0; VEC_iterate (access_site_info_p, mi->access_l, i, acc_info);
         i++)
      {
!       if (TREE_CODE (GIMPLE_STMT_OPERAND (acc_info->stmt, 1)) == PLUS_EXPR
  	  && acc_info->level < min_escape_l)
  	{
  	  loop = loop_containing_stmt (acc_info->stmt);
--- 904,910 ----
    for (i = 0; VEC_iterate (access_site_info_p, mi->access_l, i, acc_info);
         i++)
      {
!       if (TREE_CODE (GIMPLE_STMT_OPERAND (acc_info->stmt, 1)) == POINTER_PLUS_EXPR
  	  && acc_info->level < min_escape_l)
  	{
  	  loop = loop_containing_stmt (acc_info->stmt);
*************** analyze_accesses_for_modify_stmt (struct
*** 1197,1203 ****
  	  return current_indirect_level;
  	}
        if (rhs_acc.t_code != INDIRECT_REF
! 	  && rhs_acc.t_code != PLUS_EXPR && rhs_acc.t_code != SSA_NAME)
  	{
  	  mark_min_matrix_escape_level (mi, current_indirect_level, use_stmt);
  	  return current_indirect_level;
--- 1198,1204 ----
  	  return current_indirect_level;
  	}
        if (rhs_acc.t_code != INDIRECT_REF
! 	  && rhs_acc.t_code != POINTER_PLUS_EXPR && rhs_acc.t_code != SSA_NAME)
  	{
  	  mark_min_matrix_escape_level (mi, current_indirect_level, use_stmt);
  	  return current_indirect_level;
*************** analyze_accesses_for_modify_stmt (struct
*** 1212,1222 ****
  					   current_indirect_level, true);
  	  current_indirect_level += 1;
  	}
!       else if (rhs_acc.t_code == PLUS_EXPR)
  	{
- 	  /* ??? maybe we should check
- 	     the type of the PLUS_EXP and make sure it's
- 	     integral type.  */
  	  gcc_assert (rhs_acc.second_op);
  	  if (last_op)
  	    /* Currently we support only one PLUS expression on the
--- 1213,1220 ----
  					   current_indirect_level, true);
  	  current_indirect_level += 1;
  	}
!       else if (rhs_acc.t_code == POINTER_PLUS_EXPR)
  	{
  	  gcc_assert (rhs_acc.second_op);
  	  if (last_op)
  	    /* Currently we support only one PLUS expression on the
*************** analyze_accesses_for_modify_stmt (struct
*** 1286,1292 ****
  	  /* We are placing it in an SSA, follow that SSA.  */
  	  analyze_matrix_accesses (mi, lhs,
  				   current_indirect_level,
! 				   rhs_acc.t_code == PLUS_EXPR,
  				   visited, record_accesses);
  	}
      }
--- 1284,1290 ----
  	  /* We are placing it in an SSA, follow that SSA.  */
  	  analyze_matrix_accesses (mi, lhs,
  				   current_indirect_level,
! 				   rhs_acc.t_code == POINTER_PLUS_EXPR,
  				   visited, record_accesses);
  	}
      }
*************** analyze_matrix_accesses (struct matrix_i
*** 1321,1327 ****
  
  /* Now go over the uses of the SSA_NAME and check how it is used in
     each one of them.  We are mainly looking for the pattern INDIRECT_REF,
!    then a PLUS_EXPR, then INDIRECT_REF etc.  while in between there could
     be any number of copies and casts.  */
    gcc_assert (TREE_CODE (ssa_var) == SSA_NAME);
  
--- 1319,1325 ----
  
  /* Now go over the uses of the SSA_NAME and check how it is used in
     each one of them.  We are mainly looking for the pattern INDIRECT_REF,
!    then a POINTER_PLUS_EXPR, then INDIRECT_REF etc.  while in between there could
     be any number of copies and casts.  */
    gcc_assert (TREE_CODE (ssa_var) == SSA_NAME);
  
*************** can_calculate_expr_before_stmt (tree exp
*** 1405,1410 ****
--- 1403,1409 ----
      case PARM_DECL:
      case INTEGER_CST:
        return expr;
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
      case MINUS_EXPR:
      case MULT_EXPR:
*************** transform_access_sites (void **slot, voi
*** 1798,1804 ****
  		    GIMPLE_STMT_OPERAND (orig, 0));
  	  GIMPLE_STMT_OPERAND (acc_info->stmt, 1) = orig;
  	}
!       else if (TREE_CODE (orig) == PLUS_EXPR
  	       && acc_info->level < (min_escape_l))
  	{
  	  imm_use_iterator imm_iter;
--- 1797,1803 ----
  		    GIMPLE_STMT_OPERAND (orig, 0));
  	  GIMPLE_STMT_OPERAND (acc_info->stmt, 1) = orig;
  	}
!       else if (TREE_CODE (orig) == POINTER_PLUS_EXPR
  	       && acc_info->level < (min_escape_l))
  	{
  	  imm_use_iterator imm_iter;
*************** transform_access_sites (void **slot, voi
*** 1822,1832 ****
  		  tree new_offset;
  		  tree d_type_size, d_type_size_k;
  
! 		  d_type_size =
! 		    build_int_cst (type,
! 				   mi->dimension_type_size[min_escape_l]);
! 		  d_type_size_k =
! 		    build_int_cst (type, mi->dimension_type_size[k + 1]);
  
  		  new_offset =
  		    compute_offset (mi->dimension_type_size[min_escape_l],
--- 1821,1828 ----
  		  tree new_offset;
  		  tree d_type_size, d_type_size_k;
  
! 		  d_type_size = size_int (mi->dimension_type_size[min_escape_l]);
! 		  d_type_size_k = size_int (mi->dimension_type_size[k + 1]);
  
  		  new_offset =
  		    compute_offset (mi->dimension_type_size[min_escape_l],
*************** transform_access_sites (void **slot, voi
*** 1857,1863 ****
  	    {
  	      d_size = mi->dimension_size[mi->dim_map[k] + 1];
  	      num_elements =
! 		fold_build2 (MULT_EXPR, type, acc_info->index, d_size);
  	      tmp1 = force_gimple_operand (num_elements, &stmts, true, NULL);
  	      add_referenced_var (d_size);
  	      if (stmts)
--- 1853,1860 ----
  	    {
  	      d_size = mi->dimension_size[mi->dim_map[k] + 1];
  	      num_elements =
! 		fold_build2 (MULT_EXPR, sizetype, fold_convert (sizetype, acc_info->index),
! 			    fold_convert (sizetype, d_size));
  	      tmp1 = force_gimple_operand (num_elements, &stmts, true, NULL);
  	      add_referenced_var (d_size);
  	      if (stmts)
*************** transform_access_sites (void **slot, voi
*** 1880,1887 ****
  
  		  FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, offset)
  		    FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
! 		    if (use_stmt == acc_info->stmt)
! 		    SET_USE (use_p, tmp1);
  		}
  	      else
  		{
--- 1877,1884 ----
  
  		  FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, offset)
  		    FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
! 		      if (use_stmt == acc_info->stmt)
! 		        SET_USE (use_p, tmp1);
  		}
  	      else
  		{
Index: fortran/trans-expr.c
===================================================================
*** fortran/trans-expr.c	(.../trunk/gcc)	(revision 125658)
--- fortran/trans-expr.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** gfc_trans_string_copy (stmtblock_t * blo
*** 2571,2578 ****
    tmp3 = build_call_expr (built_in_decls[BUILT_IN_MEMMOVE],
  			  3, dest, src, slen);
  
!   tmp4 = fold_build2 (PLUS_EXPR, pchar_type_node, dest,
! 		      fold_convert (pchar_type_node, slen));
    tmp4 = build_call_expr (built_in_decls[BUILT_IN_MEMSET], 3,
  			  tmp4, 
  			  build_int_cst (gfc_get_int_type (gfc_c_int_kind),
--- 2571,2578 ----
    tmp3 = build_call_expr (built_in_decls[BUILT_IN_MEMMOVE],
  			  3, dest, src, slen);
  
!   tmp4 = fold_build2 (POINTER_PLUS_EXPR, pchar_type_node, dest,
! 		      fold_convert (sizetype, slen));
    tmp4 = build_call_expr (built_in_decls[BUILT_IN_MEMSET], 3,
  			  tmp4, 
  			  build_int_cst (gfc_get_int_type (gfc_c_int_kind),
Index: fortran/ChangeLog.ptr
===================================================================
*** fortran/ChangeLog.ptr	(.../trunk/gcc)	(revision 0)
--- fortran/ChangeLog.ptr	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,11 ----
+ 2007-05-15  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* trans-intrinsic.c (gfc_conv_intrinsic_repeat): Use
+ 	POINTER_PLUS_EXPR instead of PLUS_EXPR for pointer addition.
+ 
+ 2007-05-07  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* trans-expr.c (gfc_trans_string_copy): Create
+ 	POINTER_PLUS_EXPR instead of a PLUS_EXPR
+ 	for pointer types.
+ 
Index: fortran/trans-intrinsic.c
===================================================================
*** fortran/trans-intrinsic.c	(.../trunk/gcc)	(revision 125658)
--- fortran/trans-intrinsic.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** gfc_conv_intrinsic_repeat (gfc_se * se, 
*** 3530,3537 ****
    /* Call memmove (dest + (i*slen), src, slen).  */
    tmp = fold_build2 (MULT_EXPR, gfc_charlen_type_node, slen,
  		     fold_convert (gfc_charlen_type_node, count));
!   tmp = fold_build2 (PLUS_EXPR, pchar_type_node, dest,
! 		     fold_convert (pchar_type_node, tmp));
    tmp = build_call_expr (built_in_decls[BUILT_IN_MEMMOVE], 3,
  			 tmp, src, slen);
    gfc_add_expr_to_block (&body, tmp);
--- 3530,3537 ----
    /* Call memmove (dest + (i*slen), src, slen).  */
    tmp = fold_build2 (MULT_EXPR, gfc_charlen_type_node, slen,
  		     fold_convert (gfc_charlen_type_node, count));
!   tmp = fold_build2 (POINTER_PLUS_EXPR, pchar_type_node, dest,
! 		     fold_convert (sizetype, tmp));
    tmp = build_call_expr (built_in_decls[BUILT_IN_MEMMOVE], 3,
  			 tmp, src, slen);
    gfc_add_expr_to_block (&body, tmp);
Index: tree-data-ref.c
===================================================================
*** tree-data-ref.c	(.../trunk/gcc)	(revision 125658)
--- tree-data-ref.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** split_constant_offset (tree exp, tree *v
*** 495,519 ****
    tree type = TREE_TYPE (exp), otype;
    tree var0, var1;
    tree off0, off1;
  
    *var = exp;
    STRIP_NOPS (exp);
    otype = TREE_TYPE (exp);
  
!   switch (TREE_CODE (exp))
      {
      case INTEGER_CST:
        *var = build_int_cst (type, 0);
        *off = fold_convert (ssizetype, exp);
        return;
  
      case PLUS_EXPR:
      case MINUS_EXPR:
        split_constant_offset (TREE_OPERAND (exp, 0), &var0, &off0);
        split_constant_offset (TREE_OPERAND (exp, 1), &var1, &off1);
        *var = fold_convert (type, fold_build2 (TREE_CODE (exp), otype, 
  					      var0, var1));
!       *off = size_binop (TREE_CODE (exp), off0, off1);
        return;
  
      case MULT_EXPR:
--- 495,524 ----
    tree type = TREE_TYPE (exp), otype;
    tree var0, var1;
    tree off0, off1;
+   enum tree_code code;
  
    *var = exp;
    STRIP_NOPS (exp);
    otype = TREE_TYPE (exp);
+   code = TREE_CODE (exp);
  
!   switch (code)
      {
      case INTEGER_CST:
        *var = build_int_cst (type, 0);
        *off = fold_convert (ssizetype, exp);
        return;
  
+     case POINTER_PLUS_EXPR:
+       code = PLUS_EXPR;
+       /* FALL THROUGH */
      case PLUS_EXPR:
      case MINUS_EXPR:
        split_constant_offset (TREE_OPERAND (exp, 0), &var0, &off0);
        split_constant_offset (TREE_OPERAND (exp, 1), &var1, &off1);
        *var = fold_convert (type, fold_build2 (TREE_CODE (exp), otype, 
  					      var0, var1));
!       *off = size_binop (code, off0, off1);
        return;
  
      case MULT_EXPR:
Index: tree-affine.c
===================================================================
*** tree-affine.c	(.../trunk/gcc)	(revision 125658)
--- tree-affine.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** tree_to_aff_combination (tree expr, tree
*** 268,273 ****
--- 268,280 ----
        aff_combination_const (comb, type, tree_to_double_int (expr));
        return;
  
+     case POINTER_PLUS_EXPR:
+       tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+       tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
+       aff_combination_convert (&tmp, type);
+       aff_combination_add (comb, &tmp);
+       return;
+ 
      case PLUS_EXPR:
      case MINUS_EXPR:
        tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
Index: ChangeLog.ptr
===================================================================
*** ChangeLog.ptr	(.../trunk/gcc)	(revision 0)
--- ChangeLog.ptr	(.../branches/pointer_plus/gcc)	(revision 125672)
***************
*** 0 ****
--- 1,498 ----
+ 2007-06-13  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* expr.c (expand_expr_real_1 <case POINTER_PLUS_EXPR>): Remove assert
+ 	for checking the modes of the operands are the same.
+ 
+ 2007-06-12  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* config/sparc/sparc.c (sparc_gimplify_va_arg): Use POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR when the operand was a pointer.  Don't create a
+ 	BIT_AND_EXPR for pointer types.
+ 
+ 2007-06-12  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* config/mips/mips.c (mips_va_start): Use POINTER_PLUS_EXPR
+ 	for pointers.
+ 	(mips_gimplify_va_arg_expr): Likewise.
+ 	Don't create BIT_AND_EXPR in a pointer type.
+ 
+ 2007-06-12  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	Merge mainline, revision 125658 
+ 
+ 2007-06-11  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	Merge mainline, revision 125611
+ 
+ 2007-06-07  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* matrix-reorg.c (collect_data_for_malloc_call): Stmt
+ 	will now only be either INDIRECT_REF and POINTER_PLUS_EXPR.
+ 	Offset only holds something for PLUS_EXPR.
+ 	(ssa_accessed_in_tree): Handle POINTER_PLUS_EXPR just as
+ 	a PLUS_EXPR.
+ 	(analyze_transpose): POINTER_PLUS_EXPR will only show up now
+ 	and not PLUS_EXPR.
+ 	(analyze_accesses_for_modify_stmt): Likewise.
+ 	Remove comment about the type being integral type as it is
+ 	wrong now.
+ 	(analyze_matrix_accesses): Handle POINTER_PLUS_EXPR as
+ 	PLUS_EXPR.
+ 	(transform_access_sites): POINTER_PLUS_EXPR will only show up now
+ 	and not PLUS_EXPR.
+ 	Correct the type which the artimentic is done in (is now
+ 	sizetype).
+ 	Reindent one loop.
+ 
+ 2007-06-07  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* config/ia64/ia64.c (ia64_gimplify_va_arg): Use
+ 	POINTER_PLUS_EXPR for pointers and create the
+ 	BIT_AND_EXPR in sizetype.
+ 	* config/s390/s390.c (s390_va_start): Use POINTER_PLUS_EXPR
+ 	for pointers instead of PLUS_EXPR.
+ 	(s390_gimplify_va_arg): Likewise.
+ 
+ 2007-06-07  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* config/frv/frv.c (frv_expand_builtin_va_start): Use sizetype
+ 	with make_tree, instead of a pointer type.
+ 	* config/pa/pa.c (reloc_needed): Handle POINTER_PLUS_EXPR
+ 	as PLUS_EXPR/MINUS_EXPR.
+ 	(hppa_gimplify_va_arg_expr): Don't create MINUS_EXPR or
+ 	PLUS_EXPR for pointers, instead use POINTER_PLUS_EXPR.
+ 	Don't use BIT_AND_EXPR on a pointer type, convert the
+ 	expression to sizetype first.
+ 
+ 2007-06-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree-ssa-forwprop.c
+ 	(forward_propagate_addr_into_variable_array_index):
+ 	Don't expect a statement for the size 1 case.
+ 	Use the offset variable for the size 1 case.
+ 	Look through use-def chains to find the mutliply
+ 	for the non size 1 case.
+ 	(forward_propagate_addr_expr_1): Call
+ 	forward_propagate_addr_into_variable_array_index with
+ 	the SSA_NAME instead of the statement.
+ 
+ 2007-06-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	PR tree-opt/32225
+ 	* tree-scalar-evolution.c (follow_ssa_edge_in_rhs <case
+ 	POINTER_PLUS_EXPR>): Do not change type_rhs.
+ 	(follow_ssa_edge_in_rhs <case POINTER_PLUS_EXPR, case PLUS_EXPR>):
+ 	Use the code of the orginal expression instead of just PLUS_EXPR.
+ 	Also use type_rhs where TREE_TYPE (rhs) was used (reverting back
+ 	to the trunk).
+ 
+ 2007-06-03  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree-predcom.c (ref_at_iteration): If we have a pointer
+ 	type do the multiplication in sizetype.
+ 
+ 2007-06-01  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	Merge mainline, revision 125285
+ 
+ 2007-05-31  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree-vrp.c (extract_range_from_binary_expr): Handle
+ 	MIN_EXPR/MAX_EXPR for pointers type.
+ 
+ 	PR tree-opt/32167
+ 	* tree-chrec.c (chrec_fold_plus): When either
+ 	operand is zero, convert the other operand.
+ 
+ 2007-05-30  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* builtins.c (std_expand_builtin_va_start): Use
+ 	sizetype for the call to make_tree and then convert
+ 	to the pointer type.
+ 
+ 2007-05-30  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	PR tree-op/32145
+ 	* tree-vrp.c (extract_range_from_assert): Create
+ 	POINTER_PLUS_EXPR for pointer types.
+ 
+ 	PR tree-opt/32144
+ 	* tree-chrec.c (chrec_fold_plus_poly_poly): If the
+ 	first chrec is a pointer type, then the second should
+ 	be sizetype and not the first's type.	
+ 
+ 2007-05-28  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* fold-const.c (try_move_mult_to_index):
+ 	Say why we strip the nops.
+ 	(fold_unary <case NOP_EXPR>): Remove
+ 	TODO as we cannot get that case.
+ 	* tree-chrec.c (chrec_fold_plus):
+ 	Cleanup the code to chose which
+ 	tree code is used.
+ 	(chrec_convert_rhs): Add comment on
+ 	why the increment is sizetype for
+ 	pointers.
+ 	* tree-mudflap.c (mf_xform_derefs_1):
+ 	Use size_int instead of build_int_cst.
+ 	* tree-ssa-loop-prefetch.c (issue_prefetch_ref): Likewise.
+ 
+ 2007-05-21  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	PR tree-opt/32015
+ 	* tree.c (build2_stat): Make sure that
+ 	MULT_EXPR is not used with pointers.
+ 	* tree-chrec.c (chrec_apply): Use chrec_convert_rhs
+ 	on the argument x instead of chrec_convert.
+ 
+ 2007-05-20  Kaz Kojima  <kkojima@gcc.gnu.org>
+ 
+ 	* config/sh/sh.c (sh_va_start): Call make_tree with sizetype
+ 	and convert its result to a pointer type.  Use POINTER_PLUS_EXPR
+ 	for the pointer additions and also use size_int for the offsets.
+ 	(sh_gimplify_va_arg_expr): Use POINTER_PLUS_EXPR for the pointer
+ 	additions and also use size_int for the offsets.  Perform
+ 	BIT_AND_EXPR on sizetype arguments.
+ 
+ 2007-05-15  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree-ssa-forwprop (forward_propagate_addr_into_variable_array_index):
+ 	Don't expect there to be a cast for the index as that
+ 	does not exist anymore.
+ 	(forward_propagate_addr_expr_1): Check for
+ 	POINTER_PLUS_EXPR instead of PLUS_EXPR.
+ 	Don't check for the first operand of the
+ 	POINTER_PLUS_EXPR was the index as it
+ 	cannot be.
+ 
+ 2007-05-15  Richard Guenther  <rguenther@suse.de>
+ 
+ 	* config/i386/i386.c (ix86_gimplify_va_arg): Use POINTER_PLUS_EXPR,
+ 	perform BIT_AND_EXPR on sizetype arguments.
+ 
+ 2007-05-15  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* config/rs6000/rs6000.c (rs6000_va_start): Use POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR for pointer addition.
+ 	(rs6000_va_start): Likewise.
+ 	Also use sizetype for the offset.
+ 	* tree-stdarg.c (va_list_counter_bump): Check for PLUS_EXPR
+ 	and POINTER_PLUS_EXPR.
+ 	(check_va_list_escapes): Likewise.
+ 
+ 2007-05-14  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* config/i386/i386.c (ix86_va_start): Use POINTER_PLUS_EXPR
+ 	for the pointer addition and also use size_int/sizetype
+ 	for the offset.
+ 	(ix86_gimplify_va_arg): Likewise.
+ 
+ 2007-05-14  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	Merge mainline, revision 124657
+ 	* tree-data-ref.c (split_constant_offset): Handle
+ 	POINTER_PLUS_EXPR
+ 	exactly the same as PLUS_EXPR/MINUS_EXPR except for the offset
+ 	needs to be calcuated using PLUS_EXPR instead of
+ 	POINTER_PLUS_EXPR.
+ 	* builtins.c (fold_builtin_memchr): Use POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR for adding to a pointer.
+ 
+ 2006-05-15  Zdenek Dvorak <dvorakz@suse.cz>
+ 
+ 	* tree-ssa-loop-ivopts.c (determine_base_object): Abort for PLUS_EXPR
+ 	in pointer type.
+ 
+ 2007-05-12  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree-ssa-address.c (tree_mem_ref_addr): When adding
+ 	the offset to the base, use POINTER_PLUS_EXPR.
+ 
+ 2007-05-12  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* expr.c (expand_expr_addr_expr_1): Call expand_expr
+ 	for the offset with the modifier as EXPAND_INITIALIZER
+ 	if the modifier is EXPAND_INITIALIZER.
+ 	(expand_expr_real_1 <case INTEGER_CST>): Don't force to
+ 	a register if we had an overflow.
+ 
+ 2007-05-10  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	Merge mainline, revision 124602.
+ 
+ 	* fold-const.c  (extract_array_ref): Make sure the offset
+ 	is converted to sizetype.
+ 	(try_move_mult_to_index): Strip the NOPs from the offset.
+ 	(fold_binary <case POINTER_PLUS_EXPR>): Convert the second
+ 	operand to sizetype before calling try_move_mult_to_index.
+ 	* tree-ssa-loop-niter.c (number_of_iterations_lt_to_ne):
+ 	For pointer types, use sizetype when
+ 	creating MINUS_EXPR/PLUS_EXPRs.
+ 	* tree-ssa-ccp.c (maybe_fold_stmt_indirect): Make sure
+ 	the offset is converted to sizetype.
+ 
+ 2007-05-11  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* config/spu/spu.c (spu_va_start): Create POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR when doing addition on pointer
+ 	types.  Use sizetype for the second operand.
+ 	(spu_gimplify_va_arg_expr): Likewise.
+ 	* tree-ssa.c (tree_ssa_useless_type_conversion_1):
+ 	Convert the MIN/MAX of the inner type to the outer
+ 	type before comparing them.
+ 
+ 2007-05-09  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 	    Zdenek Dvorak  <dvorakz@suse.cz>
+ 
+ 	* fold-const.c  (fold_to_nonsharp_ineq_using_bound): Don't
+ 	use a pointer type for MINUS_EXPR.
+ 	(fold_binary <case MINUS_EXPR>): Fold (PTR0 p+ A) - (PTR1 p+ B)
+ 	into (PTR0 - PTR1) + (A - B). Fold (PTR0 p+ A) - PTR1 into
+ 	(PTR0 - PTR1) + A iff (PTR0 - PTR1) simplifies.
+ 	* tree-chrec.c (chrec_fold_plus_poly_poly): For
+ 	POINTER_PLUS_EXPR, use a different right hand side type.
+ 	Handle POINTER_PLUS_EXPR like PLUS_EXPR.
+ 	(chrec_fold_plus_1): Likewise.
+ 	(convert_affine_scev): Likewise.
+ 	(chrec_convert_aggressive): Likewise.
+ 	(chrec_fold_plus): For pointer types, use POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR.
+ 	(reset_evolution_in_loop): For pointer types, the new_evol
+ 	should be sizetype.
+ 	(chrec_convert_rhs): New function.
+ 	* tree-chrec.h (chrec_convert_rhs): New prototype.
+ 	(build_polynomial_chrec): For pointer types, the right hand
+ 	side should be sizetype and not the same as the left hand side.
+ 	* tree-scalar-evolution.c (add_to_evolution_1): Convert the
+ 	increment using chrec_convert_rhs instead of chrec_convert.
+ 	(follow_ssa_edge_in_rhs): Handle POINTER_PLUS_EXPR like
+ 	PLUS_EXPR except for the right hand side's type will be
+ 	sizetype.
+ 	(interpret_rhs_modify_stmt): Handle POINTER_PLUS_EXPR.
+ 	(fold_used_pointer_cast): Kill.
+ 	(pointer_offset_p): Kill.
+ 	(fold_used_pointer): Kill.
+ 	(pointer_used_p): Kill.
+ 	(analyze_scalar_evolution_1 <case GIMPLE_MODIFY_STMT>): Don't
+ 	call fold_used_pointer.
+ 	(instantiate_parameters_1): Convert the increment
+ 	using chrec_convert_rhs instead of chrec_convert.
+ 	Handle POINTER_PLUS_EXPR as PLUS_EXPR.
+ 	* tree-ssa-loop-niter.c (split_to_var_and_offset): Handle
+ 	POINTER_PLUS_EXPR as PLUS_EXPR.
+ 	(assert_loop_rolls_lt): For pointer types, use sizetype when
+ 	creating MINUS_EXPR/PLUS_EXPRs.
+ 	(number_of_iterations_le): Likewise.
+ 	(expand_simple_operations): POINTER_PLUS_EXPR are simple also.
+ 	(derive_constant_upper_bound): Handle POINTER_PLUS_EXPR just
+ 	like PLUS_EXPR and MINUS_EXPR.
+ 	* tree-data-ref.c (analyze_offset_expr): Likewise.
+ 	(address_analysis): Handle POINTER_PLUS_EXPR as PLUS_EXPR.
+ 	(analyze_offset): Handle POINTER_PLUS_EXPR also.
+ 	(create_data_ref): Convert the increment
+ 	using chrec_convert_rhs instead of chrec_convert.
+ 	* tree-vect-transform.c (vect_update_ivs_after_vectorizer):
+ 	For pointer types, create POINTER_PLUS_EXPR instead of
+ 	PLUS_EXPR and also create MULT_EXPR in sizetype.
+ 
+ 2007-05-07  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* builtins.c (std_gimplify_va_arg_expr): Use fold_build2 for
+ 	the creating of POINTER_PLUS_EXPR.  For the BIT_AND_EXPR, cast
+ 	the operands to sizetype first and then cast the BIT_AND_EXPR
+ 	back to the pointer type.
+ 	* tree-ssa-address.c (create_mem_ref): Create A
+ 	POINTER_PLUS_EXPR for one case.
+ 	* tree.c (const_hash_1): Handle POINTER_PLUS_EXPR same as
+ 	PLUS_EXPR.
+ 	(compare_constant): Likewise.
+ 	(copy_constant): Likewise.
+ 	(compute_reloc_for_constant): Likewise.
+ 	(output_addressed_constants): Likewise.
+ 
+ 2007-05-07  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree.def (POINTER_PLUS_EXPR): The second operand
+ 	is of type sizetype and not ssizetype.
+ 	* doc/c-tree.texi (POINTER_PLUS_EXPR): Document.
+ 
+ 2007-05-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree-mudflap.c (mf_xform_derefs_1 <case BIT_FIELD_REF>):
+ 	Add a conversion of ofs to sizetype.
+ 	(mf_decl_eligible_p): Reformat for length issues.
+ 	(mf_xform_derefs_1): Likewise.
+ 
+ 2007-05-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree.c (build2_stat): Check to make sure the
+ 	second operand is compatiable with sizetype.
+ 
+ 2007-05-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree-cfg.c (verify_expr): Change error
+ 	message about sizetype to be correct.
+ 
+ 2007-05-06  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	Merge mainline, revision 124478.
+ 	* fold-const.c (fold_unary): Handle for (T1)(X op Y),
+ 	only p+ as that is the only as that can be handled for
+ 	binary operators now.  Add a TODO for non pointer type
+ 	op's.
+ 	* gimplifier.c (gimplify_expr): Don't special case
+ 	PLUS_EXPR.  Special case POINTER_PLUS_EXPR instead,
+ 	remove check for pointer type as it will always be
+ 	a pointer type now.
+ 
+ 2007-05-04  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree-vrp.c (extract_range_from_binary_expr): Handle
+ 	POINTER_PLUS_EXPRs.  Assert POINTER_PLUS_EXPR is
+ 	the only expression for pointer types.
+ 	* tree-vect-transform.c (vect_gen_niters_for_prolog_loop):
+ 	Add a cast when creating byte_misalign.
+ 
+ 2007-05-04  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* fold-const.c (fold_binary <case POINTER_PLUS_EXPR>);
+ 	Add comment on why you get INT +p INT.
+ 	(fold_binary <case PLUS_EXPR>): Add folding of PTR+INT into
+ 	PTR p+ INT.
+ 	* dwarf2out.c (loc_descriptor_from_tree_1):
+ 	Handle POINT_PLUS_EXPR as a PLUS_EXPR.
+ 
+ 2007-05-04  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree-vrp.c  (compare_values_warnv): Convert val2 to
+ 	the type of val1.
+ 	* fold-const.c (extract_array_ref): Look for
+ 	POINTER_PLUS_EXPR instead of PLUS_EXPR's.
+ 	* tree-ssa-ccp.c (maybe_fold_stmt_indirect): Likewise.
+ 
+ 2007-05-02  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* c-format.c (check_format_arg): Handle POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR of pointer types.
+ 
+ 2007-05-02  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* fold-const.c (try_move_mult_to_index): Remove code argument
+ 	and replace all uses with PLUS_EXPR.
+ 	(fold_binary <case POINTER_PLUS_EXR>): Remove code argument.
+ 	(fold_binary <case PLUS_EXPR>): Don't call try_move_mult_to_index.
+ 	(fold_binary <case MINUS_EXPR>): Likewise.
+ 	* tree-ssa-ccp.c (maybe_fold_stmt_indirect): Remove subtraction
+ 	case as it is always addition now.
+ 	(fold_stmt_r): Don't handle PLUS_EXPR/MINUS_EXPR specially.
+ 	Handle POINTER_PLUS_EXPR like PLUS_EXPR was handled before.
+ 
+ 2007-05-01  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	Merge mainline, revision 124343.
+ 	* tree-vect-transform.c (bump_vector_ptr): Create a POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR for the pointer increment statement.
+ 	* expr.c (expand_expr_real_1): Add FIXME/assert for the unhandle case
+ 	where the modes of the two operands are different.
+ 
+ 2007-02-25  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	Merge mainline, revision 122323.
+ 
+ 2006-12-14  Zdenek Dvorak <dvorakz@suse.cz>
+ 
+ 	Merge mainline, revision 119860.
+ 
+ 2006-11-23  Andrew Pinski  <andrew_pinski@playstation.sony.com>
+ 
+ 	* tree.def (POINTER_PLUS_EXPR): New tree code.
+ 	* tree-pretty-print.c (dump_generic_node): Handle
+ 	POINTER_PLUS_EXPR.
+ 	(op_prio): Likewise.
+ 	(op_symbol_1): Likewise.
+ 	* optabs.c (optab_for_tree_code): Likewise.
+ 	* tree-ssa-loop-manip.c (create_iv): Handle pointer base
+ 	specially.
+ 	* tree-tailcall.c (process_assignment): Mention
+ 	POINTER_PLUS_EXPR in a TODO comment.
+ 	* tree.c (build2_stat): Assert when trying to use PLUS_EXPR or 
+ 	MINUS_EXPR with a pointer. Also assert for POINTER_PLUS_EXPR
+ 	not used with a pointer and an integer type.
+ 	*  tree-scalar-evolution.c (fold_used_pointer): Mention
+ 	POINTER_PLUS_EXPR is what this needs to handle.
+ 	* builtins.c (get_pointer_alignment): Handle POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR.
+ 	(expand_builtin_strcat): Create a POINTER_PLUS_EXPR instead of
+ 	PLUS_EXPR for pointers.
+ 	(std_gimplify_va_arg_expr): Likewise.
+ 	(fold_builtin_memory_op): Likewise.
+ 	(fold_builtin_strstr): Likewise.
+ 	(fold_builtin_strchr): Likewise.
+ 	(fold_builtin_strrchr): Likewise.
+ 	(fold_builtin_strpbrk): Likewise.
+ 	(expand_builtin_memory_chk): Likewise.
+ 	(fold_builtin_memory_chk): Likewise.
+ 	* fold-const.c (build_range_check): Handle pointer types
+ 	specially.
+ 	(fold_to_nonsharp_ineq_using_bound): Likewise.
+ 	(fold_binary): Handle simple POINTER_PLUS_EXPR cases.
+ 	(tree_expr_nonnegative_p): Handle POINTER_PLUS_EXPR.
+ 	(tree_expr_nonzero_p): Likewise.
+ 	(fold_indirect_ref_1): Look at POINTER_PLUS_EXPR instead
+ 	of PLUS_EXPR for the complex expression folding.
+ 	* tree-ssa-loop-ivopts.c (determine_base_object): Handle
+ 	POINTER_PLUS_EXPR.
+ 	(tree_to_aff_combination): Likewise.
+ 	(force_expr_to_var_cost): Likewise.
+ 	(force_expr_to_var_cost): Likewise. Create a POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR for pointers.
+ 	* c-format.c (check_format_arg): Mention this should be handling
+ 	POINTER_PLUS_EXPR.
+ 	* tree-stdarg.c (va_list_counter_bump): Handle POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR.
+ 	(check_va_list_escapes): Likewise.
+ 	(check_all_va_list_escapes): Likewise.
+ 	* expr.c (expand_expr_real_1): Handle POINTER_PLUS_EXPR.
+ 	(string_constant): Likewise.
+ 	* tree-ssa-address.c (add_to_parts): Create a POINTER_PLUS_EXPR
+ 	instead of PLUS_EXPR for pointers.
+ 	(most_expensive_mult_to_index): Likewise.
+ 	(addr_to_parts): Use the correct type for the index.
+ 	* c-typeck.c (build_unary_op): For pointers create the increment
+ 	as a sizetype. Create a POINTER_PLUS_EXPR instead of PLUS_EXPR
+ 	for pointers.
+ 	* gimplify.c (gimplify_self_mod_expr): Create a
+ 	POINTER_PLUS_EXPR instead of PLUS_EXPR for pointers.
+ 	(gimplify_omp_atomic_fetch_op): Handle POINTER_PLUS_EXPR.
+ 	* tree-mudflap.c (mf_xform_derefs_1): Create a
+ 	POINTER_PLUS_EXPR instead of PLUS_EXPR for pointers.
+ 	* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Add a
+ 	note this should be handling POINTER_PLUS_EXPR.
+ 	* varasm.c (initializer_constant_valid_p): Handle
+ 	POINTER_PLUS_EXPR.
+ 	* tree-ssa-loop-prefetch.c (idx_analyze_ref):  Handle
+ 	POINTER_PLUS_EXPR instead of PLUS_EXPR.
+ 	(issue_prefetch_ref): Create a POINTER_PLUS_EXPR instead
+ 	of PLUS_EXPR for pointers.
+ 	* tree-vect-transform.c (vect_create_addr_base_for_vector_ref):
+ 	Likewise.
+ 	* tree-inline.c (estimate_num_insns_1): Handle
+ 	POINTER_PLUS_EXPR.
+ 	* tree-object-size.c (plus_expr_object_size): Handle
+ 	POINTER_PLUS_EXPR instead of PLUS_EXPR.  Removing all the extra
+ 	code which is trying to figure out which side is a pointer and 
+ 	is the index.
+ 	(check_for_plus_in_loops_1): Likewise.
+ 	(check_for_plus_in_loops): Likewise.
+ 	* c-common.c (pointer_int_sum): Create a
+ 	POINTER_PLUS_EXPR instead of PLUS_EXPR for pointers.
+ 	* tree-ssa-structalias.c (handle_ptr_arith): Handle
+ 	only POINTER_PLUS_EXPR.  Removing all the extra
+ 	code which is trying to figure out which side is a pointer and 
+ 	is the index.
+ 	* tree-cfg.c (verify_expr): Add extra checking for pointers and
+ 	PLUS_EXPR and MINUS_EXPR.
+ 	Also add checking to make sure the operands of POINTER_PLUS_EXPR
+ 	are correct.
+ 
+ 
Index: c-typeck.c
===================================================================
*** c-typeck.c	(.../trunk/gcc)	(revision 125658)
--- c-typeck.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** build_unary_op (enum tree_code code, tre
*** 2959,2969 ****
  	      }
  
  	    inc = c_size_in_bytes (TREE_TYPE (result_type));
  	  }
  	else
! 	  inc = integer_one_node;
! 
! 	inc = convert (argtype, inc);
  
  	/* Complain about anything else that is not a true lvalue.  */
  	if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
--- 2959,2971 ----
  	      }
  
  	    inc = c_size_in_bytes (TREE_TYPE (result_type));
+ 	    inc = convert (sizetype, inc);
  	  }
  	else
! 	  {
! 	    inc = integer_one_node;
! 	    inc = convert (argtype, inc);
! 	  }
  
  	/* Complain about anything else that is not a true lvalue.  */
  	if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
*************** build_unary_op (enum tree_code code, tre
*** 3051,3060 ****
        if (val && TREE_CODE (val) == INDIRECT_REF
            && TREE_CONSTANT (TREE_OPERAND (val, 0)))
  	{
! 	  tree op0 = fold_convert (argtype, fold_offsetof (arg, val)), op1;
  
  	  op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
! 	  return fold_build2 (PLUS_EXPR, argtype, op0, op1);
  	}
  
        val = build1 (ADDR_EXPR, argtype, arg);
--- 3053,3062 ----
        if (val && TREE_CODE (val) == INDIRECT_REF
            && TREE_CONSTANT (TREE_OPERAND (val, 0)))
  	{
! 	  tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
  
  	  op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
! 	  return fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
  	}
  
        val = build1 (ADDR_EXPR, argtype, arg);
Index: gimplify.c
===================================================================
*** gimplify.c	(.../trunk/gcc)	(revision 125658)
--- gimplify.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** gimplify_self_mod_expr (tree *expr_p, tr
*** 1960,1965 ****
--- 1960,1974 ----
  	return ret;
      }
  
+   /* For POINTERs increment, use POINTER_PLUS_EXPR.  */
+   if (POINTER_TYPE_P (TREE_TYPE (lhs)))
+     {
+       rhs = fold_convert (sizetype, rhs);
+       if (arith_code == MINUS_EXPR)
+ 	rhs = fold_build1 (NEGATE_EXPR, TREE_TYPE (rhs), rhs);
+       arith_code = POINTER_PLUS_EXPR;
+     }
+ 
    t1 = build2 (arith_code, TREE_TYPE (*expr_p), lhs, rhs);
    t1 = build_gimple_modify_stmt (lvalue, t1);
  
*************** gimplify_omp_atomic_fetch_op (tree *expr
*** 5125,5130 ****
--- 5134,5140 ----
    /* Check for one of the supported fetch-op operations.  */
    switch (TREE_CODE (rhs))
      {
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        base = BUILT_IN_FETCH_AND_ADD_N;
        optab = sync_add_optab;
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 5875,5886 ****
  	  ret = GS_ALL_DONE;
  	  break;
  
! 	case PLUS_EXPR:
            /* Convert ((type *)A)+offset into &A->field_of_type_and_offset.
  	     The second is gimple immediate saving a need for extra statement.
  	   */
! 	  if (POINTER_TYPE_P (TREE_TYPE (*expr_p))
! 	      && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
  	      && (tmp = maybe_fold_offset_to_reference
  			 (TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
  		   	  TREE_TYPE (TREE_TYPE (*expr_p)))))
--- 5885,5895 ----
  	  ret = GS_ALL_DONE;
  	  break;
  
! 	case POINTER_PLUS_EXPR:
            /* Convert ((type *)A)+offset into &A->field_of_type_and_offset.
  	     The second is gimple immediate saving a need for extra statement.
  	   */
! 	  if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
  	      && (tmp = maybe_fold_offset_to_reference
  			 (TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
  		   	  TREE_TYPE (TREE_TYPE (*expr_p)))))
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 5890,5897 ****
  	       break;
  	     }
  	  /* Convert (void *)&a + 4 into (void *)&a[1].  */
! 	  if (POINTER_TYPE_P (TREE_TYPE (*expr_p))
! 	      && TREE_CODE (TREE_OPERAND (*expr_p, 0)) == NOP_EXPR
  	      && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
  	      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p,
  									0),0)))
--- 5899,5905 ----
  	       break;
  	     }
  	  /* Convert (void *)&a + 4 into (void *)&a[1].  */
! 	  if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == NOP_EXPR
  	      && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
  	      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p,
  									0),0)))
Index: tree.def
===================================================================
*** tree.def	(.../trunk/gcc)	(revision 125658)
--- tree.def	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** DEFTREECODE (PLUS_EXPR, "plus_expr", tcc
*** 612,617 ****
--- 612,621 ----
  DEFTREECODE (MINUS_EXPR, "minus_expr", tcc_binary, 2)
  DEFTREECODE (MULT_EXPR, "mult_expr", tcc_binary, 2)
  
+ /* Plus expression but for pointers in that the first operand is always a pointer
+    and the second operand is an integer which is the same type as the sizetype.  */
+ DEFTREECODE (POINTER_PLUS_EXPR, "pointer_plus_expr", tcc_binary, 2)
+ 
  /* Division for integer result that rounds the quotient toward zero.  */
  DEFTREECODE (TRUNC_DIV_EXPR, "trunc_div_expr", tcc_binary, 2)
  
Index: tree-predcom.c
===================================================================
*** tree-predcom.c	(.../trunk/gcc)	(revision 125658)
--- tree-predcom.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** ref_at_iteration (struct loop *loop, tre
*** 1350,1358 ****
    else
      {
        type = TREE_TYPE (iv.base);
!       val = fold_build2 (MULT_EXPR, type, iv.step,
! 			 build_int_cst_type (type, iter));
!       val = fold_build2 (PLUS_EXPR, type, iv.base, val);
        *idx_p = unshare_expr (val);
      }
  
--- 1350,1367 ----
    else
      {
        type = TREE_TYPE (iv.base);
!       if (POINTER_TYPE_P (type))
! 	{
! 	  val = fold_build2 (MULT_EXPR, sizetype, iv.step,
! 			     size_int (iter));
! 	  val = fold_build2 (POINTER_PLUS_EXPR, type, iv.base, val);
! 	}
!       else
! 	{
! 	  val = fold_build2 (MULT_EXPR, type, iv.step,
! 			     build_int_cst_type (type, iter));
! 	  val = fold_build2 (PLUS_EXPR, type, iv.base, val);
! 	}
        *idx_p = unshare_expr (val);
      }
  
Index: tree-mudflap.c
===================================================================
*** tree-mudflap.c	(.../trunk/gcc)	(revision 125658)
--- tree-mudflap.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** mf_decl_eligible_p (tree decl)
*** 699,705 ****
            /* The decl must have its address taken.  In the case of
               arrays, this flag is also set if the indexes are not
               compile-time known valid constants.  */
!           && TREE_ADDRESSABLE (decl)    /* XXX: not sufficient: return-by-value structs! */
            /* The type of the variable must be complete.  */
            && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
  	  /* The decl hasn't been decomposed somehow.  */
--- 699,706 ----
            /* The decl must have its address taken.  In the case of
               arrays, this flag is also set if the indexes are not
               compile-time known valid constants.  */
!           && TREE_ADDRESSABLE (decl)
! 		    /* XXX: not sufficient: return-by-value structs! */
            /* The type of the variable must be complete.  */
            && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
  	  /* The decl hasn't been decomposed somehow.  */
*************** mf_xform_derefs_1 (block_stmt_iterator *
*** 758,764 ****
          while (1)
            {
  	    if (bitfield_ref_p && elt == NULL_TREE
! 		&& (TREE_CODE (var) == ARRAY_REF || TREE_CODE (var) == COMPONENT_REF))
  	      elt = var;
  	
              if (TREE_CODE (var) == ARRAY_REF)
--- 759,766 ----
          while (1)
            {
  	    if (bitfield_ref_p && elt == NULL_TREE
! 		&& (TREE_CODE (var) == ARRAY_REF 
! 		    || TREE_CODE (var) == COMPONENT_REF))
  	      elt = var;
  	
              if (TREE_CODE (var) == ARRAY_REF)
*************** mf_xform_derefs_1 (block_stmt_iterator *
*** 787,793 ****
                    return;
                  else
  		  {
! 		    base = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (var)), var);
  		    break;
  		  }
                }
--- 789,796 ----
                    return;
                  else
  		  {
! 		    base = build1 (ADDR_EXPR,
! 				   build_pointer_type (TREE_TYPE (var)), var);
  		    break;
  		  }
                }
*************** mf_xform_derefs_1 (block_stmt_iterator *
*** 810,819 ****
                size = DECL_SIZE_UNIT (field);
              
  	    if (elt)
! 	      elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)), elt);
              addr = fold_convert (ptr_type_node, elt ? elt : base);
!             addr = fold_build2 (PLUS_EXPR, ptr_type_node,
! 				addr, fold_convert (ptr_type_node,
  						    byte_position (field)));
            }
          else
--- 813,823 ----
                size = DECL_SIZE_UNIT (field);
              
  	    if (elt)
! 	      elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)),
! 			    elt);
              addr = fold_convert (ptr_type_node, elt ? elt : base);
!             addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
! 				addr, fold_convert (sizetype,
  						    byte_position (field)));
            }
          else
*************** mf_xform_derefs_1 (block_stmt_iterator *
*** 830,846 ****
      case INDIRECT_REF:
        addr = TREE_OPERAND (t, 0);
        base = addr;
!       limit = fold_build2 (MINUS_EXPR, ptr_type_node,
!                            fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
!                            integer_one_node);
        break;
  
      case TARGET_MEM_REF:
        addr = tree_mem_ref_addr (ptr_type_node, t);
        base = addr;
!       limit = fold_build2 (MINUS_EXPR, ptr_type_node,
! 			   fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
! 			   build_int_cst (ptr_type_node, 1));
        break;
  
      case ARRAY_RANGE_REF:
--- 834,852 ----
      case INDIRECT_REF:
        addr = TREE_OPERAND (t, 0);
        base = addr;
!       limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
! 			   fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base,
! 					size),
! 			   size_int (-1));
        break;
  
      case TARGET_MEM_REF:
        addr = tree_mem_ref_addr (ptr_type_node, t);
        base = addr;
!       limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
! 			   fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base,
! 					size),
! 			   size_int (-1));
        break;
  
      case ARRAY_RANGE_REF:
*************** mf_xform_derefs_1 (block_stmt_iterator *
*** 860,866 ****
          bpu = bitsize_int (BITS_PER_UNIT);
          ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
          rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
!         ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
  
          size = convert (bitsizetype, TREE_OPERAND (t, 1));
          size = size_binop (PLUS_EXPR, size, rem);
--- 866,872 ----
          bpu = bitsize_int (BITS_PER_UNIT);
          ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
          rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
!         ofs = fold_convert (sizetype, size_binop (TRUNC_DIV_EXPR, ofs, bpu));
  
          size = convert (bitsizetype, TREE_OPERAND (t, 1));
          size = size_binop (PLUS_EXPR, size, rem);
*************** mf_xform_derefs_1 (block_stmt_iterator *
*** 869,880 ****
  
          addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
          addr = convert (ptr_type_node, addr);
!         addr = fold_build2 (PLUS_EXPR, ptr_type_node, addr, ofs);
  
          base = addr;
!         limit = fold_build2 (MINUS_EXPR, ptr_type_node,
!                              fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
!                              integer_one_node);
        }
        break;
  
--- 875,887 ----
  
          addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
          addr = convert (ptr_type_node, addr);
!         addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, ofs);
  
          base = addr;
!         limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
!                              fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
! 					   base, size),
!                              size_int (-1));
        }
        break;
  
Index: tree-ssa-forwprop.c
===================================================================
*** tree-ssa-forwprop.c	(.../trunk/gcc)	(revision 125658)
--- tree-ssa-forwprop.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** forward_propagate_addr_into_variable_arr
*** 504,523 ****
  {
    tree index;
  
-   /* The offset must be defined by a simple GIMPLE_MODIFY_STMT statement.  */
-   if (TREE_CODE (offset) != GIMPLE_MODIFY_STMT)
-     return false;
- 
-   /* The RHS of the statement which defines OFFSET must be a gimple
-      cast of another SSA_NAME.  */
-   offset = GIMPLE_STMT_OPERAND (offset, 1);
-   if (!is_gimple_cast (offset))
-     return false;
- 
-   offset = TREE_OPERAND (offset, 0);
-   if (TREE_CODE (offset) != SSA_NAME)
-     return false;
- 
    /* Try to find an expression for a proper index.  This is either
       a multiplication expression by the element size or just the
       ssa name we came along in case the element size is one.  */
--- 504,509 ----
*************** forward_propagate_addr_into_variable_arr
*** 525,538 ****
      index = offset;
    else
      {
        offset = SSA_NAME_DEF_STMT (offset);
  
!       /* The RHS of the statement which defines OFFSET must be a
! 	 multiplication of an object by the size of the array elements.  */
        if (TREE_CODE (offset) != GIMPLE_MODIFY_STMT)
  	return false;
  
!       offset = GIMPLE_STMT_OPERAND (offset, 1);
        if (TREE_CODE (offset) != MULT_EXPR
  	  || TREE_CODE (TREE_OPERAND (offset, 1)) != INTEGER_CST
  	  || !simple_cst_equal (TREE_OPERAND (offset, 1),
--- 511,529 ----
      index = offset;
    else
      {
+       /* Get the offset's defining statement.  */
        offset = SSA_NAME_DEF_STMT (offset);
  
!       /* The statement which defines OFFSET before type conversion
!          must be a simple GIMPLE_MODIFY_STMT.  */
        if (TREE_CODE (offset) != GIMPLE_MODIFY_STMT)
  	return false;
  
!       /* The RHS of the statement which defines OFFSET must be a
! 	 multiplication of an object by the size of the array elements. 
! 	 This implicitly verifies that the size of the array elements
! 	 is constant.  */
!      offset = GIMPLE_STMT_OPERAND (offset, 1);
        if (TREE_CODE (offset) != MULT_EXPR
  	  || TREE_CODE (TREE_OPERAND (offset, 1)) != INTEGER_CST
  	  || !simple_cst_equal (TREE_OPERAND (offset, 1),
*************** forward_propagate_addr_expr_1 (tree name
*** 644,653 ****
  
    /* If the use of the ADDR_EXPR must be a PLUS_EXPR, or else there
       is nothing to do. */
!   if (TREE_CODE (rhs) != PLUS_EXPR)
      return false;
  
!   /* Try to optimize &x[0] + C where C is a multiple of the size
       of the elements in X into &x[C/element size].  */
    if (TREE_OPERAND (rhs, 0) == name
        && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
--- 635,644 ----
  
    /* If the use of the ADDR_EXPR must be a PLUS_EXPR, or else there
       is nothing to do. */
!   if (TREE_CODE (rhs) != POINTER_PLUS_EXPR)
      return false;
  
!   /* Try to optimize &x[0] p+ C where C is a multiple of the size
       of the elements in X into &x[C/element size].  */
    if (TREE_OPERAND (rhs, 0) == name
        && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
*************** forward_propagate_addr_expr_1 (tree name
*** 671,677 ****
  	}
      }
  
!   /* Try to optimize &x[0] + OFFSET where OFFSET is defined by
       converting a multiplication of an index by the size of the
       array elements, then the result is converted into the proper
       type for the arithmetic.  */
--- 662,668 ----
  	}
      }
  
!   /* Try to optimize &x[0] p+ OFFSET where OFFSET is defined by
       converting a multiplication of an index by the size of the
       array elements, then the result is converted into the proper
       type for the arithmetic.  */
*************** forward_propagate_addr_expr_1 (tree name
*** 682,705 ****
        && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
      {
        bool res;
-       tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 1));
        
!       res = forward_propagate_addr_into_variable_array_index (offset_stmt,
! 							      def_rhs, use_stmt);
!       return res;
!     }
! 	      
!   /* Same as the previous case, except the operands of the PLUS_EXPR
!      were reversed.  */
!   if (TREE_OPERAND (rhs, 1) == name
!       && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
!       /* Avoid problems with IVopts creating PLUS_EXPRs with a
! 	 different type than their operands.  */
!       && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
!     {
!       bool res;
!       tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0));
!       res = forward_propagate_addr_into_variable_array_index (offset_stmt,
  							      def_rhs, use_stmt);
        return res;
      }
--- 673,680 ----
        && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
      {
        bool res;
        
!       res = forward_propagate_addr_into_variable_array_index (TREE_OPERAND (rhs, 1),
  							      def_rhs, use_stmt);
        return res;
      }
*************** phiprop_insert_phi (basic_block bb, tree
*** 1174,1180 ****
  	}
  
        if (TREE_CODE (old_arg) == SSA_NAME)
! 	/* Reuse a formerly created dereference.  */
  	new_var = phivn[SSA_NAME_VERSION (old_arg)].value;
        else
  	{
--- 1149,1155 ----
  	}
  
        if (TREE_CODE (old_arg) == SSA_NAME)
! 	/* Reuse a formely created dereference.  */
  	new_var = phivn[SSA_NAME_VERSION (old_arg)].value;
        else
  	{
Index: varasm.c
===================================================================
*** varasm.c	(.../trunk/gcc)	(revision 125658)
--- varasm.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** const_hash_1 (const tree exp)
*** 2810,2815 ****
--- 2810,2816 ----
        return hi;
  
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
      case MINUS_EXPR:
        return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9
  	      + const_hash_1 (TREE_OPERAND (exp, 1)));
*************** compare_constant (const tree t1, const t
*** 2956,2961 ****
--- 2957,2963 ----
        }
  
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
      case MINUS_EXPR:
      case RANGE_EXPR:
        return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
*************** copy_constant (tree exp)
*** 3010,3015 ****
--- 3012,3018 ----
  			    copy_constant (TREE_IMAGPART (exp)));
  
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
      case MINUS_EXPR:
        return build2 (TREE_CODE (exp), TREE_TYPE (exp),
  		     copy_constant (TREE_OPERAND (exp, 0)),
*************** compute_reloc_for_constant (tree exp)
*** 3901,3906 ****
--- 3904,3910 ----
        break;
  
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
        reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
        reloc |= compute_reloc_for_constant (TREE_OPERAND (exp, 1));
        break;
*************** output_addressed_constants (tree exp)
*** 3970,3975 ****
--- 3974,3980 ----
        break;
  
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
      case MINUS_EXPR:
        output_addressed_constants (TREE_OPERAND (exp, 1));
        /* Fall through.  */
*************** initializer_constant_valid_p (tree value
*** 4147,4152 ****
--- 4152,4158 ----
        }
        break;
  
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        if (! INTEGRAL_TYPE_P (endtype)
  	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
Index: tree-ssa.c
===================================================================
*** tree-ssa.c	(.../trunk/gcc)	(revision 125658)
--- tree-ssa.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** tree_ssa_useless_type_conversion_1 (tree
*** 949,961 ****
    else if (INTEGRAL_TYPE_P (inner_type)
             && INTEGRAL_TYPE_P (outer_type)
  	   && TYPE_UNSIGNED (inner_type) == TYPE_UNSIGNED (outer_type)
! 	   && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type)
! 	   && simple_cst_equal (TYPE_MAX_VALUE (inner_type), TYPE_MAX_VALUE (outer_type))
! 	   && simple_cst_equal (TYPE_MIN_VALUE (inner_type), TYPE_MIN_VALUE (outer_type)))
      {
        bool first_boolean = (TREE_CODE (inner_type) == BOOLEAN_TYPE);
        bool second_boolean = (TREE_CODE (outer_type) == BOOLEAN_TYPE);
!       if (first_boolean == second_boolean)
  	return true;
      }
  
--- 949,963 ----
    else if (INTEGRAL_TYPE_P (inner_type)
             && INTEGRAL_TYPE_P (outer_type)
  	   && TYPE_UNSIGNED (inner_type) == TYPE_UNSIGNED (outer_type)
! 	   && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
      {
+       tree min_inner = fold_convert (outer_type, TYPE_MIN_VALUE (inner_type));
+       tree max_inner = fold_convert (outer_type, TYPE_MAX_VALUE (inner_type));
        bool first_boolean = (TREE_CODE (inner_type) == BOOLEAN_TYPE);
        bool second_boolean = (TREE_CODE (outer_type) == BOOLEAN_TYPE);
!       if (simple_cst_equal (max_inner, TYPE_MAX_VALUE (outer_type))
! 	  && simple_cst_equal (min_inner, TYPE_MIN_VALUE (outer_type))
! 	  && first_boolean == second_boolean)
  	return true;
      }
  
Index: tree-ssa-loop-prefetch.c
===================================================================
*** tree-ssa-loop-prefetch.c	(.../trunk/gcc)	(revision 125658)
--- tree-ssa-loop-prefetch.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** idx_analyze_ref (tree base, tree *index,
*** 375,381 ****
      return false;
    istep = int_cst_value (step);
  
!   if (TREE_CODE (ibase) == PLUS_EXPR
        && cst_and_fits_in_hwi (TREE_OPERAND (ibase, 1)))
      {
        idelta = int_cst_value (TREE_OPERAND (ibase, 1));
--- 375,381 ----
      return false;
    istep = int_cst_value (step);
  
!   if (TREE_CODE (ibase) == POINTER_PLUS_EXPR
        && cst_and_fits_in_hwi (TREE_OPERAND (ibase, 1)))
      {
        idelta = int_cst_value (TREE_OPERAND (ibase, 1));
*************** issue_prefetch_ref (struct mem_ref *ref,
*** 891,898 ****
      {
        /* Determine the address to prefetch.  */
        delta = (ahead + ap * ref->prefetch_mod) * ref->group->step;
!       addr = fold_build2 (PLUS_EXPR, ptr_type_node,
! 			  addr_base, build_int_cst (ptr_type_node, delta));
        addr = force_gimple_operand_bsi (&bsi, unshare_expr (addr), true, NULL);
  
        /* Create the prefetch instruction.  */
--- 891,898 ----
      {
        /* Determine the address to prefetch.  */
        delta = (ahead + ap * ref->prefetch_mod) * ref->group->step;
!       addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
! 			  addr_base, size_int (delta));
        addr = force_gimple_operand_bsi (&bsi, unshare_expr (addr), true, NULL);
  
        /* Create the prefetch instruction.  */
Index: tree-inline.c
===================================================================
*** tree-inline.c	(.../trunk/gcc)	(revision 125658)
--- tree-inline.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** estimate_num_insns_1 (tree *tp, int *wal
*** 2085,2090 ****
--- 2085,2091 ----
      case VEC_COND_EXPR:
  
      case PLUS_EXPR:
+     case POINTER_PLUS_EXPR:
      case MINUS_EXPR:
      case MULT_EXPR:
  
Index: tree-vect-transform.c
===================================================================
*** tree-vect-transform.c	(.../trunk/gcc)	(revision 125658)
--- tree-vect-transform.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** vect_create_addr_base_for_vector_ref (tr
*** 635,640 ****
--- 635,641 ----
  
    /* Create base_offset */
    base_offset = size_binop (PLUS_EXPR, base_offset, init);
+   base_offset = fold_convert (sizetype, base_offset);
    dest = create_tmp_var (TREE_TYPE (base_offset), "base_off");
    add_referenced_var (dest);
    base_offset = force_gimple_operand (base_offset, &new_stmt, false, dest);  
*************** vect_create_addr_base_for_vector_ref (tr
*** 642,648 ****
  
    if (offset)
      {
!       tree tmp = create_tmp_var (TREE_TYPE (base_offset), "offset");
        tree step; 
  
        /* For interleaved access step we divide STEP by the size of the
--- 643,649 ----
  
    if (offset)
      {
!       tree tmp = create_tmp_var (sizetype, "offset");
        tree step; 
  
        /* For interleaved access step we divide STEP by the size of the
*************** vect_create_addr_base_for_vector_ref (tr
*** 663,669 ****
      }
    
    /* base + base_offset */
!   addr_base = fold_build2 (PLUS_EXPR, TREE_TYPE (data_ref_base), data_ref_base,
  			   base_offset);
  
    vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
--- 664,670 ----
      }
    
    /* base + base_offset */
!   addr_base = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (data_ref_base), data_ref_base,
  			   base_offset);
  
    vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
*************** bump_vector_ptr (tree dataref_ptr, tree 
*** 894,907 ****
    tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    tree vptr_type = TREE_TYPE (dataref_ptr);
    tree ptr_var = SSA_NAME_VAR (dataref_ptr);
!   tree update = fold_convert (vptr_type, TYPE_SIZE_UNIT (vectype));
    tree incr_stmt;
    ssa_op_iter iter;
    use_operand_p use_p;
    tree new_dataref_ptr;
  
    incr_stmt = build_gimple_modify_stmt (ptr_var,
! 					build2 (PLUS_EXPR, vptr_type,
  						dataref_ptr, update));
    new_dataref_ptr = make_ssa_name (ptr_var, incr_stmt);
    GIMPLE_STMT_OPERAND (incr_stmt, 0) = new_dataref_ptr;
--- 895,908 ----
    tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    tree vptr_type = TREE_TYPE (dataref_ptr);
    tree ptr_var = SSA_NAME_VAR (dataref_ptr);
!   tree update = TYPE_SIZE_UNIT (vectype);
    tree incr_stmt;
    ssa_op_iter iter;
    use_operand_p use_p;
    tree new_dataref_ptr;
  
    incr_stmt = build_gimple_modify_stmt (ptr_var,
! 					build2 (POINTER_PLUS_EXPR, vptr_type,
  						dataref_ptr, update));
    new_dataref_ptr = make_ssa_name (ptr_var, incr_stmt);
    GIMPLE_STMT_OPERAND (incr_stmt, 0) = new_dataref_ptr;
*************** vect_update_ivs_after_vectorizer (loop_v
*** 5270,5281 ****
        init_expr = unshare_expr (initial_condition_in_loop_num (access_fn, 
  							       loop->num));
  
!       ni = fold_build2 (PLUS_EXPR, TREE_TYPE (init_expr),
! 			fold_build2 (MULT_EXPR, TREE_TYPE (init_expr),
! 				     fold_convert (TREE_TYPE (init_expr), 
! 						   niters), 
! 				     step_expr),
! 			init_expr);
  
        var = create_tmp_var (TREE_TYPE (init_expr), "tmp");
        add_referenced_var (var);
--- 5271,5291 ----
        init_expr = unshare_expr (initial_condition_in_loop_num (access_fn, 
  							       loop->num));
  
!       if (POINTER_TYPE_P (TREE_TYPE (init_expr)))
! 	ni = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (init_expr), 
! 			  init_expr, 
! 			  fold_convert (sizetype, 
! 					fold_build2 (MULT_EXPR, TREE_TYPE (niters),
! 						     niters, step_expr)));
!       else
! 	ni = fold_build2 (PLUS_EXPR, TREE_TYPE (init_expr),
! 			  fold_build2 (MULT_EXPR, TREE_TYPE (init_expr),
! 				       fold_convert (TREE_TYPE (init_expr),
! 						     niters),
! 				       step_expr),
! 			  init_expr);
! 
! 
  
        var = create_tmp_var (TREE_TYPE (init_expr), "tmp");
        add_referenced_var (var);
*************** vect_gen_niters_for_prolog_loop (loop_ve
*** 5473,5479 ****
    
        /* Create:  byte_misalign = addr & (vectype_size - 1)  */
        byte_misalign = 
!         fold_build2 (BIT_AND_EXPR, type, start_addr, vectype_size_minus_1);
    
        /* Create:  elem_misalign = byte_misalign / element_size  */
        elem_misalign =
--- 5483,5489 ----
    
        /* Create:  byte_misalign = addr & (vectype_size - 1)  */
        byte_misalign = 
!         fold_build2 (BIT_AND_EXPR, type, fold_convert (type, start_addr), vectype_size_minus_1);
    
        /* Create:  elem_misalign = byte_misalign / element_size  */
        elem_misalign =
Index: tree-object-size.c
===================================================================
*** tree-object-size.c	(.../trunk/gcc)	(revision 125658)
--- tree-object-size.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** merge_object_sizes (struct object_size_i
*** 555,561 ****
  
  
  /* Compute object_sizes for PTR, defined to VALUE, which is
!    a PLUS_EXPR.  Return true if the object size might need reexamination
     later.  */
  
  static bool
--- 555,561 ----
  
  
  /* Compute object_sizes for PTR, defined to VALUE, which is
!    a POINTER_PLUS_EXPR.  Return true if the object size might need reexamination
     later.  */
  
  static bool
*************** plus_expr_object_size (struct object_siz
*** 563,595 ****
  {
    tree op0 = TREE_OPERAND (value, 0);
    tree op1 = TREE_OPERAND (value, 1);
-   bool ptr1_p = POINTER_TYPE_P (TREE_TYPE (op0))
- 		&& TREE_CODE (op0) != INTEGER_CST;
-   bool ptr2_p = POINTER_TYPE_P (TREE_TYPE (op1))
- 		&& TREE_CODE (op1) != INTEGER_CST;
    int object_size_type = osi->object_size_type;
    unsigned int varno = SSA_NAME_VERSION (var);
    unsigned HOST_WIDE_INT bytes;
  
!   gcc_assert (TREE_CODE (value) == PLUS_EXPR);
  
    if (object_sizes[object_size_type][varno] == unknown[object_size_type])
      return false;
  
-   /* Swap operands if needed.  */
-   if (ptr2_p && !ptr1_p)
-     {
-       tree tem = op0;
-       op0 = op1;
-       op1 = tem;
-       ptr1_p = true;
-       ptr2_p = false;
-     }
- 
    /* Handle PTR + OFFSET here.  */
!   if (ptr1_p
!       && !ptr2_p
!       && TREE_CODE (op1) == INTEGER_CST
        && (TREE_CODE (op0) == SSA_NAME
  	  || TREE_CODE (op0) == ADDR_EXPR))
      {
--- 563,579 ----
  {
    tree op0 = TREE_OPERAND (value, 0);
    tree op1 = TREE_OPERAND (value, 1);
    int object_size_type = osi->object_size_type;
    unsigned int varno = SSA_NAME_VERSION (var);
    unsigned HOST_WIDE_INT bytes;
  
!   gcc_assert (TREE_CODE (value) == POINTER_PLUS_EXPR);
  
    if (object_sizes[object_size_type][varno] == unknown[object_size_type])
      return false;
  
    /* Handle PTR + OFFSET here.  */
!   if (TREE_CODE (op1) == INTEGER_CST
        && (TREE_CODE (op0) == SSA_NAME
  	  || TREE_CODE (op0) == ADDR_EXPR))
      {
*************** cond_expr_object_size (struct object_siz
*** 669,675 ****
     OSI->object_size_type).
     For allocation CALL_EXPR like malloc or calloc object size is the size
     of the allocation.
!    For pointer PLUS_EXPR where second operand is a constant integer,
     object size is object size of the first operand minus the constant.
     If the constant is bigger than the number of remaining bytes until the
     end of the object, object size is 0, but if it is instead a pointer
--- 653,659 ----
     OSI->object_size_type).
     For allocation CALL_EXPR like malloc or calloc object size is the size
     of the allocation.
!    For POINTER_PLUS_EXPR where second operand is a constant integer,
     object size is object size of the first operand minus the constant.
     If the constant is bigger than the number of remaining bytes until the
     end of the object, object size is 0, but if it is instead a pointer
*************** collect_object_sizes_for (struct object_
*** 750,756 ****
  	    && POINTER_TYPE_P (TREE_TYPE (rhs)))
  	  reexamine = merge_object_sizes (osi, var, rhs, 0);
  
! 	else if (TREE_CODE (rhs) == PLUS_EXPR)
  	  reexamine = plus_expr_object_size (osi, var, rhs);
  
          else if (TREE_CODE (rhs) == COND_EXPR)
--- 734,740 ----
  	    && POINTER_TYPE_P (TREE_TYPE (rhs)))
  	  reexamine = merge_object_sizes (osi, var, rhs, 0);
  
! 	else if (TREE_CODE (rhs) == POINTER_PLUS_EXPR)
  	  reexamine = plus_expr_object_size (osi, var, rhs);
  
          else if (TREE_CODE (rhs) == COND_EXPR)
*************** check_for_plus_in_loops_1 (struct object
*** 877,899 ****
  
  	if (TREE_CODE (rhs) == SSA_NAME)
  	  check_for_plus_in_loops_1 (osi, rhs, depth);
! 	else if (TREE_CODE (rhs) == PLUS_EXPR)
  	  {
  	    tree op0 = TREE_OPERAND (rhs, 0);
  	    tree op1 = TREE_OPERAND (rhs, 1);
  	    tree cst, basevar;
  
! 	    if (TREE_CODE (op0) == SSA_NAME)
! 	      {
! 		basevar = op0;
! 		cst = op1;
! 	      }
! 	    else
! 	      {
! 		basevar = op1;
! 		cst = op0;
! 		gcc_assert (TREE_CODE (basevar) == SSA_NAME);
! 	      }
  	    gcc_assert (TREE_CODE (cst) == INTEGER_CST);
  
  	    check_for_plus_in_loops_1 (osi, basevar,
--- 861,874 ----
  
  	if (TREE_CODE (rhs) == SSA_NAME)
  	  check_for_plus_in_loops_1 (osi, rhs, depth);
! 	else if (TREE_CODE (rhs) == POINTER_PLUS_EXPR)
  	  {
  	    tree op0 = TREE_OPERAND (rhs, 0);
  	    tree op1 = TREE_OPERAND (rhs, 1);
  	    tree cst, basevar;
  
! 	    basevar = op0;
! 	    cst = op1;
  	    gcc_assert (TREE_CODE (cst) == INTEGER_CST);
  
  	    check_for_plus_in_loops_1 (osi, basevar,
*************** check_for_plus_in_loops (struct object_s
*** 953,975 ****
  	      rhs = arg;
  	  }
  
! 	if (TREE_CODE (rhs) == PLUS_EXPR)
  	  {
  	    tree op0 = TREE_OPERAND (rhs, 0);
  	    tree op1 = TREE_OPERAND (rhs, 1);
  	    tree cst, basevar;
  
! 	    if (TREE_CODE (op0) == SSA_NAME)
! 	      {
! 		basevar = op0;
! 		cst = op1;
! 	      }
! 	    else
! 	      {
! 		basevar = op1;
! 		cst = op0;
! 		gcc_assert (TREE_CODE (basevar) == SSA_NAME);
! 	      }
  	    gcc_assert (TREE_CODE (cst) == INTEGER_CST);
  
  	    if (integer_zerop (cst))
--- 928,941 ----
  	      rhs = arg;
  	  }
  
! 	if (TREE_CODE (rhs) == POINTER_PLUS_EXPR)
  	  {
  	    tree op0 = TREE_OPERAND (rhs, 0);
  	    tree op1 = TREE_OPERAND (rhs, 1);
  	    tree cst, basevar;
  
! 	    basevar = op0;
! 	    cst = op1;
  	    gcc_assert (TREE_CODE (cst) == INTEGER_CST);
  
  	    if (integer_zerop (cst))
Index: c-common.c
===================================================================
*** c-common.c	(.../trunk/gcc)	(revision 125658)
--- c-common.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** pointer_int_sum (enum tree_code resultco
*** 2700,2711 ****
       Do this multiplication as signed, then convert to the appropriate
       pointer type (actually unsigned integral).  */
  
!   intop = convert (result_type,
! 		   build_binary_op (MULT_EXPR, intop,
! 				    convert (TREE_TYPE (intop), size_exp), 1));
  
    /* Create the sum or difference.  */
!   ret = fold_build2 (resultcode, result_type, ptrop, intop);
  
    fold_undefer_and_ignore_overflow_warnings ();
  
--- 2700,2716 ----
       Do this multiplication as signed, then convert to the appropriate
       pointer type (actually unsigned integral).  */
  
!   intop = build_binary_op (MULT_EXPR, intop,
! 			   convert (TREE_TYPE (intop), size_exp), 1);
! 
!   /* FIXME: maybe add a POINTER_MINUS_EXPR ???  */
!   if (resultcode == MINUS_EXPR)
!     intop = fold_build1 (NEGATE_EXPR, TREE_TYPE (intop), intop);
! 
!   intop = convert (sizetype, intop);
  
    /* Create the sum or difference.  */
!   ret = fold_build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop);
  
    fold_undefer_and_ignore_overflow_warnings ();
  
Index: tree-ssa-structalias.c
===================================================================
*** tree-ssa-structalias.c	(.../trunk/gcc)	(revision 125658)
--- tree-ssa-structalias.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** handle_ptr_arith (VEC (ce_s, heap) *lhsc
*** 3293,3315 ****
    VEC (ce_s, heap) *temp = NULL;
    unsigned int rhsoffset = 0;
  
!   if (TREE_CODE (expr) != PLUS_EXPR
!       && TREE_CODE (expr) != MINUS_EXPR)
      return false;
  
    op0 = TREE_OPERAND (expr, 0);
    op1 = TREE_OPERAND (expr, 1);
  
    get_constraint_for (op0, &temp);
-   if (POINTER_TYPE_P (TREE_TYPE (op0))
-       && TREE_CODE (op1) == INTEGER_CST
-       && TREE_CODE (expr) == PLUS_EXPR)
-     {
-       rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
-     }
-   else
-     return false;
  
  
    for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
      for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
--- 3293,3309 ----
    VEC (ce_s, heap) *temp = NULL;
    unsigned int rhsoffset = 0;
  
!   if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
      return false;
  
    op0 = TREE_OPERAND (expr, 0);
    op1 = TREE_OPERAND (expr, 1);
+   gcc_assert (POINTER_TYPE_P (TREE_TYPE (op0)));
  
    get_constraint_for (op0, &temp);
  
+   if (TREE_CODE (op1) == INTEGER_CST)
+     rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
  
    for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
      for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
Index: tree-cfg.c
===================================================================
*** tree-cfg.c	(.../trunk/gcc)	(revision 125658)
--- tree-cfg.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** verify_expr (tree *tp, int *walk_subtree
*** 3265,3271 ****
--- 3265,3300 ----
  	}
        *walk_subtrees = 0;
        break;
+     case PLUS_EXPR:
+     case MINUS_EXPR:
+       /* PLUS_EXPR and MINUS_EXPR don't work on pointers, they should be done using
+ 	 POINTER_PLUS_EXPR. */
+       if (POINTER_TYPE_P (TREE_TYPE (t)))
+ 	{
+ 	  error ("invalid operand to plus/minus, type is a pointer");
+ 	  return t;
+ 	}
+       CHECK_OP (0, "invalid operand to binary operator");
+       CHECK_OP (1, "invalid operand to binary operator");
+       break;
  
+     case POINTER_PLUS_EXPR:
+       /* Check to make sure the first operand is a pointer or reference type. */
+       if (!POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
+ 	{
+ 	  error ("invalid operand to pointer plus, first operand is not a pointer");
+ 	  return t;
+ 	}
+       /* Check to make sure the second operand is an integer with type of
+ 	 sizetype.  */
+       if (!tree_ssa_useless_type_conversion_1 (sizetype,
+ 					       TREE_TYPE (TREE_OPERAND (t, 1))))
+ 	{
+ 	  error ("invalid operand to pointer plus, second operand is not an "
+ 		 "integer with type of sizetype.");
+ 	  return t;
+ 	}
+       /* FALLTHROUGH */
      case LT_EXPR:
      case LE_EXPR:
      case GT_EXPR:
*************** verify_expr (tree *tp, int *walk_subtree
*** 3280,3287 ****
      case UNGE_EXPR:
      case UNEQ_EXPR:
      case LTGT_EXPR:
-     case PLUS_EXPR:
-     case MINUS_EXPR:
      case MULT_EXPR:
      case TRUNC_DIV_EXPR:
      case CEIL_DIV_EXPR:
--- 3309,3314 ----
Index: config/frv/frv.c
===================================================================
*** config/frv/frv.c	(.../trunk/gcc)	(revision 125658)
--- config/frv/frv.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** frv_expand_builtin_va_start (tree valist
*** 2205,2211 ****
      }
  
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (valist), valist,
! 	      make_tree (ptr_type_node, nextarg));
    TREE_SIDE_EFFECTS (t) = 1;
  
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
--- 2205,2212 ----
      }
  
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (valist), valist,
! 	      fold_convert (TREE_TYPE (valist),
! 			    make_tree (sizetype, nextarg)));
    TREE_SIDE_EFFECTS (t) = 1;
  
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
Index: config/s390/s390.c
===================================================================
*** config/s390/s390.c	(.../trunk/gcc)	(revision 125658)
--- config/s390/s390.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** s390_va_start (tree valist, rtx nextarg 
*** 8002,8008 ****
  	fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
  		 (int)n_gpr, (int)n_fpr, off);
  
!       t = build2 (PLUS_EXPR, TREE_TYPE (ovf), t, build_int_cst (NULL_TREE, off));
  
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t);
        TREE_SIDE_EFFECTS (t) = 1;
--- 8002,8008 ----
  	fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
  		 (int)n_gpr, (int)n_fpr, off);
  
!       t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ovf), t, size_int (off));
  
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t);
        TREE_SIDE_EFFECTS (t) = 1;
*************** s390_va_start (tree valist, rtx nextarg 
*** 8014,8021 ****
        || (cfun->va_list_fpr_size && n_fpr < FP_ARG_NUM_REG))
      {
        t = make_tree (TREE_TYPE (sav), return_address_pointer_rtx);
!       t = build2 (PLUS_EXPR, TREE_TYPE (sav), t,
! 	          build_int_cst (NULL_TREE, -RETURN_REGNUM * UNITS_PER_WORD));
    
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (sav), sav, t);
        TREE_SIDE_EFFECTS (t) = 1;
--- 8014,8021 ----
        || (cfun->va_list_fpr_size && n_fpr < FP_ARG_NUM_REG))
      {
        t = make_tree (TREE_TYPE (sav), return_address_pointer_rtx);
!       t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (sav), t,
! 	          size_int (-RETURN_REGNUM * UNITS_PER_WORD));
    
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (sav), sav, t);
        TREE_SIDE_EFFECTS (t) = 1;
*************** s390_gimplify_va_arg (tree valist, tree 
*** 8144,8154 ****
    t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
    gimplify_and_add (t, pre_p);
  
!   t = build2 (PLUS_EXPR, ptr_type_node, sav, 
! 	      fold_convert (ptr_type_node, size_int (sav_ofs)));
    u = build2 (MULT_EXPR, TREE_TYPE (reg), reg, 
  	      fold_convert (TREE_TYPE (reg), size_int (sav_scale)));
!   t = build2 (PLUS_EXPR, ptr_type_node, t, fold_convert (ptr_type_node, u));
  
    t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
    gimplify_and_add (t, pre_p);
--- 8144,8154 ----
    t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
    gimplify_and_add (t, pre_p);
  
!   t = build2 (POINTER_PLUS_EXPR, ptr_type_node, sav, 
! 	      size_int (sav_ofs));
    u = build2 (MULT_EXPR, TREE_TYPE (reg), reg, 
  	      fold_convert (TREE_TYPE (reg), size_int (sav_scale)));
!   t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t, fold_convert (sizetype, u));
  
    t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
    gimplify_and_add (t, pre_p);
*************** s390_gimplify_va_arg (tree valist, tree 
*** 8164,8179 ****
  
    t = ovf;
    if (size < UNITS_PER_WORD)
!     t = build2 (PLUS_EXPR, ptr_type_node, t, 
! 		fold_convert (ptr_type_node, size_int (UNITS_PER_WORD - size)));
  
    gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
  
    u = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
    gimplify_and_add (u, pre_p);
  
!   t = build2 (PLUS_EXPR, ptr_type_node, t, 
! 	      fold_convert (ptr_type_node, size_int (size)));
    t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, ovf, t);
    gimplify_and_add (t, pre_p);
  
--- 8164,8179 ----
  
    t = ovf;
    if (size < UNITS_PER_WORD)
!     t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t, 
! 		size_int (UNITS_PER_WORD - size));
  
    gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
  
    u = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
    gimplify_and_add (u, pre_p);
  
!   t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t, 
! 	      size_int (size));
    t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, ovf, t);
    gimplify_and_add (t, pre_p);
  
Index: config/spu/spu.c
===================================================================
*** config/spu/spu.c	(.../trunk/gcc)	(revision 125658)
--- config/spu/spu.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** spu_va_start (tree valist, rtx nextarg)
*** 3115,3132 ****
    /* Find the __args area.  */
    t = make_tree (TREE_TYPE (args), nextarg);
    if (current_function_pretend_args_size > 0)
!     t = build2 (PLUS_EXPR, TREE_TYPE (args), t,
! 		build_int_cst (integer_type_node, -STACK_POINTER_OFFSET));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (args), args, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  
    /* Find the __skip area.  */
    t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
!   t = build2 (PLUS_EXPR, TREE_TYPE (skip), t,
! 	      build_int_cst (integer_type_node,
! 			     (current_function_pretend_args_size
! 			      - STACK_POINTER_OFFSET)));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (skip), skip, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
--- 3115,3131 ----
    /* Find the __args area.  */
    t = make_tree (TREE_TYPE (args), nextarg);
    if (current_function_pretend_args_size > 0)
!     t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (args), t,
! 		size_int (-STACK_POINTER_OFFSET));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (args), args, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  
    /* Find the __skip area.  */
    t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
!   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (skip), t,
! 	      size_int (current_function_pretend_args_size
! 			 - STACK_POINTER_OFFSET));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (skip), skip, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
*************** spu_gimplify_va_arg_expr (tree valist, t
*** 3182,3202 ****
  
    /* build conditional expression to calculate addr. The expression
       will be gimplified later. */
!   paddedsize = fold_convert (ptr_type_node, size_int (rsize));
!   tmp = build2 (PLUS_EXPR, ptr_type_node, args, paddedsize);
    tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
  		build2 (GT_EXPR, boolean_type_node, tmp, skip),
  		build2 (LE_EXPR, boolean_type_node, args, skip));
  
    tmp = build3 (COND_EXPR, ptr_type_node, tmp,
! 		build2 (PLUS_EXPR, ptr_type_node, skip,
! 			fold_convert (ptr_type_node, size_int (32))), args);
  
    tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, addr, tmp);
    gimplify_and_add (tmp, pre_p);
  
    /* update VALIST.__args */
!   tmp = build2 (PLUS_EXPR, ptr_type_node, addr, paddedsize);
    tmp = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (args), args, tmp);
    gimplify_and_add (tmp, pre_p);
  
--- 3181,3201 ----
  
    /* build conditional expression to calculate addr. The expression
       will be gimplified later. */
!   paddedsize = size_int (rsize);
!   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, args, paddedsize);
    tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
  		build2 (GT_EXPR, boolean_type_node, tmp, skip),
  		build2 (LE_EXPR, boolean_type_node, args, skip));
  
    tmp = build3 (COND_EXPR, ptr_type_node, tmp,
! 		build2 (POINTER_PLUS_EXPR, ptr_type_node, skip,
! 			size_int (32)), args);
  
    tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, addr, tmp);
    gimplify_and_add (tmp, pre_p);
  
    /* update VALIST.__args */
!   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, paddedsize);
    tmp = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (args), args, tmp);
    gimplify_and_add (tmp, pre_p);
  
Index: config/sparc/sparc.c
===================================================================
*** config/sparc/sparc.c	(.../trunk/gcc)	(revision 125658)
--- config/sparc/sparc.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** sparc_gimplify_va_arg (tree valist, tree
*** 5716,5733 ****
    incr = valist;
    if (align)
      {
!       incr = fold_build2 (PLUS_EXPR, ptr_type_node, incr,
! 			  ssize_int (align - 1));
!       incr = fold_build2 (BIT_AND_EXPR, ptr_type_node, incr,
! 			  ssize_int (-align));
      }
  
    gimplify_expr (&incr, pre_p, post_p, is_gimple_val, fb_rvalue);
    addr = incr;
  
    if (BYTES_BIG_ENDIAN && size < rsize)
!     addr = fold_build2 (PLUS_EXPR, ptr_type_node, incr,
! 			ssize_int (rsize - size));
  
    if (indirect)
      {
--- 5716,5735 ----
    incr = valist;
    if (align)
      {
!       incr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, incr,
! 			  size_int (align - 1));
!       incr = fold_convert (sizetype, incr);
!       incr = fold_build2 (BIT_AND_EXPR, sizetype, incr,
! 			  size_int (-align));
!       incr = fold_convert (ptr_type_node, incr);
      }
  
    gimplify_expr (&incr, pre_p, post_p, is_gimple_val, fb_rvalue);
    addr = incr;
  
    if (BYTES_BIG_ENDIAN && size < rsize)
!     addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, incr,
! 			size_int (rsize - size));
  
    if (indirect)
      {
*************** sparc_gimplify_va_arg (tree valist, tree
*** 5755,5761 ****
    else
      addr = fold_convert (ptrtype, addr);
  
!   incr = fold_build2 (PLUS_EXPR, ptr_type_node, incr, ssize_int (rsize));
    incr = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, valist, incr);
    gimplify_and_add (incr, post_p);
  
--- 5757,5763 ----
    else
      addr = fold_convert (ptrtype, addr);
  
!   incr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, incr, size_int (rsize));
    incr = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, valist, incr);
    gimplify_and_add (incr, post_p);
  
Index: config/i386/i386.c
===================================================================
*** config/i386/i386.c	(.../trunk/gcc)	(revision 125658)
--- config/i386/i386.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** ix86_va_start (tree valist, rtx nextarg)
*** 4824,4831 ****
    type = TREE_TYPE (ovf);
    t = make_tree (type, virtual_incoming_args_rtx);
    if (words != 0)
!     t = build2 (PLUS_EXPR, type, t,
! 	        build_int_cst (type, words * UNITS_PER_WORD));
    t = build2 (GIMPLE_MODIFY_STMT, type, ovf, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
--- 4824,4831 ----
    type = TREE_TYPE (ovf);
    t = make_tree (type, virtual_incoming_args_rtx);
    if (words != 0)
!     t = build2 (POINTER_PLUS_EXPR, type, t,
! 	        size_int (words * UNITS_PER_WORD));
    t = build2 (GIMPLE_MODIFY_STMT, type, ovf, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
*************** ix86_gimplify_va_arg (tree valist, tree 
*** 4971,4986 ****
        if (needed_intregs)
  	{
  	  /* int_addr = gpr + sav; */
! 	  t = fold_convert (ptr_type_node, fold_convert (size_type_node, gpr));
! 	  t = build2 (PLUS_EXPR, ptr_type_node, sav, t);
  	  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, int_addr, t);
  	  gimplify_and_add (t, pre_p);
  	}
        if (needed_sseregs)
  	{
  	  /* sse_addr = fpr + sav; */
! 	  t = fold_convert (ptr_type_node, fold_convert (size_type_node, fpr));
! 	  t = build2 (PLUS_EXPR, ptr_type_node, sav, t);
  	  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, sse_addr, t);
  	  gimplify_and_add (t, pre_p);
  	}
--- 4971,4986 ----
        if (needed_intregs)
  	{
  	  /* int_addr = gpr + sav; */
! 	  t = fold_convert (sizetype, gpr);
! 	  t = build2 (POINTER_PLUS_EXPR, ptr_type_node, sav, t);
  	  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, int_addr, t);
  	  gimplify_and_add (t, pre_p);
  	}
        if (needed_sseregs)
  	{
  	  /* sse_addr = fpr + sav; */
! 	  t = fold_convert (sizetype, fpr);
! 	  t = build2 (POINTER_PLUS_EXPR, ptr_type_node, sav, t);
  	  t = build2 (GIMPLE_MODIFY_STMT, void_type_node, sse_addr, t);
  	  gimplify_and_add (t, pre_p);
  	}
*************** ix86_gimplify_va_arg (tree valist, tree 
*** 5016,5027 ****
  		  src_offset = REGNO (reg) * 8;
  		}
  	      src_addr = fold_convert (addr_type, src_addr);
! 	      src_addr = fold_build2 (PLUS_EXPR, addr_type, src_addr,
  				      build_int_cst (addr_type, src_offset));
  	      src = build_va_arg_indirect_ref (src_addr);
  
  	      dest_addr = fold_convert (addr_type, addr);
! 	      dest_addr = fold_build2 (PLUS_EXPR, addr_type, dest_addr,
  				       build_int_cst (addr_type, INTVAL (XEXP (slot, 1))));
  	      dest = build_va_arg_indirect_ref (dest_addr);
  
--- 5016,5027 ----
  		  src_offset = REGNO (reg) * 8;
  		}
  	      src_addr = fold_convert (addr_type, src_addr);
! 	      src_addr = fold_build2 (POINTER_PLUS_EXPR, addr_type, src_addr,
  				      build_int_cst (addr_type, src_offset));
  	      src = build_va_arg_indirect_ref (src_addr);
  
  	      dest_addr = fold_convert (addr_type, addr);
! 	      dest_addr = fold_build2 (POINTER_PLUS_EXPR, addr_type, dest_addr,
  				       build_int_cst (addr_type, INTVAL (XEXP (slot, 1))));
  	      dest = build_va_arg_indirect_ref (dest_addr);
  
*************** ix86_gimplify_va_arg (tree valist, tree 
*** 5058,5078 ****
    if (FUNCTION_ARG_BOUNDARY (VOIDmode, type) <= 64
        || integer_zerop (TYPE_SIZE (type)))
      t = ovf;
!   else
      {
        HOST_WIDE_INT align = FUNCTION_ARG_BOUNDARY (VOIDmode, type) / 8;
!       t = build2 (PLUS_EXPR, TREE_TYPE (ovf), ovf,
! 		  build_int_cst (TREE_TYPE (ovf), align - 1));
        t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
! 		  build_int_cst (TREE_TYPE (t), -align));
      }
    gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
  
    t2 = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
    gimplify_and_add (t2, pre_p);
  
!   t = build2 (PLUS_EXPR, TREE_TYPE (t), t,
! 	      build_int_cst (TREE_TYPE (t), rsize * UNITS_PER_WORD));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t);
    gimplify_and_add (t, pre_p);
  
--- 5058,5080 ----
    if (FUNCTION_ARG_BOUNDARY (VOIDmode, type) <= 64
        || integer_zerop (TYPE_SIZE (type)))
      t = ovf;
!  else
      {
        HOST_WIDE_INT align = FUNCTION_ARG_BOUNDARY (VOIDmode, type) / 8;
!       t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ovf), ovf,
! 		  size_int (align - 1));
!       t = fold_convert (sizetype, t);
        t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
! 		  size_int (-align));
!       t = fold_convert (TREE_TYPE (ovf), t);
      }
    gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
  
    t2 = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
    gimplify_and_add (t2, pre_p);
  
!   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t,
! 	      size_int (rsize * UNITS_PER_WORD));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t);
    gimplify_and_add (t, pre_p);
  
Index: config/sh/sh.c
===================================================================
*** config/sh/sh.c	(.../trunk/gcc)	(revision 125658)
--- config/sh/sh.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** sh_va_start (tree valist, rtx nextarg)
*** 7049,7055 ****
  		       valist, f_next_stack, NULL_TREE);
  
    /* Call __builtin_saveregs.  */
!   u = make_tree (ptr_type_node, expand_builtin_saveregs ());
    t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_fp, u);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
--- 7049,7056 ----
  		       valist, f_next_stack, NULL_TREE);
  
    /* Call __builtin_saveregs.  */
!   u = make_tree (sizetype, expand_builtin_saveregs ());
!   u = fold_convert (ptr_type_node, u);
    t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_fp, u);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
*************** sh_va_start (tree valist, rtx nextarg)
*** 7059,7066 ****
      nfp = 8 - nfp;
    else
      nfp = 0;
!   u = fold_build2 (PLUS_EXPR, ptr_type_node, u,
! 		   build_int_cst (NULL_TREE, UNITS_PER_WORD * nfp));
    t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_fp_limit, u);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
--- 7060,7067 ----
      nfp = 8 - nfp;
    else
      nfp = 0;
!   u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
! 		   size_int (UNITS_PER_WORD * nfp));
    t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_fp_limit, u);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
*************** sh_va_start (tree valist, rtx nextarg)
*** 7074,7081 ****
      nint = 4 - nint;
    else
      nint = 0;
!   u = fold_build2 (PLUS_EXPR, ptr_type_node, u,
! 		   build_int_cst (NULL_TREE, UNITS_PER_WORD * nint));
    t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_o_limit, u);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
--- 7075,7082 ----
      nint = 4 - nint;
    else
      nint = 0;
!   u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
! 		   size_int (UNITS_PER_WORD * nint));
    t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_o_limit, u);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
*************** sh_gimplify_va_arg_expr (tree valist, tr
*** 7208,7215 ****
  	  gimplify_and_add (tmp, pre_p);
  	  tmp = next_fp_limit;
  	  if (size > 4 && !is_double)
! 	    tmp = build2 (PLUS_EXPR, TREE_TYPE (tmp), tmp,
! 			  fold_convert (TREE_TYPE (tmp), size_int (4 - size)));
  	  tmp = build2 (GE_EXPR, boolean_type_node, next_fp_tmp, tmp);
  	  cmp = build3 (COND_EXPR, void_type_node, tmp,
  		        build1 (GOTO_EXPR, void_type_node, lab_false),
--- 7209,7216 ----
  	  gimplify_and_add (tmp, pre_p);
  	  tmp = next_fp_limit;
  	  if (size > 4 && !is_double)
! 	    tmp = build2 (POINTER_PLUS_EXPR, TREE_TYPE (tmp), tmp,
! 			  size_int (4 - size));
  	  tmp = build2 (GE_EXPR, boolean_type_node, next_fp_tmp, tmp);
  	  cmp = build3 (COND_EXPR, void_type_node, tmp,
  		        build1 (GOTO_EXPR, void_type_node, lab_false),
*************** sh_gimplify_va_arg_expr (tree valist, tr
*** 7220,7228 ****
  	  if (TYPE_ALIGN (eff_type) > BITS_PER_WORD
  	      || (is_double || size == 16))
  	    {
! 	      tmp = fold_convert (ptr_type_node, size_int (UNITS_PER_WORD));
! 	      tmp = build2 (BIT_AND_EXPR, ptr_type_node, next_fp_tmp, tmp);
! 	      tmp = build2 (PLUS_EXPR, ptr_type_node, next_fp_tmp, tmp);
  	      tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node,
  		  	    next_fp_tmp, tmp);
  	      gimplify_and_add (tmp, pre_p);
--- 7221,7231 ----
  	  if (TYPE_ALIGN (eff_type) > BITS_PER_WORD
  	      || (is_double || size == 16))
  	    {
! 	      tmp = fold_convert (sizetype, next_fp_tmp);
! 	      tmp = build2 (BIT_AND_EXPR, sizetype, tmp,
! 			    size_int (UNITS_PER_WORD));
! 	      tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
! 			    next_fp_tmp, tmp);
  	      tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node,
  		  	    next_fp_tmp, tmp);
  	      gimplify_and_add (tmp, pre_p);
*************** sh_gimplify_va_arg_expr (tree valist, tr
*** 7268,7275 ****
  	}
        else
  	{
! 	  tmp = fold_convert (ptr_type_node, size_int (rsize));
! 	  tmp = build2 (PLUS_EXPR, ptr_type_node, next_o, tmp);
  	  tmp = build2 (GT_EXPR, boolean_type_node, tmp, next_o_limit);
  	  tmp = build3 (COND_EXPR, void_type_node, tmp,
  		        build1 (GOTO_EXPR, void_type_node, lab_false),
--- 7271,7278 ----
  	}
        else
  	{
! 	  tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, next_o,
! 			size_int (rsize));
  	  tmp = build2 (GT_EXPR, boolean_type_node, tmp, next_o_limit);
  	  tmp = build3 (COND_EXPR, void_type_node, tmp,
  		        build1 (GOTO_EXPR, void_type_node, lab_false),
Index: config/ia64/ia64.c
===================================================================
*** config/ia64/ia64.c	(.../trunk/gcc)	(revision 125658)
--- config/ia64/ia64.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** ia64_gimplify_va_arg (tree valist, tree 
*** 4326,4335 ****
    if ((TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == INTEGER_TYPE)
        ? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
      {
!       tree t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist,
! 		       build_int_cst (NULL_TREE, 2 * UNITS_PER_WORD - 1));
        t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
! 		  build_int_cst (NULL_TREE, -2 * UNITS_PER_WORD));
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (valist), valist, t);
        gimplify_and_add (t, pre_p);
      }
--- 4326,4337 ----
    if ((TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == INTEGER_TYPE)
        ? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
      {
!       tree t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist,
! 		       size_int (2 * UNITS_PER_WORD - 1));
!       t = fold_convert (sizetype, t);
        t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
! 		  size_int (-2 * UNITS_PER_WORD));
!       t = fold_convert (TREE_TYPE (valist), t);
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (valist), valist, t);
        gimplify_and_add (t, pre_p);
      }
Index: config/rs6000/rs6000.c
===================================================================
*** config/rs6000/rs6000.c	(.../trunk/gcc)	(revision 125658)
--- config/rs6000/rs6000.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** rs6000_va_start (tree valist, rtx nextar
*** 6210,6217 ****
    /* Find the overflow area.  */
    t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
    if (words != 0)
!     t = build2 (PLUS_EXPR, TREE_TYPE (ovf), t,
! 	        build_int_cst (NULL_TREE, words * UNITS_PER_WORD));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
--- 6210,6217 ----
    /* Find the overflow area.  */
    t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
    if (words != 0)
!     t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ovf), t,
! 	        size_int (words * UNITS_PER_WORD));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
*************** rs6000_va_start (tree valist, rtx nextar
*** 6227,6234 ****
    /* Find the register save area.  */
    t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx);
    if (cfun->machine->varargs_save_offset)
!     t = build2 (PLUS_EXPR, TREE_TYPE (sav), t,
! 	        build_int_cst (NULL_TREE, cfun->machine->varargs_save_offset));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (sav), sav, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
--- 6227,6234 ----
    /* Find the register save area.  */
    t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx);
    if (cfun->machine->varargs_save_offset)
!     t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (sav), t,
! 	        size_int (cfun->machine->varargs_save_offset));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (sav), sav, t);
    TREE_SIDE_EFFECTS (t) = 1;
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
*************** rs6000_gimplify_va_arg (tree valist, tre
*** 6367,6378 ****
  
        t = sav;
        if (sav_ofs)
! 	t = build2 (PLUS_EXPR, ptr_type_node, sav, size_int (sav_ofs));
  
        u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, size_int (n_reg));
!       u = build1 (CONVERT_EXPR, integer_type_node, u);
!       u = build2 (MULT_EXPR, integer_type_node, u, size_int (sav_scale));
!       t = build2 (PLUS_EXPR, ptr_type_node, t, u);
  
        t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
        gimplify_and_add (t, pre_p);
--- 6367,6378 ----
  
        t = sav;
        if (sav_ofs)
! 	t = build2 (POINTER_PLUS_EXPR, ptr_type_node, sav, size_int (sav_ofs));
  
        u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, size_int (n_reg));
!       u = fold_convert (sizetype, u);
!       u = build2 (MULT_EXPR, sizetype, u, size_int (sav_scale));
!       t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t, u);
  
        t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
        gimplify_and_add (t, pre_p);
*************** rs6000_gimplify_va_arg (tree valist, tre
*** 6398,6413 ****
    t = ovf;
    if (align != 1)
      {
!       t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (align - 1));
        t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
! 		  build_int_cst (NULL_TREE, -align));
      }
    gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
  
    u = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
    gimplify_and_add (u, pre_p);
  
!   t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (size));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t);
    gimplify_and_add (t, pre_p);
  
--- 6398,6415 ----
    t = ovf;
    if (align != 1)
      {
!       t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (align - 1));
!       t = fold_convert (sizetype, t);
        t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
! 		  size_int (-align));
!       t = fold_convert (TREE_TYPE (ovf), t);
      }
    gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
  
    u = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
    gimplify_and_add (u, pre_p);
  
!   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (size));
    t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t);
    gimplify_and_add (t, pre_p);
  
Index: config/pa/pa.c
===================================================================
*** config/pa/pa.c	(.../trunk/gcc)	(revision 125658)
--- config/pa/pa.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** reloc_needed (tree exp)
*** 2046,2051 ****
--- 2046,2052 ----
      case ADDR_EXPR:
        return 1;
  
+     case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
      case MINUS_EXPR:
        reloc = reloc_needed (TREE_OPERAND (exp, 0));
*************** hppa_gimplify_va_arg_expr (tree valist, 
*** 5922,5942 ****
  
        /* Args grow down.  Not handled by generic routines.  */
  
!       u = fold_convert (valist_type, size_in_bytes (type));
!       t = build2 (MINUS_EXPR, valist_type, valist, u);
  
        /* Copied from va-pa.h, but we probably don't need to align to
  	 word size, since we generate and preserve that invariant.  */
!       u = build_int_cst (valist_type, (size > 4 ? -8 : -4));
!       t = build2 (BIT_AND_EXPR, valist_type, t, u);
  
        t = build2 (MODIFY_EXPR, valist_type, valist, t);
  
        ofs = (8 - size) % 4;
        if (ofs != 0)
  	{
! 	  u = fold_convert (valist_type, size_int (ofs));
! 	  t = build2 (PLUS_EXPR, valist_type, t, u);
  	}
  
        t = fold_convert (ptr, t);
--- 5923,5946 ----
  
        /* Args grow down.  Not handled by generic routines.  */
  
!       u = fold_convert (sizetype, size_in_bytes (type));
!       u = fold_build1 (NEGATE_EXPR, sizetype, u);
!       t = build2 (POINTER_PLUS_EXPR, valist_type, valist, u);
  
        /* Copied from va-pa.h, but we probably don't need to align to
  	 word size, since we generate and preserve that invariant.  */
!       u = size_int (size > 4 ? -8 : -4);
!       t = fold_convert (sizetype, t);
!       t = build2 (BIT_AND_EXPR, sizetype, t, u);
!       t = fold_convert (valist_type, t);
  
        t = build2 (MODIFY_EXPR, valist_type, valist, t);
  
        ofs = (8 - size) % 4;
        if (ofs != 0)
  	{
! 	  u = size_int (ofs);
! 	  t = build2 (POINTER_PLUS_EXPR, valist_type, t, u);
  	}
  
        t = fold_convert (ptr, t);
Index: config/mips/mips.c
===================================================================
*** config/mips/mips.c	(.../trunk/gcc)	(revision 125658)
--- config/mips/mips.c	(.../branches/pointer_plus/gcc)	(revision 125672)
*************** mips_va_start (tree valist, rtx nextarg)
*** 4366,4374 ****
  	 words used by named arguments.  */
        t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
        if (cum->stack_words > 0)
! 	t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), t,
! 		    build_int_cst (NULL_TREE,
! 				   cum->stack_words * UNITS_PER_WORD));
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovfl), ovfl, t);
        expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  
--- 4366,4373 ----
  	 words used by named arguments.  */
        t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
        if (cum->stack_words > 0)
! 	t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ovfl), t,
! 		    size_int (cum->stack_words * UNITS_PER_WORD));
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovfl), ovfl, t);
        expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  
*************** mips_va_start (tree valist, rtx nextarg)
*** 4384,4391 ****
        fpr_offset = gpr_save_area_size + UNITS_PER_FPVALUE - 1;
        fpr_offset &= ~(UNITS_PER_FPVALUE - 1);
        if (fpr_offset)
! 	t = build2 (PLUS_EXPR, TREE_TYPE (ftop), t,
! 		    build_int_cst (NULL_TREE, -fpr_offset));
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ftop), ftop, t);
        expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  
--- 4383,4390 ----
        fpr_offset = gpr_save_area_size + UNITS_PER_FPVALUE - 1;
        fpr_offset &= ~(UNITS_PER_FPVALUE - 1);
        if (fpr_offset)
! 	t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ftop), t,
! 		    size_int (-fpr_offset));
        t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ftop), ftop, t);
        expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  
*************** mips_gimplify_va_arg_expr (tree valist, 
*** 4535,4562 ****
        t = fold_convert (TREE_TYPE (off), build_int_cst (NULL_TREE, rsize));
        t = build2 (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t);
        t = fold_convert (sizetype, t);
!       t = fold_convert (TREE_TYPE (top), t);
  
        /* [4] Emit code for: addr_rtx = top - off.  On big endian machines,
  	 the argument has RSIZE - SIZE bytes of leading padding.  */
!       t = build2 (MINUS_EXPR, TREE_TYPE (top), top, t);
        if (BYTES_BIG_ENDIAN && rsize > size)
  	{
! 	  u = fold_convert (TREE_TYPE (t), build_int_cst (NULL_TREE,
! 							  rsize - size));
! 	  t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u);
  	}
        COND_EXPR_THEN (addr) = t;
  
        if (osize > UNITS_PER_WORD)
  	{
  	  /* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize.  */
! 	  u = fold_convert (TREE_TYPE (ovfl),
! 			    build_int_cst (NULL_TREE, osize - 1));
! 	  t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u);
! 	  u = fold_convert (TREE_TYPE (ovfl),
! 			    build_int_cst (NULL_TREE, -osize));
! 	  t = build2 (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u);
  	  align = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovfl), ovfl, t);
  	}
        else
--- 4534,4560 ----
        t = fold_convert (TREE_TYPE (off), build_int_cst (NULL_TREE, rsize));
        t = build2 (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t);
        t = fold_convert (sizetype, t);
!       t = fold_build1 (NEGATE_EXPR, sizetype, t);
  
        /* [4] Emit code for: addr_rtx = top - off.  On big endian machines,
  	 the argument has RSIZE - SIZE bytes of leading padding.  */
!       t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (top), top, t);
        if (BYTES_BIG_ENDIAN && rsize > size)
  	{
! 	  u = size_int (rsize - size);
! 	  t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, u);
  	}
        COND_EXPR_THEN (addr) = t;
  
        if (osize > UNITS_PER_WORD)
  	{
  	  /* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize.  */
! 	  u = size_int (osize - 1);
! 	  t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u);
! 	  t = fold_convert (sizetype, t);
! 	  u = size_int (-osize);
! 	  t = build2 (BIT_AND_EXPR, sizetype, t, u);
! 	  t = fold_convert (TREE_TYPE (ovfl), t);
  	  align = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovfl), ovfl, t);
  	}
        else
*************** mips_gimplify_va_arg_expr (tree valist, 
*** 4570,4578 ****
        t = build2 (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u);
        if (BYTES_BIG_ENDIAN && osize > size)
  	{
! 	  u = fold_convert (TREE_TYPE (t),
! 			    build_int_cst (NULL_TREE, osize - size));
! 	  t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u);
  	}
  
        /* String [9] and [10,11] together.  */
--- 4568,4575 ----
        t = build2 (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u);
        if (BYTES_BIG_ENDIAN && osize > size)
  	{
! 	  u = size_int (osize - size);
! 	  t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, u);
  	}
  
        /* String [9] and [10,11] together.  */


More information about the Gcc-patches mailing list