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


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

New branch for POINTER_PLUS_EXPR


Hi,
  This branch add POINTER_PLUS_EXPR for adding a pointer and an integer
together.  Right now my patches are able to bootstrap C but we get
failures due to scev not being updated to handle POINTER_PLUS_EXPR.

I committed this current patch to that branch so other people can start
helping me out since I might not have time to work on this until after
fixing some of the SPU bugs.  Also this patch bootstrap for C++ but
again not all the testcase pass, some ICEs while others fail during
execution.  I have not looked into them yet.

Thanks,
Andrew Pinski

ChangeLog:

	* 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.
	
	
cp/ChangeLog:
	* 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.
	


testsuite/ChangeLog:
	* gcc.dg/tree-ssa/ssa-pre-8.c: Update testcase since we don't
	have a cast which is PREd.
	
	
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c	(revision 118474)
+++ gcc/tree-pretty-print.c	(working copy)
@@ -1183,6 +1183,7 @@ dump_generic_node (pretty_printer *buffe
     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:
@@ -2162,6 +2163,7 @@ op_prio (tree op)
 
     case WIDEN_SUM_EXPR:
     case PLUS_EXPR:
+    case POINTER_PLUS_EXPR:
     case MINUS_EXPR:
       return 12;
 
@@ -2314,6 +2316,9 @@ op_symbol_1 (enum tree_code code)
 
     case VEC_RSHIFT_EXPR:
       return "v>>";
+
+    case POINTER_PLUS_EXPR:
+      return "p+";
  
     case PLUS_EXPR:
       return "+";
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(revision 118474)
+++ gcc/optabs.c	(working copy)
@@ -322,6 +322,7 @@ optab_for_tree_code (enum tree_code code
   trapv = flag_trapv && INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type);
   switch (code)
     {
+    case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       return trapv ? addv_optab : add_optab;
 
Index: gcc/tree-ssa-loop-manip.c
===================================================================
--- gcc/tree-ssa-loop-manip.c	(revision 118474)
+++ gcc/tree-ssa-loop-manip.c	(working copy)
@@ -93,7 +93,13 @@ create_iv (tree base, tree step, tree va
 	    }
 	}
     }
