aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2012-11-21 18:04:45 +0100
committerMartin Jambor <jamborm@gcc.gnu.org>2012-11-21 18:04:45 +0100
commit7e9f2b6e35b47373730c340471afa1734e197b60 (patch)
tree9e8061f624d67b7b06a839882525f10a7e5687b8 /gcc
parent3358fd40546fa1c360f625ca9e7a911ac3ba80cd (diff)
downloadgcc-7e9f2b6e35b47373730c340471afa1734e197b60.zip
gcc-7e9f2b6e35b47373730c340471afa1734e197b60.tar.gz
gcc-7e9f2b6e35b47373730c340471afa1734e197b60.tar.bz2
re PR tree-optimization/55260 (ICE: in ipa_get_parm_lattices, at ipa-cp.c:263 with -O2 -fno-inline -fipa-cp-clone)
2012-11-21 Martin Jambor <mjambor@suse.cz> PR tree-optimization/55260 * ipa-cp.c (intersect_aggregates_with_edge): New function. (find_aggregate_values_for_callers_subset): Part moved to the function above. Call it. (cgraph_edge_brings_all_agg_vals_for_node): Reimplemented using intersect_aggregates_with_edge. * testsuite/g++.dg/torture/pr55260-2.C: New test. From-SVN: r193700
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/ipa-cp.c297
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr55260-2.C16
4 files changed, 200 insertions, 127 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cdce51e..58f69d1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2012-11-21 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/55260
+ * ipa-cp.c (intersect_aggregates_with_edge): New function.
+ (find_aggregate_values_for_callers_subset): Part moved to the function
+ above. Call it.
+ (cgraph_edge_brings_all_agg_vals_for_node): Reimplemented using
+ intersect_aggregates_with_edge.
+
2012-11-21 Matthias Klose <doko@ubuntu.com>
* config/s390/t-linux64: Add multiarch names in MULTILIB_OSDIRNAMES.
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index c22f63b..16cf990 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -2850,6 +2850,127 @@ intersect_with_agg_replacements (struct cgraph_node *node, int index,
}
}
+/* Intersect values in INTER with aggregate values that come along edge CS to
+ parameter number INDEX and return it. If INTER does not actually exist yet,
+ copy all incoming values to it. If we determine we ended up with no values
+ whatsoever, return a released vector. */
+
+static vec<ipa_agg_jf_item_t>
+intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
+ vec<ipa_agg_jf_item_t> inter)
+{
+ struct ipa_jump_func *jfunc;
+ jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
+ if (jfunc->type == IPA_JF_PASS_THROUGH
+ && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
+ {
+ struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
+ int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
+
+ if (caller_info->ipcp_orig_node)
+ {
+ struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
+ struct ipcp_param_lattices *orig_plats;
+ orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
+ src_idx);
+ if (agg_pass_through_permissible_p (orig_plats, jfunc))
+ {
+ if (!inter.exists ())
+ inter = agg_replacements_to_vector (cs->caller, 0);
+ else
+ intersect_with_agg_replacements (cs->caller, src_idx,
+ &inter, 0);
+ }
+ }
+ else
+ {
+ struct ipcp_param_lattices *src_plats;
+ src_plats = ipa_get_parm_lattices (caller_info, src_idx);
+ if (agg_pass_through_permissible_p (src_plats, jfunc))
+ {
+ /* Currently we do not produce clobber aggregate jump
+ functions, adjust when we do. */
+ gcc_checking_assert (!jfunc->agg.items);
+ if (!inter.exists ())
+ inter = copy_plats_to_inter (src_plats, 0);
+ else
+ intersect_with_plats (src_plats, &inter, 0);
+ }
+ }
+ }
+ else if (jfunc->type == IPA_JF_ANCESTOR
+ && ipa_get_jf_ancestor_agg_preserved (jfunc))
+ {
+ struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
+ int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
+ struct ipcp_param_lattices *src_plats;
+ HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
+
+ if (caller_info->ipcp_orig_node)
+ {
+ if (!inter.exists ())
+ inter = agg_replacements_to_vector (cs->caller, delta);
+ else
+ intersect_with_agg_replacements (cs->caller, index, &inter,
+ delta);
+ }
+ else
+ {
+ src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
+ /* Currently we do not produce clobber aggregate jump
+ functions, adjust when we do. */
+ gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
+ if (!inter.exists ())
+ inter = copy_plats_to_inter (src_plats, delta);
+ else
+ intersect_with_plats (src_plats, &inter, delta);
+ }
+ }
+ else if (jfunc->agg.items)
+ {
+ struct ipa_agg_jf_item *item;
+ int k;
+
+ if (!inter.exists ())
+ for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
+ inter.safe_push ((*jfunc->agg.items)[i]);
+ else
+ FOR_EACH_VEC_ELT (inter, k, item)
+ {
+ int l = 0;
+ bool found = false;;
+
+ if (!item->value)
+ continue;
+
+ while ((unsigned) l < jfunc->agg.items->length ())
+ {
+ struct ipa_agg_jf_item *ti;
+ ti = &(*jfunc->agg.items)[l];
+ if (ti->offset > item->offset)
+ break;
+ if (ti->offset == item->offset)
+ {
+ gcc_checking_assert (ti->value);
+ if (values_equal_for_ipcp_p (item->value,
+ ti->value))
+ found = true;
+ break;
+ }
+ l++;
+ }
+ if (!found)
+ item->value = NULL;
+ }
+ }
+ else
+ {
+ inter.release();
+ return vec<ipa_agg_jf_item_t>();
+ }
+ return inter;
+}
+
/* Look at edges in CALLERS and collect all known aggregate values that arrive
from all of them. */
@@ -2883,111 +3004,7 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
FOR_EACH_VEC_ELT (callers, j, cs)
{
- struct ipa_jump_func *jfunc;
- jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
- if (jfunc->type == IPA_JF_PASS_THROUGH
- && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
- {
- struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
- int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
-
- if (caller_info->ipcp_orig_node)
- {
- struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
- struct ipcp_param_lattices *orig_plats;
- orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
- src_idx);
- if (agg_pass_through_permissible_p (orig_plats, jfunc))
- {
- if (!inter.exists ())
- inter = agg_replacements_to_vector (cs->caller, 0);
- else
- intersect_with_agg_replacements (cs->caller, src_idx,
- &inter, 0);
- }
- }
- else
- {
- struct ipcp_param_lattices *src_plats;
- src_plats = ipa_get_parm_lattices (caller_info, src_idx);
- if (agg_pass_through_permissible_p (src_plats, jfunc))
- {
- /* Currently we do not produce clobber aggregate jump
- functions, adjust when we do. */
- gcc_checking_assert (!jfunc->agg.items);
- if (!inter.exists ())
- inter = copy_plats_to_inter (src_plats, 0);
- else
- intersect_with_plats (src_plats, &inter, 0);
- }
- }
- }
- else if (jfunc->type == IPA_JF_ANCESTOR
- && ipa_get_jf_ancestor_agg_preserved (jfunc))
- {
- struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
- int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
- struct ipcp_param_lattices *src_plats;
- HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
-
- if (caller_info->ipcp_orig_node)
- {
- if (!inter.exists ())
- inter = agg_replacements_to_vector (cs->caller, delta);
- else
- intersect_with_agg_replacements (cs->caller, i, &inter,
- delta);
- }
- else
- {
- src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
- /* Currently we do not produce clobber aggregate jump
- functions, adjust when we do. */
- gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
- if (!inter.exists ())
- inter = copy_plats_to_inter (src_plats, delta);
- else
- intersect_with_plats (src_plats, &inter, delta);
- }
- }
- else if (jfunc->agg.items)
- {
- int k;
-
- if (!inter.exists ())
- for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
- inter.safe_push ((*jfunc->agg.items)[i]);
- else
- FOR_EACH_VEC_ELT (inter, k, item)
- {
- int l = 0;
- bool found = false;;
-
- if (!item->value)
- continue;
-
- while ((unsigned) l < jfunc->agg.items->length ())
- {
- struct ipa_agg_jf_item *ti;
- ti = &(*jfunc->agg.items)[l];
- if (ti->offset > item->offset)
- break;
- if (ti->offset == item->offset)
- {
- gcc_checking_assert (ti->value);
- if (values_equal_for_ipcp_p (item->value,
- ti->value))
- found = true;
- break;
- }
- l++;
- }
- if (!found)
- item->value = NULL;
- }
- }
- else
- goto next_param;
+ inter = intersect_aggregates_with_edge (cs, i, inter);
if (!inter.exists ())
goto next_param;
@@ -3079,37 +3096,63 @@ static bool
cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
struct cgraph_node *node)
{
- struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
+ struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
struct ipa_agg_replacement_value *aggval;
+ int i, ec, count;
aggval = ipa_get_agg_replacements_for_node (node);
- while (aggval)
+ if (!aggval)
+ return true;
+
+ count = ipa_get_param_count (IPA_NODE_REF (node));
+ ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
+ if (ec < count)
+ for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
+ if (aggval->index >= ec)
+ return false;
+
+ if (orig_caller_info->ipcp_orig_node)
+ orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
+
+ for (i = 0; i < count; i++)
{
- bool found = false;
+ static vec<ipa_agg_jf_item_t> values = vec<ipa_agg_jf_item_t>();
struct ipcp_param_lattices *plats;
- plats = ipa_get_parm_lattices (caller_info, aggval->index);
- if (plats->aggs_bottom || plats->aggs_contain_variable)
+ bool interesting = false;
+ for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
+ if (aggval->index == i)
+ {
+ interesting = true;
+ break;
+ }
+ if (!interesting)
+ continue;
+
+ plats = ipa_get_parm_lattices (orig_caller_info, aggval->index);
+ if (plats->aggs_bottom)
return false;
- for (struct ipcp_agg_lattice *aglat = plats->aggs;
- aglat;
- aglat = aglat->next)
- if (aglat->offset == aggval->offset)
- {
- if (ipa_lat_is_single_const (aglat)
- && values_equal_for_ipcp_p (aggval->value,
- aglat->values->value))
- {
- found = true;
- break;
- }
- else
- return false;
- }
- if (!found)
+ values = intersect_aggregates_with_edge (cs, i, values);
+ if (!values.exists())
return false;
- aggval = aggval->next;
+ for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
+ if (aggval->index == i)
+ {
+ struct ipa_agg_jf_item *item;
+ int j;
+ bool found = false;
+ FOR_EACH_VEC_ELT (values, j, item)
+ if (item->value
+ && item->offset == av->offset
+ && values_equal_for_ipcp_p (item->value, av->value))
+ found = true;
+ if (!found)
+ {
+ values.release();
+ return false;
+ }
+ }
}
return true;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 965c7e1..5def603 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2012-11-21 Martin Jambor <mjambor@suse.cz>
+ PR tree-optimization/55260
+ * g++.dg/torture/pr55260-2.C: New test.
+
+2012-11-21 Martin Jambor <mjambor@suse.cz>
+
* gcc.dg/torture/pr55238.c: Remove hidden attribute.
2012-11-21 Bin Cheng <bin.cheng@arm.com>
diff --git a/gcc/testsuite/g++.dg/torture/pr55260-2.C b/gcc/testsuite/g++.dg/torture/pr55260-2.C
new file mode 100644
index 0000000..43ed1e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr55260-2.C
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-add-options bind_pic_locally } */
+
+struct B
+{
+ virtual void test_suite_finish ();
+};
+void
+fn1 (B & p2)
+{
+ fn1 (p2);
+ B & a = p2;
+ a.test_suite_finish ();
+ B b;
+ fn1 (b);
+}