diff options
-rw-r--r-- | gcc/ipa-param-manipulation.c | 33 | ||||
-rw-r--r-- | gcc/ipa-param-manipulation.h | 7 | ||||
-rw-r--r-- | gcc/ipa-prop.c | 73 | ||||
-rw-r--r-- | gcc/ipa-prop.h | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ipa/pr103227-1.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ipa/pr103227-2.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ipa/pr103227-3.c | 52 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/pr53787.f90 | 2 |
8 files changed, 216 insertions, 24 deletions
diff --git a/gcc/ipa-param-manipulation.c b/gcc/ipa-param-manipulation.c index cec1dba..479c20b 100644 --- a/gcc/ipa-param-manipulation.c +++ b/gcc/ipa-param-manipulation.c @@ -449,6 +449,39 @@ ipa_param_adjustments::get_updated_indices (vec<int> *new_indices) } } +/* If a parameter with original INDEX has survived intact, return its new + index. Otherwise return -1. In that case, if it has been split and there + is a new parameter representing a portion at unit OFFSET for which a value + of a TYPE can be substituted, store its new index into SPLIT_INDEX, + otherwise store -1 there. */ +int +ipa_param_adjustments::get_updated_index_or_split (int index, + unsigned unit_offset, + tree type, int *split_index) +{ + unsigned adj_len = vec_safe_length (m_adj_params); + for (unsigned i = 0; i < adj_len ; i++) + { + ipa_adjusted_param *apm = &(*m_adj_params)[i]; + if (apm->base_index != index) + continue; + if (apm->op == IPA_PARAM_OP_COPY) + return i; + if (apm->op == IPA_PARAM_OP_SPLIT + && apm->unit_offset == unit_offset) + { + if (useless_type_conversion_p (apm->type, type)) + *split_index = i; + else + *split_index = -1; + return -1; + } + } + + *split_index = -1; + return -1; +} + /* Return the original index for the given new parameter index. Return a negative number if not available. */ diff --git a/gcc/ipa-param-manipulation.h b/gcc/ipa-param-manipulation.h index 5adf8a2..d1dad9f 100644 --- a/gcc/ipa-param-manipulation.h +++ b/gcc/ipa-param-manipulation.h @@ -236,6 +236,13 @@ public: void get_surviving_params (vec<bool> *surviving_params); /* Fill a vector with new indices of surviving original parameters. */ void get_updated_indices (vec<int> *new_indices); + /* If a parameter with original INDEX has survived intact, return its new + index. Otherwise return -1. In that case, if it has been split and there + is a new parameter representing a portion at UNIT_OFFSET for which a value + of a TYPE can be substituted, store its new index into SPLIT_INDEX, + otherwise store -1 there. */ + int get_updated_index_or_split (int index, unsigned unit_offset, tree type, + int *split_index); /* Return the original index for the given new parameter index. Return a negative number if not available. */ int get_original_index (int newidx); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index e85df09..a297f50 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -5578,32 +5578,55 @@ ipcp_read_transformation_summaries (void) } /* Adjust the aggregate replacements in AGGVAL to reflect parameters skipped in - NODE. */ + NODE but also if any parameter was IPA-SRAed into a scalar go ahead with + substitution of the default_definitions of that new param with the + appropriate constant. -static void -adjust_agg_replacement_values (struct cgraph_node *node, - struct ipa_agg_replacement_value *aggval) + Return two bools. the first it true if at least one item in AGGVAL still + exists and function body walk should go ahead. The second is true if any + values were already substituted for scalarized parameters and update_cfg + shuld be run after replace_uses_by. */ + +static std::pair<bool, bool> +adjust_agg_replacement_values (cgraph_node *node, + ipa_agg_replacement_value *aggval, + const vec<ipa_param_descriptor, va_gc> + &descriptors) { struct ipa_agg_replacement_value *v; clone_info *cinfo = clone_info::get (node); - if (!cinfo || !cinfo->param_adjustments) - return; + return std::pair<bool, bool> (true, false); - auto_vec<int, 16> new_indices; - cinfo->param_adjustments->get_updated_indices (&new_indices); + bool anything_left = false; + bool done_replacement = false; for (v = aggval; v; v = v->next) { gcc_checking_assert (v->index >= 0); - if ((unsigned) v->index < new_indices.length ()) - v->index = new_indices[v->index]; - else - /* This can happen if we know about a constant passed by reference by - an argument which is never actually used for anything, let alone - loading that constant. */ - v->index = -1; + unsigned unit_offset = v->offset / BITS_PER_UNIT; + tree cst_type = TREE_TYPE (v->value); + int split_idx; + int new_idx + = cinfo->param_adjustments->get_updated_index_or_split (v->index, + unit_offset, + cst_type, + &split_idx); + v->index = new_idx; + if (new_idx >= 0) + anything_left = true; + else if (split_idx >= 0) + { + tree parm = ipa_get_param (descriptors, split_idx); + tree ddef = ssa_default_def (cfun, parm); + if (ddef) + { + replace_uses_by (ddef, v->value); + done_replacement = true; + } + } } + return std::pair<bool, bool> (anything_left, done_replacement); } /* Dominator walker driving the ipcp modification phase. */ @@ -5995,7 +6018,19 @@ ipcp_transform_function (struct cgraph_node *node) param_count = count_formal_params (node->decl); if (param_count == 0) return 0; - adjust_agg_replacement_values (node, aggval); + vec_safe_grow_cleared (descriptors, param_count, true); + ipa_populate_param_decls (node, *descriptors); + std::pair<bool, bool> rr + = adjust_agg_replacement_values (node, aggval, *descriptors); + int retval = rr.second ? TODO_cleanup_cfg : 0; + if (!rr.first) + { + vec_free (descriptors); + if (dump_file) + fprintf (dump_file, " All affected aggregate parameters were either " + "removed or converted into scalars, phase done.\n"); + return retval; + } if (dump_file) ipa_dump_agg_replacement_values (dump_file, aggval); @@ -6006,8 +6041,6 @@ ipcp_transform_function (struct cgraph_node *node) fbi.param_count = param_count; fbi.aa_walk_budget = opt_for_fn (node->decl, param_ipa_max_aa_steps); - vec_safe_grow_cleared (descriptors, param_count, true); - ipa_populate_param_decls (node, *descriptors); calculate_dominance_info (CDI_DOMINATORS); ipcp_modif_dom_walker walker (&fbi, descriptors, aggval, &something_changed); walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); @@ -6028,12 +6061,12 @@ ipcp_transform_function (struct cgraph_node *node) vec_free (descriptors); if (!something_changed) - return 0; + return retval; if (cfg_changed) delete_unreachable_blocks_update_callgraph (node, false); - return TODO_update_ssa_only_virtuals; + return retval | TODO_update_ssa_only_virtuals; } diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 1d0c115..ba49843 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -700,6 +700,17 @@ ipa_get_param_count (class ipa_node_params *info) return vec_safe_length (info->descriptors); } +/* Return the parameter declaration in DESCRIPTORS at index I and assert it is + indeed a PARM_DECL. */ + +static inline tree +ipa_get_param (const vec<ipa_param_descriptor, va_gc> &descriptors, int i) +{ + tree t = descriptors[i].decl_or_type; + gcc_checking_assert (TREE_CODE (t) == PARM_DECL); + return t; +} + /* Return the declaration of Ith formal parameter of the function corresponding to INFO. Note there is no setter function as this array is built just once using ipa_initialize_node_params. This function should not be called in @@ -709,9 +720,7 @@ static inline tree ipa_get_param (class ipa_node_params *info, int i) { gcc_checking_assert (info->descriptors); - tree t = (*info->descriptors)[i].decl_or_type; - gcc_checking_assert (TREE_CODE (t) == PARM_DECL); - return t; + return ipa_get_param (*info->descriptors, i); } /* Return the type of Ith formal parameter of the function corresponding diff --git a/gcc/testsuite/gcc.dg/ipa/pr103227-1.c b/gcc/testsuite/gcc.dg/ipa/pr103227-1.c new file mode 100644 index 0000000..0f56eb1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr103227-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized-slim" } */ + +struct S +{ + int a, b, c; +}; + +int ellide (int c); + +static void __attribute__ ((noinline)) +foo (struct S *p) +{ + int c = p->c; + if (c != 21) + ellide (c); +} + +void +entry (void) +{ + struct S s; + s.a = 1; + s.b = 64; + s.c = 21; + foo (&s); +} + +/* { dg-final { scan-tree-dump-not "ellide" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/ipa/pr103227-2.c b/gcc/testsuite/gcc.dg/ipa/pr103227-2.c new file mode 100644 index 0000000..e4f3c71 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr103227-2.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized-slim" } */ + +struct S +{ + int a, b, c; +}; + +int ellide (int c); + +static void __attribute__ ((noinline)) +foo (struct S s) +{ + int c = s.c; + if (c != 21) + ellide (c); +} + +void +entry (void) +{ + struct S s; + s.a = 1; + s.b = 64; + s.c = 21; + foo (s); +} + +/* { dg-final { scan-tree-dump-not "ellide" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/ipa/pr103227-3.c b/gcc/testsuite/gcc.dg/ipa/pr103227-3.c new file mode 100644 index 0000000..a48026d --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr103227-3.c @@ -0,0 +1,52 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fno-tree-fre -fno-tree-sra -fdump-tree-optimized-slim" } */ + +struct S +{ + int a, b, c; +}; + +volatile int z1; +int z2 = 44; + +void __attribute__((noipa)) +use_int (int c) +{ + z1 = c; +} + +static void __attribute__ ((noinline)) +bar (struct S s) +{ + use_int (s.c); +} + + +static void __attribute__ ((noinline)) +foo (struct S s) +{ + int c = s.c; + if (c != 21) + use_int (c); + + s.c = z2; + bar (s); + if (s.c != 44) + __builtin_abort (); +} + +int +main (void) +{ + struct S s; + s.a = 1; + s.b = 64; + s.c = 21; + foo (s); + return 0; +} + + + + +/* { dg-final { scan-tree-dump-not "ellide" "optimized" } } */ diff --git a/gcc/testsuite/gfortran.dg/pr53787.f90 b/gcc/testsuite/gfortran.dg/pr53787.f90 index f366a30..412bbc7 100644 --- a/gcc/testsuite/gfortran.dg/pr53787.f90 +++ b/gcc/testsuite/gfortran.dg/pr53787.f90 @@ -1,5 +1,5 @@ ! { dg-do compile } -! { dg-options "-O3 -fdump-ipa-cp-details -fno-inline -fwhole-program" } +! { dg-options "-O3 -fdump-ipa-cp-details -fno-ipa-sra -fno-inline -fwhole-program" } real x(10) n = 10 |