aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-cp.c
diff options
context:
space:
mode:
authorFeng Xue <fxue@os.amperecomputing.com>2019-12-19 02:54:40 +0000
committerFeng Xue <fxue@gcc.gnu.org>2019-12-19 02:54:40 +0000
commit951e27f58ca5c7f33124407079c383706e99c68d (patch)
treeb65a6e0da38ccfd243a0ba0325bae4961c4a4f5b /gcc/ipa-cp.c
parent1ed6330924d2b7f961bbf68d7e2617c4e9372c4f (diff)
downloadgcc-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.c99
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;