New branch for POINTER_PLUS_EXPR

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Thu Nov 23 19:06:00 GMT 2006


Hello,

>   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.

what is the name of the branch?  I might have a look at the scev
problems.

Zdenek

> 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:



More information about the Gcc-patches mailing list