From f11a7b6d57f6fcba1bf2e5a0403dc49120195320 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Sun, 27 Sep 2015 09:02:00 +0000 Subject: revert to assign_parms assignments using default defs Revert the fragile and complicated changes to assign_parms designed to enable it to use RTL assigments chosen by cfgexpand, and instead have cfgexpand use the RTL assignments by assign_parms, keying them off of the default defs that are now necessarily introduced for each parm and result. The possible lack of a default def was already a problem, and the fallbacks in place were not enough, as shown by PR67312. We now have checking asserts in set_rtl that verify that we're assigning to each var a piece of RTL that matches the expectations set forth by use_register_for_decl. for gcc/ChangeLog PR rtl-optimization/64164 PR tree-optimization/67312 PR middle-end/67340 PR middle-end/67490 PR bootstrap/67597 * cfgexpand.c (parm_in_stack_slot_p): Remove. (ssa_default_def_partition): Remove. (get_rtl_for_parm_ssa_default_def): Remove. (set_rtl): Check that RTL assignments match expectations. Loop on SUBREGs, CONCATs and PARALLELs subexprs. Set only the default def location for params and results. Record SSA names or types in REG and MEM attrs, respectively. (set_parm_rtl): New. (expand_one_ssa_partition): Drop logic that assigned MEMs with unassigned addresses. (adjust_one_expanded_partition_var): Don't accept NULL RTL on deferred stack alloc vars. (expand_used_vars): Skip partitions holding parm default defs. Move adjust_one_expanded_partition_var loop... (pass_expand::execute): ... here. Drop redundant assert. Adjust comments before the final loop over all ssa names. Require assigned rtl of parms and results to match exactly. Reset its attributes to match them, not any other variables in the same partition. (expand_debug_expr): Use entry value for PARM's default defs only iff they have zero nondebug uses. * cfgexpand.h (parm_in_stack_slot_p): Remove. (get_rtl_for_parm_ssa_default_def): Remove. (set_parm_rtl): Declare. * doc/invoke.texi: Improve wording. * explow.c (promote_decl_mode): Fix promote_function_mode for result decls not by reference. (promote_ssa_mode): Disregard BLKmode from promote_decl, and bypass TYPE_MODE to get the actual vector mode. * function.c: Include tree-dfa.h. Revert 2015-08-14's and 2015-08-19's changes as follows. Drop include of basic-block.h and df.h. (rtl_for_parm): Remove. (maybe_reset_rtl_for_parm): Remove. (parm_in_unassigned_mem_p): Remove. (use_register_for_decl): Add logic for RESULT_DECLs matching assign_parms' behavior. (split_complex_args): Revert. (assign_parms_augmented_arg_list): Revert. Add comment referencing the logic above. (assign_parm_adjust_stack_rtl): Revert. (assign_parm_setup_block): Revert. Use set_parm_rtl instead of SET_DECL_RTL. Set up a REG if the parm demands so. (assign_parm_setup_reg): Revert. Consolidated SET_DECL_RTL calls into a single set_parm_rtl. Set up a temporary RTL temporarily for expand_assignment. (assign_parm_setup_stack): Revert. Use set_parm_rtl. (assign_parms_unsplit_complex): Revert. Use set_parm_rtl. (assign_bounds): Revert. (assign_parms): Revert. Use set_parm_rtl. (allocate_struct_function): Relayout result and parms of non-abstruct functions. (expand_function_start): Revert. Use set_parm_rtl. If the result is not a hard reg, create a pseudo from the promoted mode of the default def. Promote static chain mode. * tree-outof-ssa.c (remove_ssa_form): Drop unused partition_has_default_def. Set up partitions_for_parm_default_defs. (finish_out_of_ssa): Remove partition_has_default_def. Release partitions_for_parm_default_defs. * tree-outof-ssa.h (struct ssaexpand): Remove partition_has_default_def. Add partitions_for_parm_default_defs. * tree-ssa-coalesce.c: Include tree-dfa.h, tm_p.h and stor-layout.h. (build_ssa_conflict_graph): Fix conflict-detection of default defs of even unused default defs of params and results. (for_all_parms): New. (create_default_def): New. (register_default_def): New. (coalesce_with_default): New. (create_outofssa_var_map): Create default defs for all parms and results, and register their partitions. Add GIMPLE_RETURN operands as coalesce candidates with results. Add default defs of each parm or result as coalesce candidates with its other defs. Mark each result def, and each default def of parms, as used_in_copy. (gimple_can_coalesce_p): Call it. Call use_register_for_decl with the ssa names, even anonymous ones. Drop parm_in_stack_slot_p calls. Require same signedness and alignment. (coalesce_ssa_name): Add coalesce candidates for all defs of each parm and result, even unused ones. (parm_default_def_partition_arg): New type. (set_parm_default_def_partition): New. (get_parm_default_def_partitions): New. * tree-ssa-coalesce.h (get_parm_default_def_partitions): New. * tree-ssa-live.c (partition_view_init): Regard unused defs of parms and results as used. (verify_live_on_entry): Don't error out just because they're not live. for gcc/testsuite/ChangeLog PR rtl-optimization/64164 PR tree-optimization/67312 * gcc.dg/pr67312.c: New. From Zdenek Sojka. * gcc.target/i386/stackalign/return-4.c: Add -O. From-SVN: r228175 --- gcc/tree-ssa-coalesce.c | 231 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 193 insertions(+), 38 deletions(-) (limited to 'gcc/tree-ssa-coalesce.c') diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c index 8af6583..ff75877 100644 --- a/gcc/tree-ssa-coalesce.c +++ b/gcc/tree-ssa-coalesce.c @@ -39,7 +39,9 @@ along with GCC; see the file COPYING3. If not see #include "cfgexpand.h" #include "explow.h" #include "diagnostic-core.h" - +#include "tree-dfa.h" +#include "tm_p.h" +#include "stor-layout.h" /* This set of routines implements a coalesce_list. This is an object which is used to track pairs of ssa_names which are desirable to coalesce @@ -877,26 +879,30 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo) } /* Pretend there are defs for params' default defs at the start - of the (post-)entry block. */ + of the (post-)entry block. This will prevent PARM_DECLs from + coalescing into the same partition. Although RESULT_DECLs' + default defs don't have a useful initial value, we have to + prevent them from coalescing with PARM_DECLs' default defs + too, otherwise assign_parms would attempt to assign different + RTL to the same partition. */ if (bb == entry) { - unsigned base; - bitmap_iterator bi; - EXECUTE_IF_SET_IN_BITMAP (live->live_base_var, 0, base, bi) + unsigned i; + for (i = 1; i < num_ssa_names; i++) { - bitmap_iterator bi2; - unsigned part; - EXECUTE_IF_SET_IN_BITMAP (live->live_base_partitions[base], - 0, part, bi2) - { - tree var = partition_to_var (map, part); - if (!SSA_NAME_VAR (var) - || (TREE_CODE (SSA_NAME_VAR (var)) != PARM_DECL - && TREE_CODE (SSA_NAME_VAR (var)) != RESULT_DECL) - || !SSA_NAME_IS_DEFAULT_DEF (var)) - continue; - live_track_process_def (live, var, graph); - } + tree var = ssa_name (i); + + if (!var + || !SSA_NAME_IS_DEFAULT_DEF (var) + || !SSA_NAME_VAR (var) + || VAR_P (SSA_NAME_VAR (var))) + continue; + + live_track_process_def (live, var, graph); + /* Process a use too, so that it remains live and + conflicts with other parms' default defs, even unused + ones. */ + live_track_process_use (live, var); } } @@ -937,6 +943,71 @@ fail_abnormal_edge_coalesce (int x, int y) internal_error ("SSA corruption"); } +/* Call CALLBACK for all PARM_DECLs and RESULT_DECLs for which + assign_parms may ask for a default partition. */ + +static void +for_all_parms (void (*callback)(tree var, void *arg), void *arg) +{ + for (tree var = DECL_ARGUMENTS (current_function_decl); var; + var = DECL_CHAIN (var)) + callback (var, arg); + if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl)))) + callback (DECL_RESULT (current_function_decl), arg); + if (cfun->static_chain_decl) + callback (cfun->static_chain_decl, arg); +} + +/* Create a default def for VAR. */ + +static void +create_default_def (tree var, void *arg ATTRIBUTE_UNUSED) +{ + if (!is_gimple_reg (var)) + return; + + tree ssa = get_or_create_ssa_default_def (cfun, var); + gcc_assert (ssa); +} + +/* Register VAR's default def in MAP. */ + +static void +register_default_def (tree var, void *map_) +{ + var_map map = (var_map)map_; + + if (!is_gimple_reg (var)) + return; + + tree ssa = ssa_default_def (cfun, var); + gcc_assert (ssa); + + register_ssa_partition (map, ssa); +} + +/* If VAR is an SSA_NAME associated with a PARM_DECL or a RESULT_DECL, + and the DECL's default def is unused (i.e., it was introduced by + create_default_def), mark VAR and the default def for + coalescing. */ + +static void +coalesce_with_default (tree var, coalesce_list_p cl, bitmap used_in_copy) +{ + if (SSA_NAME_IS_DEFAULT_DEF (var) + || !SSA_NAME_VAR (var) + || VAR_P (SSA_NAME_VAR (var))) + return; + + tree ssa = ssa_default_def (cfun, SSA_NAME_VAR (var)); + if (!has_zero_uses (ssa)) + return; + + add_cost_one_coalesce (cl, SSA_NAME_VERSION (ssa), SSA_NAME_VERSION (var)); + bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (var)); + /* Default defs will have their used_in_copy bits set at the end of + create_outofssa_var_map. */ +} /* This function creates a var_map for the current function as well as creating a coalesce list for use later in the out of ssa process. */ @@ -954,8 +1025,12 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy) int v1, v2, cost; unsigned i; + for_all_parms (create_default_def, NULL); + map = init_var_map (num_ssa_names); + for_all_parms (register_default_def, map); + FOR_EACH_BB_FN (bb, cfun) { tree arg; @@ -1034,6 +1109,30 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy) } break; + case GIMPLE_RETURN: + { + tree res = DECL_RESULT (current_function_decl); + if (VOID_TYPE_P (TREE_TYPE (res)) + || !is_gimple_reg (res)) + break; + tree rhs1 = gimple_return_retval (as_a (stmt)); + if (!rhs1) + break; + tree lhs = ssa_default_def (cfun, res); + gcc_assert (lhs); + if (TREE_CODE (rhs1) == SSA_NAME + && gimple_can_coalesce_p (lhs, rhs1)) + { + v1 = SSA_NAME_VERSION (lhs); + v2 = SSA_NAME_VERSION (rhs1); + cost = coalesce_cost_bb (bb); + add_coalesce (cl, v1, v2, cost); + bitmap_set_bit (used_in_copy, v1); + bitmap_set_bit (used_in_copy, v2); + } + break; + } + case GIMPLE_ASM: { gasm *asm_stmt = as_a (stmt); @@ -1100,10 +1199,13 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy) var = ssa_name (i); if (var != NULL_TREE && !virtual_operand_p (var)) { + coalesce_with_default (var, cl, used_in_copy); + /* Add coalesces between all the result decls. */ if (SSA_NAME_VAR (var) && TREE_CODE (SSA_NAME_VAR (var)) == RESULT_DECL) { + bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (var)); if (first == NULL_TREE) first = var; else @@ -1111,8 +1213,6 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy) gcc_assert (gimple_can_coalesce_p (var, first)); v1 = SSA_NAME_VERSION (first); v2 = SSA_NAME_VERSION (var); - bitmap_set_bit (used_in_copy, v1); - bitmap_set_bit (used_in_copy, v2); cost = coalesce_cost_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)); add_coalesce (cl, v1, v2, cost); } @@ -1121,7 +1221,9 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy) since they will have to be coalesced with the base variable. If not marked as present, they won't be in the coalesce view. */ if (SSA_NAME_IS_DEFAULT_DEF (var) - && !has_zero_uses (var)) + && (!has_zero_uses (var) + || (SSA_NAME_VAR (var) + && !VAR_P (SSA_NAME_VAR (var))))) bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (var)); } } @@ -1367,30 +1469,38 @@ gimple_can_coalesce_p (tree name1, tree name2) /* We don't want to coalesce two SSA names if one of the base variables is supposed to be a register while the other is - supposed to be on the stack. Anonymous SSA names take - registers, but when not optimizing, user variables should go - on the stack, so coalescing them with the anonymous variable - as the partition leader would end up assigning the user - variable to a register. Don't do that! */ - bool reg1 = !var1 || use_register_for_decl (var1); - bool reg2 = !var2 || use_register_for_decl (var2); + supposed to be on the stack. Anonymous SSA names most often + take registers, but when not optimizing, user variables + should go on the stack, so coalescing them with the anonymous + variable as the partition leader would end up assigning the + user variable to a register. Don't do that! */ + bool reg1 = use_register_for_decl (name1); + bool reg2 = use_register_for_decl (name2); if (reg1 != reg2) return false; - /* Check that the promoted modes are the same. We don't want to - coalesce if the promoted modes would be different. Only + /* Check that the promoted modes and unsignedness are the same. + We don't want to coalesce if the promoted modes would be + different, or if they would sign-extend differently. Only PARM_DECLs and RESULT_DECLs have different promotion rules, so skip the test if both are variables, or both are anonymous - SSA_NAMEs. Now, if a parm or result has BLKmode, do not - coalesce its SSA versions with those of any other variables, - because it may be passed by reference. */ + SSA_NAMEs. */ + int unsigned1, unsigned2; return ((!var1 || VAR_P (var1)) && (!var2 || VAR_P (var2))) - || (/* The case var1 == var2 is already covered above. */ - !parm_in_stack_slot_p (var1) - && !parm_in_stack_slot_p (var2) - && promote_ssa_mode (name1, NULL) == promote_ssa_mode (name2, NULL)); + || ((promote_ssa_mode (name1, &unsigned1) + == promote_ssa_mode (name2, &unsigned2)) + && unsigned1 == unsigned2); } + /* If alignment requirements are different, we can't coalesce. */ + if (MINIMUM_ALIGNMENT (t1, + var1 ? DECL_MODE (var1) : TYPE_MODE (t1), + var1 ? LOCAL_DECL_ALIGNMENT (var1) : TYPE_ALIGN (t1)) + != MINIMUM_ALIGNMENT (t2, + var2 ? DECL_MODE (var2) : TYPE_MODE (t2), + var2 ? LOCAL_DECL_ALIGNMENT (var2) : TYPE_ALIGN (t2))) + return false; + /* If the types are not the same, check for a canonical type match. This (for example) allows coalescing when the types are fundamentally the same, but just have different names. @@ -1639,7 +1749,8 @@ coalesce_ssa_name (void) if (a && SSA_NAME_VAR (a) && !DECL_IGNORED_P (SSA_NAME_VAR (a)) - && (!has_zero_uses (a) || !SSA_NAME_IS_DEFAULT_DEF (a))) + && (!has_zero_uses (a) || !SSA_NAME_IS_DEFAULT_DEF (a) + || !VAR_P (SSA_NAME_VAR (a)))) { tree *slot = ssa_name_hash.find_slot (a, INSERT); @@ -1721,3 +1832,47 @@ coalesce_ssa_name (void) return map; } + +/* We need to pass two arguments to set_parm_default_def_partition, + but for_all_parms only supports one. Use a pair. */ + +typedef std::pair parm_default_def_partition_arg; + +/* Set in ARG's PARTS bitmap the bit corresponding to the partition in + ARG's MAP containing VAR's default def. */ + +static void +set_parm_default_def_partition (tree var, void *arg_) +{ + parm_default_def_partition_arg *arg = (parm_default_def_partition_arg *)arg_; + var_map map = arg->first; + bitmap parts = arg->second; + + if (!is_gimple_reg (var)) + return; + + tree ssa = ssa_default_def (cfun, var); + gcc_assert (ssa); + + int version = var_to_partition (map, ssa); + gcc_assert (version != NO_PARTITION); + + bool changed = bitmap_set_bit (parts, version); + gcc_assert (changed); +} + +/* Allocate and return a bitmap that has a bit set for each partition + that contains a default def for a parameter. */ + +extern bitmap +get_parm_default_def_partitions (var_map map) +{ + bitmap parm_default_def_parts = BITMAP_ALLOC (NULL); + + parm_default_def_partition_arg + arg = std::make_pair (map, parm_default_def_parts); + + for_all_parms (set_parm_default_def_partition, &arg); + + return parm_default_def_parts; +} -- cgit v1.1