-
+  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: gcc/tree-tailcall.c
===================================================================
--- gcc/tree-tailcall.c	(revision 118474)
+++ gcc/tree-tailcall.c	(working copy)
@@ -346,7 +346,7 @@ process_assignment (tree ass, tree stmt,
       *ass_var = dest;
       return true;
 
-      /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR).  */
+      /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR, POINTER_PLUS_EXPR).  */
 
     default:
       return false;
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 118474)
+++ gcc/tree.c	(working copy)
@@ -2962,6 +2962,13 @@ build2_stat (enum tree_code code, tree t
 
   gcc_assert (TREE_CODE_LENGTH (code) == 2);
 
+  if ((code == MINUS_EXPR || code == PLUS_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);
+
   t = make_node_stat (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
 
Index: gcc/tree-scalar-evolution.c
===================================================================
--- gcc/tree-scalar-evolution.c	(revision 118474)
+++ gcc/tree-scalar-evolution.c	(working copy)
@@ -1816,9 +1816,7 @@ pointer_offset_p (tree expr)
    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.  */
+   FIXME: Rewrite using POINTER_PLUS_EXPR which is the orignal ??? about :).  */
 
 static tree
 fold_used_pointer (tree expr, tree at_stmt)
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 118474)
+++ gcc/builtins.c	(working copy)
@@ -261,7 +261,7 @@ get_pointer_alignment (tree exp, unsigne
 	  align = MIN (inner, max_align);
 	  break;
 
-	case PLUS_EXPR:
+	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.  */
@@ -4023,9 +4023,8 @@ expand_builtin_strcat (tree fndecl, tree
 	  newdst =
 	    build_function_call_expr (strlen_fn,
 				      build_tree_list (NULL_TREE, dst));
-	  /* Create (dst + (cast) strlen (dst)).  */
-	  newdst = fold_convert (TREE_TYPE (dst), newdst);
-	  newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
+	  /* Create (dst p+ strlen (dst)).  */
+	  newdst = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
 
 	  newdst = builtin_save_expr (newdst);
 	  arglist = tree_cons (NULL_TREE, newdst, arglist);
@@ -4308,9 +4307,9 @@ std_gimplify_va_arg_expr (tree valist, t
   if (boundary > align
       && !integer_zerop (TYPE_SIZE (type)))
     {
-      t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
+      t = size_int (boundary - 1);
       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
-		  build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
+		  build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
       gimplify_and_add (t, pre_p);
 
       t = fold_convert (TREE_TYPE (valist), size_int (-boundary));
@@ -4346,13 +4345,11 @@ std_gimplify_va_arg_expr (tree valist, t
       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);
+      addr = fold_build2 (POINTER_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 (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);
 
@@ -8300,8 +8297,7 @@ fold_builtin_memory_op (tree arglist, tr
     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_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
   dest = fold_convert (type, dest);
   if (expr)
     dest = omit_one_operand (type, dest, expr);
@@ -9613,8 +9609,8 @@ fold_builtin_strstr (tree arglist, tree 
 	    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));
+	  tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
+			     s1, build_int_cst (sizetype, r - p1));
 	  return fold_convert (type, tem);
 	}
 
@@ -9685,8 +9681,8 @@ fold_builtin_strchr (tree arglist, tree 
 	    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));
+	  tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
+			     s1, build_int_cst (sizetype, r - p1));
 	  return fold_convert (type, tem);
 	}
       return 0;
@@ -9740,8 +9736,8 @@ fold_builtin_strrchr (tree arglist, tree
 	    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));
+	  tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
+			     s1, build_int_cst (sizetype, r - p1));
 	  return fold_convert (type, tem);
 	}
 
@@ -9799,8 +9795,8 @@ fold_builtin_strpbrk (tree arglist, tree
 	    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));
+	  tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
+			     s1, build_int_cst (sizetype, r - p1));
 	  return fold_convert (type, tem);
 	}
 
@@ -10396,8 +10392,7 @@ expand_builtin_memory_chk (tree exp, rtx
 	      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);
+	  expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
 	  return expand_expr (expr, target, mode, EXPAND_NORMAL);
 	}
 
@@ -10671,8 +10666,7 @@ fold_builtin_memory_chk (tree fndecl, tr
 	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);
+	  tree temp = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
 	  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
 	}
     }
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 118474)
+++ gcc/fold-const.c	(working copy)
@@ -4192,6 +4192,20 @@ build_range_check (tree type, tree exp, 
 
   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),
@@ -6710,9 +6724,21 @@ fold_to_nonsharp_ineq_using_bound (tree 
   if (TREE_TYPE (a1) != typea)
     return NULL_TREE;
 
-  diff = fold_build2 (MINUS_EXPR, typea, a1, a);
-  if (!integer_onep (diff))
-    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, typea, 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);
 }
@@ -8559,6 +8585,52 @@ fold_binary (enum tree_code code, tree t
 
   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));
+
+      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 (PLUS_EXPR, arg0, arg1);
+	  if (tem)
+	    return fold_convert (type, tem);
+	}
+
+      return NULL_TREE;
     case PLUS_EXPR:
       /* A + (-B) -> A - B */
       if (TREE_CODE (arg1) == NEGATE_EXPR)
@@ -12138,6 +12210,7 @@ tree_expr_nonnegative_p (tree t)
     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_p (TREE_OPERAND (t, 0))
@@ -12435,6 +12508,7 @@ tree_expr_nonzero_p (tree t)
       return (TREE_INT_CST_LOW (t) != 0
 	      || TREE_INT_CST_HIGH (t) != 0);
 
