Richard Biener <rguent...@suse.de> writes:
> I am testing the following patch to fix the qsort intransitiveness
> of dr_group_sort_cmp.  The patch removes the overly powerful
> operand_equal_p checks (handling commutativity )
> because those do not mix well with the sorting constraints.
>
> I am also testing a followup to address the missed equalities by
> canonicalization -- the interesting trees happen to be all built
> by split_constant_offset where we can do some elaborate canonicalization
> in linear complexity (as opposed to operand_equal_p's exponential
> handling or trying to handle it in data_ref_compare_tree where it would
> be done at least multiple times during qsort invocation).
>
> Bootstrapped on x86_64-unknown-linux-gnu, testing still in progress
> (so is a quick SPEC 2k6 build where the issue showed up in multiple
> places).
>
> Richard.
>
> 2017-10-06  Richard Biener  <rguent...@suse.de>
>
>       PR tree-optimization/82397
>       * tree-vect-data-refs.c (dr_group_sort_cmp): Do not use
>       operand_equal_p but rely on data_ref_compare_tree for detecting
>       equalities.
>       (vect_analyze_data_ref_accesses): Use data_ref_compare_tree
>       to match up with dr_group_sort_cmp.
>
>       * gfortran.dg/pr82397.f: New testcase.
>
> Index: gcc/tree-vect-data-refs.c
> ===================================================================
> --- gcc/tree-vect-data-refs.c (revision 253475)
> +++ gcc/tree-vect-data-refs.c (working copy)
> @@ -2727,43 +2727,30 @@ dr_group_sort_cmp (const void *dra_, con
>      return loopa->num < loopb->num ? -1 : 1;
>  
>    /* Ordering of DRs according to base.  */
> -  if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0))
> -    {
> -      cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
> -                                DR_BASE_ADDRESS (drb));
> -      if (cmp != 0)
> -        return cmp;
> -    }
> +  cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
> +                            DR_BASE_ADDRESS (drb));
> +  if (cmp != 0)
> +    return cmp;
>  
>    /* And according to DR_OFFSET.  */
> -  if (!dr_equal_offsets_p (dra, drb))
> -    {
> -      cmp = data_ref_compare_tree (DR_OFFSET (dra), DR_OFFSET (drb));
> -      if (cmp != 0)
> -        return cmp;
> -    }
> +  cmp = data_ref_compare_tree (DR_OFFSET (dra), DR_OFFSET (drb));
> +  if (cmp != 0)
> +    return cmp;
>  
>    /* Put reads before writes.  */
>    if (DR_IS_READ (dra) != DR_IS_READ (drb))
>      return DR_IS_READ (dra) ? -1 : 1;
>  
>    /* Then sort after access size.  */
> -  if (!operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))),
> -                     TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))), 0))
> -    {
> -      cmp = data_ref_compare_tree (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))),
> -                                TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
> -      if (cmp != 0)
> -        return cmp;
> -    }
> +  cmp = data_ref_compare_tree (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))),
> +                            TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
> +  if (cmp != 0)
> +    return cmp;
>  
>    /* And after step.  */
> -  if (!operand_equal_p (DR_STEP (dra), DR_STEP (drb), 0))
> -    {
> -      cmp = data_ref_compare_tree (DR_STEP (dra), DR_STEP (drb));
> -      if (cmp != 0)
> -        return cmp;
> -    }
> +  cmp = data_ref_compare_tree (DR_STEP (dra), DR_STEP (drb));
> +  if (cmp != 0)
> +    return cmp;
>  
>    /* Then sort after DR_INIT.  In case of identical DRs sort after stmt UID. 
>  */
>    cmp = tree_int_cst_compare (DR_INIT (dra), DR_INIT (drb));
> @@ -2835,9 +2822,9 @@ vect_analyze_data_ref_accesses (vec_info
>            and they are both either store or load (not load and store,
>            not masked loads or stores).  */
>         if (DR_IS_READ (dra) != DR_IS_READ (drb)
> -           || !operand_equal_p (DR_BASE_ADDRESS (dra),
> -                                DR_BASE_ADDRESS (drb), 0)
> -           || !dr_equal_offsets_p (dra, drb)
> +           || data_ref_compare_tree (DR_BASE_ADDRESS (dra),
> +                                     DR_BASE_ADDRESS (drb)) != 0
> +           || data_ref_compare_tree (DR_OFFSET (dra), DR_OFFSET (drb)) != 0
>             || !gimple_assign_single_p (DR_STMT (dra))
>             || !gimple_assign_single_p (DR_STMT (drb)))
>           break;
> @@ -2851,7 +2838,7 @@ vect_analyze_data_ref_accesses (vec_info
>           break;
>  
>         /* Check that the data-refs have the same step.  */
> -       if (!operand_equal_p (DR_STEP (dra), DR_STEP (drb), 0))
> +       if (data_ref_compare_tree (DR_STEP (dra), DR_STEP (drb)) != 0)
>           break;
>  
>         /* Do not place the same access in the interleaving chain twice.  */

I don't think data_ref_compare_tree is strong enough to replace
operand_equal_p when equality is needed for correctness.
A lot of data_ref_compare_tree just uses hash values and can
return 0 for things that aren't actually equal.  (Although maybe
that's the bug...)

Thanks,
Richard

Reply via email to