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

Reply via email to