+    case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       if (!TYPE_UNSIGNED (type) && !flag_wrapv)
 	{
@@ -12934,7 +13008,7 @@ fold_indirect_ref_1 (tree type, tree op0
     }
 
   /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
-  if (TREE_CODE (sub) == PLUS_EXPR
+  if (TREE_CODE (sub) == POINTER_PLUS_EXPR
       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
     {
       tree op00 = TREE_OPERAND (sub, 0);
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c	(revision 118474)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c	(working copy)
@@ -16,6 +16,8 @@ foo (__SIZE_TYPE__ i, struct s *array)
     }
   return 0;
 }
-/* We should eliminate two address calculations, one cast, and one load.  */
-/* { dg-final { scan-tree-dump-times "Eliminated: 4" 1 "fre"} } */
+/* 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: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 118474)
+++ gcc/cp/typeck.c	(working copy)
@@ -3444,9 +3444,13 @@ build_binary_op (enum tree_code code, tr
   /* 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);
+    {
+      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: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c	(revision 118474)
+++ gcc/cp/init.c	(working copy)
@@ -786,7 +786,7 @@ expand_virtual_init (tree binfo, tree de
 
       /* Compute the value to use, when there's a VTT.  */
       vtt_parm = current_vtt_parm;
-      vtbl2 = build2 (PLUS_EXPR,
+      vtbl2 = build2 (POINTER_PLUS_EXPR,
 		      TREE_TYPE (vtt_parm),
 		      vtt_parm,
 		      vtt_index);
@@ -1850,14 +1850,15 @@ build_new_1 (tree placement, tree type, 
       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,
+      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 = build2 (MINUS_EXPR, build_pointer_type (sizetype),
-			   data_addr, size_in_bytes (sizetype));
+      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);
@@ -2229,6 +2230,7 @@ build_vec_delete_1 (tree base, tree maxi
      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);
@@ -2242,7 +2244,7 @@ build_vec_delete_1 (tree base, tree maxi
 
   tbase = create_temporary_var (ptype);
   tbase_init = build_modify_expr (tbase, NOP_EXPR,
-				  fold_build2 (PLUS_EXPR, ptype,
+				  fold_build2 (POINTER_PLUS_EXPR, ptype,
 					       base,
 					       virtual_size));
   DECL_REGISTER (tbase) = 1;
@@ -2253,9 +2255,10 @@ build_vec_delete_1 (tree base, tree maxi
   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 (MINUS_EXPR, ptype, tbase, size_exp)));
+			      build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp)));
   body = build_compound_expr
     (body, build_delete (ptype, tbase, sfk_complete_destructor,
 			 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1));
@@ -2976,10 +2979,11 @@ build_vec_delete (tree base, tree maxind
 	  base = TARGET_EXPR_SLOT (base_init);
 	}
       type = strip_array_types (TREE_TYPE (type));
-      cookie_addr = build2 (MINUS_EXPR,
+      cookie_addr = fold_build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (sizetype));
+      cookie_addr = build2 (POINTER_PLUS_EXPR,
 			    build_pointer_type (sizetype),
 			    base,
-			    TYPE_SIZE_UNIT (sizetype));
+			    cookie_addr);
       maxindex = build_indirect_ref (cookie_addr, NULL);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	(revision 118474)
+++ gcc/cp/class.c	(working copy)
@@ -355,8 +355,8 @@ build_base_path (enum tree_code code,
 	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 = 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);
