diff options
author | Feng Xue <fxue@os.amperecomputing.com> | 2019-12-19 02:54:40 +0000 |
---|---|---|
committer | Feng Xue <fxue@gcc.gnu.org> | 2019-12-19 02:54:40 +0000 |
commit | 951e27f58ca5c7f33124407079c383706e99c68d (patch) | |
tree | b65a6e0da38ccfd243a0ba0325bae4961c4a4f5b /gcc/ipa-cp.c | |
parent | 1ed6330924d2b7f961bbf68d7e2617c4e9372c4f (diff) | |
download | gcc-951e27f58ca5c7f33124407079c383706e99c68d.zip gcc-951e27f58ca5c7f33124407079c383706e99c68d.tar.gz gcc-951e27f58ca5c7f33124407079c383706e99c68d.tar.bz2 |
Handle aggregate pass-through for self-recursive call (PR ipa/92794)
2019-12-19 Feng Xue <fxue@os.amperecomputing.com>
PR ipa/92794
* ipa-cp.c (self_recursive_agg_pass_through_p): New function.
(intersect_with_plats): Use error_mark_node as place holder
when aggregate jump function is simple pass-through for
self-recursive call.
(intersect_with_agg_replacements): Likewise.
(intersect_aggregates_with_edge): Likewise.
(find_aggregate_values_for_callers_subset): Likewise.
2019-12-19 Feng Xue <fxue@os.amperecomputing.com>
PR ipa/92794
* gcc.dg/ipa/92794.c: New test.
From-SVN: r279561
Diffstat (limited to 'gcc/ipa-cp.c')
-rw-r--r-- | gcc/ipa-cp.c | 99 |
1 files changed, 83 insertions, 16 deletions
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 243b064..126d154 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -4564,6 +4564,25 @@ self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i) return false; } +/* Return true, if JFUNC, which describes a part of an aggregate represented + or pointed to by the i-th parameter of call CS, is a simple no-operation + pass-through function to itself. */ + +static bool +self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc, + int i) +{ + enum availability availability; + if (cs->caller == cs->callee->function_symbol (&availability) + && availability > AVAIL_INTERPOSABLE + && jfunc->jftype == IPA_JF_LOAD_AGG + && jfunc->offset == jfunc->value.load_agg.offset + && jfunc->value.pass_through.operation == NOP_EXPR + && jfunc->value.pass_through.formal_id == i) + return true; + return false; +} + /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in KNOWN_CSTS with constants that are also known for all of the CALLERS. */ @@ -4756,10 +4775,19 @@ intersect_with_plats (class ipcp_param_lattices *plats, if (aglat->offset - offset == item->offset) { gcc_checking_assert (item->value); - if (aglat->is_single_const () - && values_equal_for_ipcp_p (item->value, - aglat->values->value)) - found = true; + if (aglat->is_single_const ()) + { + tree value = aglat->values->value; + + if (values_equal_for_ipcp_p (item->value, value)) + found = true; + else if (item->value == error_mark_node) + { + /* Replace unknown place holder value with real one. */ + item->value = value; + found = true; + } + } break; } aglat = aglat->next; @@ -4827,6 +4855,12 @@ intersect_with_agg_replacements (struct cgraph_node *node, int index, { if (values_equal_for_ipcp_p (item->value, av->value)) found = true; + else if (item->value == error_mark_node) + { + /* Replace place holder value with real one. */ + item->value = av->value; + found = true; + } break; } } @@ -4931,17 +4965,31 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, for (unsigned i = 0; i < jfunc->agg.items->length (); i++) { struct ipa_agg_jf_item *agg_item = &(*jfunc->agg.items)[i]; - tree value = ipa_agg_value_from_node (caller_info, cs->caller, - agg_item); - if (value) + struct ipa_agg_value agg_value; + + if (self_recursive_agg_pass_through_p (cs, agg_item, index)) { - struct ipa_agg_value agg_value; + /* For a self-recursive call, if aggregate jump function is a + simple pass-through, the exact value that it stands for is + not known at this point, which must comes from other call + sites. But we still need to add a place holder in value + sets to indicate it, here we use error_mark_node to + represent the special unknown value, which will be replaced + with real one during later intersecting operations. */ + agg_value.value = error_mark_node; + } + else + { + tree value = ipa_agg_value_from_node (caller_info, cs->caller, + agg_item); + if (!value) + continue; - agg_value.offset = agg_item->offset; agg_value.value = value; - - inter.safe_push (agg_value); } + + agg_value.offset = agg_item->offset; + inter.safe_push (agg_value); } else FOR_EACH_VEC_ELT (inter, k, item) @@ -4960,11 +5008,27 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, break; if (ti->offset == item->offset) { - tree value = ipa_agg_value_from_node (caller_info, - cs->caller, ti); - if (value - && values_equal_for_ipcp_p (item->value, value)) - found = true; + tree value; + + if (self_recursive_agg_pass_through_p (cs, ti, index)) + { + /* A simple aggregate pass-through in self-recursive + call should lead to same value. */ + found = true; + } + else if ((value = ipa_agg_value_from_node (caller_info, + cs->caller, ti))) + { + if (values_equal_for_ipcp_p (item->value, value)) + found = true; + else if (item->value == error_mark_node) + { + /* Replace unknown place holder value with real + one. */ + item->value = value; + found = true; + } + } break; } l++; @@ -5040,6 +5104,9 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node, if (!item->value) continue; + /* All values must be real values, not unknown place holders. */ + gcc_assert (item->value != error_mark_node); + v = ggc_alloc<ipa_agg_replacement_value> (); v->index = i; v->offset = item->offset; |