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