@@ -394,7 +394,12 @@ build_base_path (enum tree_code code,
   expr = build1 (NOP_EXPR, ptr_target_type, expr);
 
   if (!integer_zerop (offset))
-    expr = build2 (code, ptr_target_type, expr, 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;
 
@@ -521,8 +526,8 @@ convert_to_base_statically (tree expr, t
       pointer_type = build_pointer_type (expr_type);
       expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
       if (!integer_zerop (BINFO_OFFSET (base)))
-	  expr = build2 (PLUS_EXPR, pointer_type, expr,
-			 build_nop (pointer_type, BINFO_OFFSET (base)));
+	  expr = build2 (POINTER_PLUS_EXPR, pointer_type, expr,
+			 build_nop (sizetype, BINFO_OFFSET (base)));
       expr = build_nop (build_pointer_type (BINFO_TYPE (base)), expr);
       expr = build1 (INDIRECT_REF, BINFO_TYPE (base), expr);
     }
@@ -5264,6 +5269,7 @@ fixed_type_or_null (tree instance, int* 
 	}
       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)
@@ -6316,7 +6322,7 @@ get_vtbl_decl_for_binfo (tree binfo)
   tree decl;
 
   decl = BINFO_VTABLE (binfo);
-  if (decl && TREE_CODE (decl) == PLUS_EXPR)
+  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);
@@ -7102,7 +7108,7 @@ dfs_accumulate_vtbl_inits (tree binfo,
       index = size_binop (MULT_EXPR,
 			  TYPE_SIZE_UNIT (vtable_entry_type),
 			  index);
-      vtbl = build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
+      vtbl = build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
     }
 
   if (ctor_vtbl_p)
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 118474)
+++ gcc/cp/call.c	(working copy)
@@ -5230,7 +5230,7 @@ build_special_member_call (tree instance
 		    current_vtt_parm,
 		    vtt);
       gcc_assert (BINFO_SUBVTT_INDEX (binfo));
-      sub_vtt = build2 (PLUS_EXPR, TREE_TYPE (vtt), vtt,
+      sub_vtt = build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtt), vtt,
 			BINFO_SUBVTT_INDEX (binfo));
 
       args = tree_cons (NULL_TREE, sub_vtt, args);
Index: gcc/cp/rtti.c
===================================================================
--- gcc/cp/rtti.c	(revision 118474)
+++ gcc/cp/rtti.c	(working copy)
@@ -179,7 +179,7 @@ build_headof (tree exp)
 
   type = build_qualified_type (ptr_type_node,
 			       cp_type_quals (TREE_TYPE (exp)));
-  return build2 (PLUS_EXPR, type, exp,
+  return build2 (POINTER_PLUS_EXPR, type, exp,
 		 convert_to_integer (ptrdiff_type_node, offset));
 }
 
