On Mon, Sep 22, 2025 at 5:36 PM Andrew Pinski
<[email protected]> wrote:
>
> This code dates before gimple tuples was around. So it uses both MODIFY_EXPR 
> and
> INDIRECT_REF :).
> For `__builtin_va_start(ptr, 0)` it exands into:
> ```
> _t = __builtin_next_arg (0);
> *ptr = _t;
> ```
> We need to get a new VDEF for the next arg call so we don't need to do a
> ssa update too.
>
> For `__builtin_va_copy(ptr, b)`, it expands into:
> ```
> *ptr = b;
> ```
> Which is still a store.
>
> For `__builtin_va_end(ptr)`, we change it into a GIMPLE_NOP.
>
> Since we don't return a value, we need to also set TODO_update_address_taken
> on the todo manually too.

We do have to?  That's an optimization.

Looks OK to me, but I'm confused about the above.

Richard.

>
> Note this code will be moved into gimple_fold later on. This is part of the
> reason for updating this code. The other side is this simplifies the code
> too.
>
> gcc/ChangeLog:
>
>         * tree-ssa-ccp.cc (optimize_stdarg_builtin): Mannually create the
>         gimple statements instead of depending on the gimplifier.
>         (pass_fold_builtins::execute): Handle updated call to 
> optimize_stdarg_builtin.
>
> Signed-off-by: Andrew Pinski <[email protected]>
> ---
>  gcc/tree-ssa-ccp.cc | 87 ++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 66 insertions(+), 21 deletions(-)
>
> diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
> index 1fbc3de2bfe..c9ffd2af85c 100644
> --- a/gcc/tree-ssa-ccp.cc
> +++ b/gcc/tree-ssa-ccp.cc
> @@ -3175,14 +3175,16 @@ optimize_stack_restore (gimple_stmt_iterator i)
>  /* If va_list type is a simple pointer and nothing special is needed,
>     optimize __builtin_va_start (&ap, 0) into ap = __builtin_next_arg (0),
>     __builtin_va_end (&ap) out as NOP and __builtin_va_copy into a simple
> -   pointer assignment.  */
> +   pointer assignment.  Returns true if a change happened.  */
>
> -static tree
> -optimize_stdarg_builtin (gimple *call)
> +static bool
> +optimize_stdarg_builtin (gimple_stmt_iterator *gsi, gimple *call)
>  {
>    tree callee, lhs, rhs, cfun_va_list;
>    bool va_list_simple_ptr;
>    location_t loc = gimple_location (call);
> +  gimple *nstmt0, *nstmt;
> +  tree tlhs, oldvdef, newvdef;
>
>    callee = gimple_call_fndecl (call);
>
> @@ -3197,48 +3199,90 @@ optimize_stdarg_builtin (gimple *call)
>        if (!va_list_simple_ptr
>           || targetm.expand_builtin_va_start != NULL
>           || !builtin_decl_explicit_p (BUILT_IN_NEXT_ARG))
> -       return NULL_TREE;
> +       return false;
>
>        if (gimple_call_num_args (call) != 2)
> -       return NULL_TREE;
> +       return false;
>
>        lhs = gimple_call_arg (call, 0);
>        if (!POINTER_TYPE_P (TREE_TYPE (lhs))
>           || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs)))
>              != TYPE_MAIN_VARIANT (cfun_va_list))
> -       return NULL_TREE;
> +       return false;
> +      /* Create `tlhs = __builtin_next_arg(0);`. */
> +      tlhs = make_ssa_name (cfun_va_list);
> +      nstmt0 = gimple_build_call (builtin_decl_explicit (BUILT_IN_NEXT_ARG), 
> 1, integer_zero_node);
> +      lhs = fold_build2 (MEM_REF, cfun_va_list, lhs, build_zero_cst 
> (TREE_TYPE (lhs)));
> +      gimple_call_set_lhs (nstmt0, tlhs);
> +      gimple_set_location (nstmt0, loc);
> +      gimple_move_vops (nstmt0, call);
> +      gsi_replace (gsi, nstmt0, false);
> +      oldvdef = gimple_vdef (nstmt0);
> +      newvdef = make_ssa_name (gimple_vop (cfun), nstmt0);
> +      gimple_set_vdef (nstmt0, newvdef);
> +
> +      /* Create `*lhs = tlhs;`.  */
> +      nstmt = gimple_build_assign (lhs, tlhs);
> +      gimple_set_location (nstmt, loc);
> +      gimple_set_vuse (nstmt, newvdef);
> +      gimple_set_vdef (nstmt, oldvdef);
> +      SSA_NAME_DEF_STMT (oldvdef) = nstmt;
> +      gsi_insert_after (gsi, nstmt, GSI_NEW_STMT);
>
> -      lhs = build_fold_indirect_ref_loc (loc, lhs);
> -      rhs = build_call_expr_loc (loc, builtin_decl_explicit 
> (BUILT_IN_NEXT_ARG),
> -                             1, integer_zero_node);
> -      rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
> -      return build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
> +      if (dump_file && (dump_flags & TDF_DETAILS))
> +       {
> +         fprintf (dump_file, "Simplified\n  ");
> +         print_gimple_stmt (dump_file, call, 0, dump_flags);
> +         fprintf (dump_file, "into\n  ");
> +         print_gimple_stmt (dump_file, nstmt0, 0, dump_flags);
> +         fprintf (dump_file, "  ");
> +         print_gimple_stmt (dump_file, nstmt, 0, dump_flags);
> +       }
> +      return true;
>
>      case BUILT_IN_VA_COPY:
>        if (!va_list_simple_ptr)
> -       return NULL_TREE;
> +       return false;
>
>        if (gimple_call_num_args (call) != 2)
> -       return NULL_TREE;
> +       return false;
>
>        lhs = gimple_call_arg (call, 0);
>        if (!POINTER_TYPE_P (TREE_TYPE (lhs))
>           || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs)))
>              != TYPE_MAIN_VARIANT (cfun_va_list))
> -       return NULL_TREE;
> -
> -      lhs = build_fold_indirect_ref_loc (loc, lhs);
> +       return false;
>        rhs = gimple_call_arg (call, 1);
>        if (TYPE_MAIN_VARIANT (TREE_TYPE (rhs))
>           != TYPE_MAIN_VARIANT (cfun_va_list))
> -       return NULL_TREE;
> +       return false;
>
> -      rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
> -      return build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
> +      lhs = fold_build2 (MEM_REF, cfun_va_list, lhs, build_zero_cst 
> (TREE_TYPE (lhs)));
> +      nstmt = gimple_build_assign (lhs, rhs);
> +      gimple_set_location (nstmt, loc);
> +      gimple_move_vops (nstmt, call);
> +      gsi_replace (gsi, nstmt, false);
> +
> +      if (dump_file && (dump_flags & TDF_DETAILS))
> +       {
> +         fprintf (dump_file, "Simplified\n  ");
> +         print_gimple_stmt (dump_file, call, 0, dump_flags);
> +         fprintf (dump_file, "into\n  ");
> +         print_gimple_stmt (dump_file, nstmt, 0, dump_flags);
> +       }
> +      return true;
>
>      case BUILT_IN_VA_END:
>        /* No effect, so the statement will be deleted.  */
> -      return integer_zero_node;
> +      if (dump_file && (dump_flags & TDF_DETAILS))
> +       {
> +         fprintf (dump_file, "Removed\n  ");
> +         print_gimple_stmt (dump_file, call, 0, dump_flags);
> +       }
> +      unlink_stmt_vdef (call);
> +      release_defs (call);
> +      gsi_replace (gsi, gimple_build_nop (), true);
> +      return true;
>
>      default:
>        gcc_unreachable ();
> @@ -4426,7 +4470,8 @@ pass_fold_builtins::execute (function *fun)
>                 case BUILT_IN_VA_END:
>                 case BUILT_IN_VA_COPY:
>                   /* These shouldn't be folded before pass_stdarg.  */
> -                 result = optimize_stdarg_builtin (stmt);
> +                 if (optimize_stdarg_builtin (&i, stmt))
> +                   todoflags |= TODO_update_address_taken;
>                   break;
>
>                 default:;
> --
> 2.43.0
>

Reply via email to