Hi, On Sun, Nov 16, 2014 at 12:56:45AM +0100, Jan Hubicka wrote: > Hi, > this patch enables propagation of speculative contextes I promised to fix > after Martin's > merge. There were few bugs that ended up disturbing testsuite:
Wonderful, thanks a lot. > > 1) ipa_polymorphic_call_context::combine_with did not handle very well case > where the incomming type is in construction and it's current type is > known. > This made us to drop the ball on one of devirt-*.C testcases > 2) ipa_get_indirect_edge_target_1 did not correctly apply the offset > adjustment > and type_preserved prior using the known context. This caused an ICE > while > building Firefox Opps, I was worried I would accidently remove something like that. > 4) I noticed that find_more_scalar_values_for_callers_subset seems to > contain a bug > when searching if all incomming edges do contribute a same constant to a > given parameter. The code seems to set the constant to NULL and then set > it > to non-NULL at first occurence. When it however hits two different > constants it > resets back to NULL and later it may get again non-NULL. I don't there was a bug. When it was reset back to NULL, there was the break statement that quit the loop? Your new condition (!first && !newval) will never trigger because in the second (or any later) iteration, either we had hit the break statement or set newval to a non-NULL value. (If you however still think the code was wrong, it should be also fixed on release branches.) > > Otherwise the patch just disable parts where speculation si cleared; it makes > equal_to > to work better and it also add meet operation that is used to compute context > of edges > that have multiple callers. I admit I did not expect the ipa-cp parts to be this small. > * ipa-polymorphic-call.c > (ipa_polymorphic_call_context::speculation_consistent_p): Constify. > (ipa_polymorphic_call_context::meet_speculation_with): New function. > (ipa_polymorphic_call_context::combine_with): Handle types in > construction > better. > (ipa_polymorphic_call_context::equal_to): Do not bother about useless > speculation. > (ipa_polymorphic_call_context::meet_with): New function. > * cgraph.h (class ipa_polymorphic_call_context): Add > meet_width, meet_speculation_with; constify speculation_consistent_p. > * ipa-cp.c (ipa_context_from_jfunc): Handle speculation; combine with > incomming > context. > (propagate_context_accross_jump_function): Likewise; be more cureful. > about set_contains_variable. > (ipa_get_indirect_edge_target_1): Fix handling of dynamic type changes. > (find_more_scalar_values_for_callers_subset): Fix. > (find_more_contexts_for_caller_subset): Perform meet operation. > Index: ipa-polymorphic-call.c > =================================================================== > --- ipa-polymorphic-call.c (revision 217609) > +++ ipa-polymorphic-call.c (working copy) > @@ -1727,7 +1727,7 @@ bool > ipa_polymorphic_call_context::speculation_consistent_p (tree spec_outer_type, > HOST_WIDE_INT > spec_offset, > bool > spec_maybe_derived_type, > - tree otr_type) > + tree otr_type) const > { > if (!flag_devirtualize_speculatively) > return false; > @@ -1873,6 +1873,102 @@ ipa_polymorphic_call_context::combine_sp > return false; > } > > +/* Make speculation less specific so > + NEW_OUTER_TYPE, NEW_OFFSET, NEW_MAYBE_DERIVED_TYPE is also included. > + If OTR_TYPE is set, assume the context is used with OTR_TYPE. */ > + It would be nice if the return value was documented too. > +bool > +ipa_polymorphic_call_context::meet_speculation_with > + (tree new_outer_type, HOST_WIDE_INT new_offset, bool > new_maybe_derived_type, > + tree otr_type) > +{ > + if (!new_outer_type && speculative_outer_type) > + { > + clear_speculation (); > + return true; > + } > + > + /* restrict_to_inner_class may eliminate wrong speculation making our job > + easeier. */ > + if (otr_type) > + restrict_to_inner_class (otr_type); > + > + if (!speculative_outer_type > + || !speculation_consistent_p (speculative_outer_type, > + speculative_offset, > + speculative_maybe_derived_type, > + otr_type)) > + return false; > + > + if (!speculation_consistent_p (new_outer_type, new_offset, > + new_maybe_derived_type, otr_type)) > + { > + clear_speculation (); > + return true; > + } > + > + else if (types_must_be_same_for_odr (speculative_outer_type, > + new_outer_type)) > + { > + if (speculative_offset != new_offset) > + { > + clear_speculation (); > + return true; > + } > + else > + { > + if (!speculative_maybe_derived_type && new_maybe_derived_type) > + { > + speculative_maybe_derived_type = true; > + return true; > + } > + else > + return false; > + } > + } > + /* See if one type contains the other as a field (not base). */ > + else if (contains_type_p (new_outer_type, new_offset - speculative_offset, > + speculative_outer_type, false, false)) > + return false; > + else if (contains_type_p (speculative_outer_type, > + speculative_offset - new_offset, > + new_outer_type, false, false)) > + { > + speculative_outer_type = new_outer_type; > + speculative_offset = new_offset; > + speculative_maybe_derived_type = new_maybe_derived_type; > + return true; > + } > + /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */ > + else if (contains_type_p (new_outer_type, > + new_offset - speculative_offset, > + speculative_outer_type, false, true)) > + { > + if (!speculative_maybe_derived_type) > + { > + speculative_maybe_derived_type = true; > + return true; > + } > + return false; > + } > + /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */ > + else if (contains_type_p (speculative_outer_type, > + speculative_offset - new_offset, new_outer_type, > false, true)) > + { > + speculative_outer_type = new_outer_type; > + speculative_offset = new_offset; > + speculative_maybe_derived_type = true; > + return true; > + } > + else > + { > + if (dump_file && (dump_flags & TDF_DETAILS)) > + fprintf (dump_file, "Giving up on speculative meet\n"); > + clear_speculation (); > + return true; > + } > +} > + > /* Assume that both THIS and a given context is valid and strenghten THIS > if possible. Return true if any strenghtening was made. > If actual type the context is being used in is known, OTR_TYPE should be > @@ -2160,19 +2266,220 @@ ipa_polymorphic_call_context::equal_to > else if (x.outer_type) > return false; > > - if (speculative_outer_type) > + > + if (speculative_outer_type > + && speculation_consistent_p (speculative_outer_type, > speculative_offset, > + speculative_maybe_derived_type, NULL_TREE)) > { > - if (!x.speculative_outer_type > - || !types_odr_comparable (speculative_outer_type, > - x.speculative_outer_type) > + if (!x.speculative_outer_type) > + return false; > + > + if (!types_odr_comparable (speculative_outer_type, > + x.speculative_outer_type) > || !types_same_for_odr (speculative_outer_type, > - x.speculative_outer_type) > + x.speculative_outer_type) > || speculative_offset != x.speculative_offset > || speculative_maybe_derived_type != x.speculative_maybe_derived_type) > return false; > } > - else if (x.speculative_outer_type) > + else if (x.speculative_outer_type > + && x.speculation_consistent_p (x.speculative_outer_type, > + x.speculative_offset, > + x.speculative_maybe_derived_type, > + NULL)) > return false; Do we often leak speculative-inconsistent contexts outside of this file? > > return true; > } > + > +/* Modify context to be strictly less restrictive than CTX. */ Documenting the return value would be nice here too. Thanks, Martin