@@ -854,7 +854,7 @@ tinfo_base_init (tinfo_s *ti, tree targe
 
       /* We need to point into the middle of the vtable.  */
       vtable_ptr = build2
-	(PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
+	(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: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c	(revision 118474)
+++ gcc/tree-ssa-loop-ivopts.c	(working copy)
@@ -863,6 +863,10 @@ determine_base_object (tree expr)
       return fold_convert (ptr_type_node,
 		           build_fold_addr_expr (base));
 
+    case POINTER_PLUS_EXPR:
+      return determine_base_object (TREE_OPERAND (expr, 0));
+
+    /* FIXME: these should not exist.  */
     case PLUS_EXPR:
     case MINUS_EXPR:
       op0 = determine_base_object (TREE_OPERAND (expr, 0));
@@ -2818,6 +2822,13 @@ tree_to_aff_combination (tree expr, tree
       aff_combination_const (comb, type, int_cst_value (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 (type, &tmp);
+      aff_combination_add (comb, &tmp);
+      return;
+
     case PLUS_EXPR:
     case MINUS_EXPR:
       tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
@@ -3589,9 +3600,9 @@ force_expr_to_var_cost (tree expr)
       symbol_cost = computation_cost (addr) + 1;
 
       address_cost
-	= computation_cost (build2 (PLUS_EXPR, type,
+	= computation_cost (build2 (POINTER_PLUS_EXPR, type,
 				    addr,
-				    build_int_cst (type, 2000))) + 1;
+				    build_int_cst (sizetype, 2000))) + 1;
       if (dump_file && (dump_flags & TDF_DETAILS))
 	{
 	  fprintf (dump_file, "force_expr_to_var_cost:\n");
@@ -3630,6 +3641,7 @@ force_expr_to_var_cost (tree expr)
 
   switch (TREE_CODE (expr))
     {
+    case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
     case MINUS_EXPR:
     case MULT_EXPR:
@@ -3658,6 +3670,7 @@ force_expr_to_var_cost (tree expr)
   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: gcc/c-format.c
===================================================================
--- gcc/c-format.c	(revision 118474)
+++ gcc/c-format.c	(working copy)
@@ -1302,6 +1302,7 @@ check_format_arg (void *ctx, tree format
     }
 
   offset = 0;
+  /* FIXME: Handle POINTER_PLUS_EXPR.  */
   if (TREE_CODE (format_tree) == PLUS_EXPR)
     {
       tree arg0, arg1;
Index: gcc/tree-stdarg.c
===================================================================
--- gcc/tree-stdarg.c	(revision 118474)
+++ gcc/tree-stdarg.c	(working copy)
@@ -171,7 +171,7 @@ va_list_counter_bump (struct stdarg_info
 	  continue;
 	}
 
-      if (TREE_CODE (rhs) == PLUS_EXPR
+      if (TREE_CODE (rhs) == POINTER_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))
@@ -229,7 +229,7 @@ va_list_counter_bump (struct stdarg_info
 	  continue;
 	}
 
-      if (TREE_CODE (rhs) == PLUS_EXPR
+      if (TREE_CODE (rhs) == POINTER_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))
@@ -447,7 +447,7 @@ check_va_list_escapes (struct stdarg_inf
   if (! POINTER_TYPE_P (TREE_TYPE (rhs)))
     return;
 
-  if ((TREE_CODE (rhs) == PLUS_EXPR
+  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)
@@ -555,7 +555,7 @@ check_all_va_list_escapes (struct stdarg
 		     other_ap_temp = (some_type *) ap_temp;
 		     ap = ap_temp;
 		     statements.  */
-		  if ((TREE_CODE (rhs) == PLUS_EXPR
+		  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: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 118474)
+++ gcc/expr.c	(working copy)
@@ -7859,6 +7859,7 @@ expand_expr_real_1 (tree exp, rtx target
       return op0;
 
     case PLUS_EXPR:
+    case POINTER_PLUS_EXPR:
       /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and
 	 something else, make sure we add the register to the constant and
 	 then to the other thing.  This case can occur during strength
@@ -8885,7 +8886,7 @@ string_constant (tree arg, tree *ptr_off
       else
 	return 0;
     }
-  else if (TREE_CODE (arg) == PLUS_EXPR)
+  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: gcc/tree-ssa-address.c
===================================================================
--- gcc/tree-ssa-address.c	(revision 118474)
+++ gcc/tree-ssa-address.c	(working copy)
@@ -360,10 +360,9 @@ add_to_parts (struct mem_address *parts,
     }
 
   if (coef != 1)
-    elt = fold_build2 (MULT_EXPR, type, fold_convert (type, elt),
-		       build_int_cst_type (type, coef));
-  else
-    elt = fold_convert (type, elt);
+    elt = fold_build2 (MULT_EXPR, sizetype, fold_convert (sizetype, elt),
+		       build_int_cst_type (sizetype, coef));
+  elt = fold_convert (type, elt);
 
   if (!parts->base)
     {
@@ -373,12 +372,12 @@ add_to_parts (struct mem_address *parts,
 
   if (!parts->index)
     {
-      parts->index = elt;
+      parts->index = fold_convert (sizetype, elt);
       return;
     }
 
   /* Add ELT to base.  */
-  parts->base = fold_build2 (PLUS_EXPR, type, parts->base, elt);
+  parts->base = fold_build2 (POINTER_PLUS_EXPR, type, parts->base, fold_convert (sizetype, elt));
 }
 
 /* Finds the most expensive multiplication in ADDR that can be
@@ -387,7 +386,7 @@ add_to_parts (struct mem_address *parts,
    construct.  */
 
 static void
-most_expensive_mult_to_index (struct mem_address *parts, tree type,
+most_expensive_mult_to_index (struct mem_address *parts,
 			      struct affine_tree_combination *addr)
 {
   unsigned HOST_WIDE_INT best_mult = 0;
@@ -423,16 +422,16 @@ most_expensive_mult_to_index (struct mem
 	  continue;
 	}
 
-      elt = fold_convert (type, addr->elts[i]);
+      elt = fold_convert (sizetype, addr->elts[i]);
       if (!mult_elt)
 	mult_elt = elt;
       else
-	mult_elt = fold_build2 (PLUS_EXPR, type, mult_elt, elt);
+	mult_elt = fold_build2 (PLUS_EXPR, sizetype, mult_elt, elt);
     }
   addr->n = j;
 
   parts->index = mult_elt;
-  parts->step = build_int_cst_type (type, best_mult);
+  parts->step = build_int_cst_type (sizetype, best_mult);
 }
 
 /* Splits address ADDR into PARTS.
@@ -456,13 +455,13 @@ addr_to_parts (struct affine_tree_combin
   parts->step = NULL_TREE;
 
   if (addr->offset)
-    parts->offset = build_int_cst_type (type, addr->offset);
+    parts->offset = build_int_cst_type (sizetype, addr->offset);
   else
     parts->offset = NULL_TREE;
 
   /* First move the most expensive feasible multiplication
      to index.  */
-  most_expensive_mult_to_index (parts, type, addr);
+  most_expensive_mult_to_index (parts, addr);
 
   /* Then try to process the remaining elements.  */
   for (i = 0; i < addr->n; i++)
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 118474)
+++ gcc/c-typeck.c	(working copy)
@@ -2996,11 +2996,13 @@ build_unary_op (enum tree_code code, tre
 	      }
 
 	    inc = c_size_in_bytes (TREE_TYPE (result_type));
+	    inc = convert (sizetype, inc);
 	  }
 	else
-	  inc = integer_one_node;
-
-	inc = convert (argtype, inc);
+	  {
+	    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
@@ -3088,10 +3090,10 @@ build_unary_op (enum tree_code code, tre
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
 	{
-	  tree op0 = fold_convert (argtype, fold_offsetof (arg, val)), op1;
+	  tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
 
 	  op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
-	  return fold_build2 (PLUS_EXPR, argtype, op0, op1);
+	  return fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
 	}
 
       val = build1 (ADDR_EXPR, argtype, arg);
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c	(revision 118474)
+++ gcc/gimplify.c	(working copy)
@@ -1942,6 +1942,15 @@ gimplify_self_mod_expr (tree *expr_p, tr
 	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 = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
 
@@ -5004,6 +5013,7 @@ gimplify_omp_atomic_fetch_op (tree *expr
   /* 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;
Index: gcc/tree.def
===================================================================
--- gcc/tree.def	(revision 118474)
+++ gcc/tree.def	(working copy)
@@ -609,6 +609,10 @@ DEFTREECODE (PLUS_EXPR, "plus_expr", tcc
 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 ssizetype.  */
+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: gcc/tree-mudflap.c
===================================================================
--- gcc/tree-mudflap.c	(revision 118474)
+++ gcc/tree-mudflap.c	(working copy)
@@ -821,8 +821,8 @@ mf_xform_derefs_1 (block_stmt_iterator *
 	    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,
+            addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+				addr, fold_convert (sizetype,
 						    byte_position (field)));
           }
         else
@@ -839,17 +839,17 @@ mf_xform_derefs_1 (block_stmt_iterator *
     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);
+      limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+			   fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base, size),
+			   build_int_cst (sizetype, -1));
       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));
+      limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+			   fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base, size),
+			   build_int_cst (sizetype, -1));
       break;
 
     case ARRAY_RANGE_REF:
@@ -878,12 +878,12 @@ mf_xform_derefs_1 (block_stmt_iterator *
 
         addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
         addr = convert (ptr_type_node, addr);
-        addr = fold_build2 (PLUS_EXPR, ptr_type_node, addr, ofs);
+        addr = fold_build2 (POINTER_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);
+        limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+                             fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base, size),
+                             size_int (-1));
       }
       break;
 
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c	(revision 118474)
+++ gcc/tree-ssa-forwprop.c	(working copy)
@@ -743,6 +743,7 @@ forward_propagate_addr_expr_1 (tree stmt
       || !integer_zerop (TREE_OPERAND (array_ref, 1)))
     return false;
 
+  /* FIXME: this should be changed to POINTER_PLUS_EXPR.  */
   /* 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)
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(revision 118474)
+++ gcc/varasm.c	(working copy)
@@ -3852,6 +3852,7 @@ initializer_constant_valid_p (tree value
       }
       break;
 
+    case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       if (! INTEGRAL_TYPE_P (endtype)
 	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
Index: gcc/tree-ssa-loop-prefetch.c
===================================================================
--- gcc/tree-ssa-loop-prefetch.c	(revision 118474)
+++ gcc/tree-ssa-loop-prefetch.c	(working copy)
@@ -357,7 +357,7 @@ idx_analyze_ref (tree base, tree *index,
       istep = int_cst_value (step);
     }
 
-  if (TREE_CODE (ibase) == PLUS_EXPR
+  if (TREE_CODE (ibase) == POINTER_PLUS_EXPR
       && cst_and_fits_in_hwi (TREE_OPERAND (ibase, 1)))
     {
       idelta = int_cst_value (TREE_OPERAND (ibase, 1));
@@ -838,8 +838,8 @@ issue_prefetch_ref (struct mem_ref *ref,
     {
       /* 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 = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+			  addr_base, build_int_cst (sizetype, delta));
       addr = force_gimple_operand_bsi (&bsi, unshare_expr (addr), true, NULL);
 
       /* Create the prefetch instruction.  */
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c	(revision 118474)
+++ gcc/tree-inline.c	(working copy)
@@ -1696,6 +1696,7 @@ estimate_num_insns_1 (tree *tp, int *wal
     case VEC_COND_EXPR:
 
     case PLUS_EXPR:
+    case POINTER_PLUS_EXPR:
     case MINUS_EXPR:
     case MULT_EXPR:
 
Index: gcc/tree-vect-transform.c
===================================================================
--- gcc/tree-vect-transform.c	(revision 118474)
+++ gcc/tree-vect-transform.c	(working copy)
@@ -152,6 +152,7 @@ vect_create_addr_base_for_vector_ref (tr
 
   /* 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);  
@@ -159,7 +160,7 @@ vect_create_addr_base_for_vector_ref (tr
 
   if (offset)
     {
-      tree tmp = create_tmp_var (TREE_TYPE (base_offset), "offset");
+      tree tmp = create_tmp_var (sizetype, "offset");
       add_referenced_var (tmp);
       offset = fold_build2 (MULT_EXPR, TREE_TYPE (offset), offset,
 			    DR_STEP (dr));
@@ -170,7 +171,7 @@ vect_create_addr_base_for_vector_ref (tr
     }
   
   /* base + base_offset */
-  addr_base = fold_build2 (PLUS_EXPR, TREE_TYPE (data_ref_base), data_ref_base,
+  addr_base = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (data_ref_base), data_ref_base,
 			   base_offset);
 
   /* addr_expr = addr_base */
Index: gcc/tree-object-size.c
===================================================================
--- gcc/tree-object-size.c	(revision 118474)
+++ gcc/tree-object-size.c	(working copy)
@@ -549,7 +549,7 @@ merge_object_sizes (struct object_size_i
 
 
 /* Compute object_sizes for PTR, defined to VALUE, which is
-   a PLUS_EXPR.  Return true if the object size might need reexamination
+   a POINTER_PLUS_EXPR.  Return true if the object size might need reexamination
    later.  */
 
 static bool
@@ -557,33 +557,17 @@ plus_expr_object_size (struct object_siz
 {
   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);
+  gcc_assert (TREE_CODE (value) == POINTER_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
+  if (TREE_CODE (op1) == INTEGER_CST
       && (TREE_CODE (op0) == SSA_NAME
 	  || TREE_CODE (op0) == ADDR_EXPR))
     {
@@ -627,7 +611,7 @@ plus_expr_object_size (struct object_siz
    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,
+   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
@@ -708,7 +692,7 @@ collect_object_sizes_for (struct object_
 	    && POINTER_TYPE_P (TREE_TYPE (rhs)))
 	  reexamine = merge_object_sizes (osi, var, rhs, 0);
 
-	else if (TREE_CODE (rhs) == PLUS_EXPR)
+	else if (TREE_CODE (rhs) == POINTER_PLUS_EXPR)
 	  reexamine = plus_expr_object_size (osi, var, rhs);
 
 	else
@@ -832,23 +816,14 @@ check_for_plus_in_loops_1 (struct object
 
 	if (TREE_CODE (rhs) == SSA_NAME)
 	  check_for_plus_in_loops_1 (osi, rhs, depth);
-	else if (TREE_CODE (rhs) == PLUS_EXPR)
+	else if (TREE_CODE (rhs) == POINTER_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);
-	      }
+	    basevar = op0;
+	    cst = op1;
 	    gcc_assert (TREE_CODE (cst) == INTEGER_CST);
 
 	    check_for_plus_in_loops_1 (osi, basevar,
@@ -908,23 +883,14 @@ check_for_plus_in_loops (struct object_s
 	      rhs = arg;
 	  }
 
-	if (TREE_CODE (rhs) == PLUS_EXPR)
+	if (TREE_CODE (rhs) == POINTER_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);
-	      }
+	    basevar = op0;
+	    cst = op1;
 	    gcc_assert (TREE_CODE (cst) == INTEGER_CST);
 
 	    if (integer_zerop (cst))
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 118474)
+++ gcc/c-common.c	(working copy)
@@ -2483,12 +2483,17 @@ pointer_int_sum (enum tree_code resultco
      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));
+  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.  */
-  return fold_build2 (resultcode, result_type, ptrop, intop);
+  return fold_build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop);
 }
 
 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
Index: gcc/tree-ssa-structalias.c
===================================================================
--- gcc/tree-ssa-structalias.c	(revision 118474)
+++ gcc/tree-ssa-structalias.c	(working copy)
@@ -3287,20 +3287,16 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc
   VEC (ce_s, heap) *temp = NULL;
   unsigned int rhsoffset = 0;
 
-  if (TREE_CODE (expr) != PLUS_EXPR
-      && TREE_CODE (expr) != MINUS_EXPR)
+  if (TREE_CODE (expr) != POINTER_PLUS_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;
-    }
+  /* FIXME: We should only need to check for constant here.  */
+  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++)
Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 118474)
+++ gcc/tree-cfg.c	(working copy)
@@ -3381,7 +3381,36 @@ verify_expr (tree *tp, int *walk_subtree
 	}
       *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
+	 ssizetype.  */
+      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 ssizetype.");
+	  return t;
+	}
+      /* FALLTHROUGH */
     case LT_EXPR:
     case LE_EXPR:
     case GT_EXPR:
@@ -3396,8 +3425,6 @@ verify_expr (tree *tp, int *walk_subtree
     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:

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