From: Andrew Pinski Date: Tue, 23 Sep 2025 19:58:37 +0000 (-0700) Subject: fab/gimple-fold/forwprop: Move va_args folding to gimple_fold [PR121762] X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6eff00d2fc3b709d27f7c3727168e1f8336246a5;p=thirdparty%2Fgcc.git fab/gimple-fold/forwprop: Move va_args folding to gimple_fold [PR121762] This moves the va_args functions folding to gimple-fold. Right now this is still kept for the last folding but later it can move sometime after stdargs pass is run by checking PROP_gimple_lva instead. Also for forwprop, if a folding happens for the last folding we need to maybe update the variables as non-addressable like what is done in fab. It was originally added in fab for __builtin_sincos->__builtin_cexpi folding (PR39643). After the removal of fab, this will also be the last pass which updates address taken too. PR tree-optimization/121762 gcc/ChangeLog: * gimple-fold.cc (gimple_fold_builtin_stdarg): New function, moved from tree-ssa-ccp.cc (optimize_stdarg_builtin). (gimple_fold_builtin): Call gimple_fold_builtin_stdarg for va_start, va_copy and va_end. * tree-ssa-ccp.cc (optimize_stdarg_builtin): Remove. (pass_fold_builtins::execute): Remove handling of va_start, va_copy and va_end. * tree-ssa-forwprop.cc (pass_forwprop::execute): Update todos if fold_stmt return true if last forwprop to include TODO_update_address_taken. Signed-off-by: Andrew Pinski --- diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index a12fb5e8eab..2f64de2fb41 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -5252,6 +5252,127 @@ gimple_fold_builtin_assume_aligned (gimple_stmt_iterator *gsi) return true; } +/* 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. Returns true if a change happened. */ + +static bool +gimple_fold_builtin_stdarg (gimple_stmt_iterator *gsi, gcall *call) +{ + /* These shouldn't be folded before pass_stdarg. */ + if (!(cfun->curr_properties & PROP_last_full_fold)) + return false; + + 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); + + cfun_va_list = targetm.fn_abi_va_list (callee); + va_list_simple_ptr = POINTER_TYPE_P (cfun_va_list) + && (TREE_TYPE (cfun_va_list) == void_type_node + || TREE_TYPE (cfun_va_list) == char_type_node); + + switch (DECL_FUNCTION_CODE (callee)) + { + case BUILT_IN_VA_START: + if (!va_list_simple_ptr + || targetm.expand_builtin_va_start != NULL + || !builtin_decl_explicit_p (BUILT_IN_NEXT_ARG)) + return false; + + if (gimple_call_num_args (call) != 2) + 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 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); + + 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 false; + + if (gimple_call_num_args (call) != 2) + 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 false; + rhs = gimple_call_arg (call, 1); + if (TYPE_MAIN_VARIANT (TREE_TYPE (rhs)) + != TYPE_MAIN_VARIANT (cfun_va_list)) + return false; + + 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. */ + 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 (); + } +} + /* Fold the non-target builtin at *GSI and return whether any simplification was made. */ @@ -5270,6 +5391,10 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi) enum built_in_function fcode = DECL_FUNCTION_CODE (callee); switch (fcode) { + case BUILT_IN_VA_START: + case BUILT_IN_VA_END: + case BUILT_IN_VA_COPY: + return gimple_fold_builtin_stdarg (gsi, stmt); case BUILT_IN_BCMP: return gimple_fold_builtin_bcmp (gsi); case BUILT_IN_BCOPY: diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc index b69a8b64a61..2d16395ac68 100644 --- a/gcc/tree-ssa-ccp.cc +++ b/gcc/tree-ssa-ccp.cc @@ -3085,124 +3085,6 @@ make_pass_ccp (gcc::context *ctxt) return new pass_ccp (ctxt); } -/* 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. Returns true if a change happened. */ - -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); - - cfun_va_list = targetm.fn_abi_va_list (callee); - va_list_simple_ptr = POINTER_TYPE_P (cfun_va_list) - && (TREE_TYPE (cfun_va_list) == void_type_node - || TREE_TYPE (cfun_va_list) == char_type_node); - - switch (DECL_FUNCTION_CODE (callee)) - { - case BUILT_IN_VA_START: - if (!va_list_simple_ptr - || targetm.expand_builtin_va_start != NULL - || !builtin_decl_explicit_p (BUILT_IN_NEXT_ARG)) - return false; - - if (gimple_call_num_args (call) != 2) - 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 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); - - 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 false; - - if (gimple_call_num_args (call) != 2) - 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 false; - rhs = gimple_call_arg (call, 1); - if (TYPE_MAIN_VARIANT (TREE_TYPE (rhs)) - != TYPE_MAIN_VARIANT (cfun_va_list)) - return false; - - 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. */ - 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 (); - } -} - - /* Convert _1 = __atomic_fetch_or_* (ptr_6, 1, _3); _7 = ~_1; @@ -4339,14 +4221,6 @@ pass_fold_builtins::execute (function *fun) false); break; - case BUILT_IN_VA_START: - case BUILT_IN_VA_END: - case BUILT_IN_VA_COPY: - /* These shouldn't be folded before pass_stdarg. */ - if (optimize_stdarg_builtin (&i, stmt)) - todoflags |= TODO_update_address_taken; - break; - default:; } diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc index 9307e216207..2c6e1eab9cd 100644 --- a/gcc/tree-ssa-forwprop.cc +++ b/gcc/tree-ssa-forwprop.cc @@ -5463,6 +5463,11 @@ pass_forwprop::execute (function *fun) if (fold_stmt (&gsi, fwprop_ssa_val, simple_dce_worklist)) { changed = true; + /* There is no updating of the address + taken after the last forwprop so update + the addresses when a folding happened. */ + if (last_p) + todoflags |= TODO_update_address_taken; stmt = gsi_stmt (gsi); /* Cleanup the CFG if we simplified a condition to true or false. */