Commit 951e27f5 by Feng Xue Committed by Feng Xue

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
parent 1ed63309
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-18 David Malcolm <dmalcolm@redhat.com>
* common.opt (fdiagnostics-show-cwe): Add.
......@@ -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;
......
2019-12-19 Feng Xue <fxue@os.amperecomputing.com>
PR ipa/92794
* gcc.dg/ipa/92794.c: New test.
2019-12-18 David Malcolm <dmalcolm@redhat.com>
* gcc.dg/plugin/diagnostic-test-metadata.c: New test.
......
/* { dg-do compile } */
/* { dg-options "-O3 --param ipa-cp-eval-threshold=1" } */
int data[100];
int depth = 0;
int recur_fn (int *__restrict p)
{
int i = *p;
if (depth++ > 6)
return 10;
data[i] = i;
recur_fn (&i);
depth--;
return i;
}
int main ()
{
int i = 1;
recur_fn (&i);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment