On October 3, 2017 1:55:35 PM GMT+02:00, Jakub Jelinek <ja...@redhat.com> wrote:
>On Tue, Oct 03, 2017 at 01:24:32PM +0300, Alexander Monakov wrote:
>> On Tue, 3 Oct 2017, Jakub Jelinek wrote:
>> > The qsort cmp transitivity checks may fail with the
>sort_by_operand_rank
>> > comparator, because if one of the operands has stmt_to_insert and
>the
>> > other doesn't (but likely also if one SSA_NAME is (D) and the other
>is not),
>> > we fallthrough into SSA_NAME_VERSION comparison, but if both aren't
>(D) and
>> > both don't have stmt_to_insert, we use different comparison rules.
>> 
>> When looking at the code I've noticed another issue, so the fix seems
>> incomplete (but I don't know if the other problem can/should be fixed
>> independently), see below:
>> 
>> 
>> > --- gcc/tree-ssa-reassoc.c.jj      2017-10-02 17:33:14.270282226 +0200
>> > +++ gcc/tree-ssa-reassoc.c 2017-10-02 18:18:07.328611132 +0200
>> > @@ -514,36 +514,37 @@ sort_by_operand_rank (const void *pa, co
>> >        && TREE_CODE (oea->op) == SSA_NAME
>> >        && TREE_CODE (oeb->op) == SSA_NAME)
>> >      {
>> 
>> The containing if statement condition reads:
>> 
>>   if (oeb->rank == oea->rank
>>       && TREE_CODE (oea->op) == SSA_NAME
>>       && TREE_CODE (oeb->op) == SSA_NAME)
>> 
>> so as far as I can tell it's possible to have items A, B, C such that
>> all have same rank, A and C correspond to SSA_NAMEs and compare C <
>A,
>> but B does not, so comparisons of A or C against B fall down to 
>> 
>>     return oeb->id > oea->id ? 1 : -1;
>> 
>> and ultimately result in A < B < C < A.
>
>I think it is likely only hypothetical, because get_rank for
>non-SSA_NAME
>should be 0 and thus handled earlier (for SSA_NAME I think rank of 0 is
>still possible).
>
>That said, this untested patch reshuffles stuff a little bit, ok for
>trunk
>if it passes testing?

OK. 

Richard. 

>2017-10-03  Jakub Jelinek  <ja...@redhat.com>
>
>       PR tree-optimization/82381
>       * tree-ssa-reassoc.c (sort_by_operand_rank): Check for different
>       oeN->rank first.  Return 1 or -1 if one op is SSA_NAME and the other
>       is not.
>
>--- gcc/tree-ssa-reassoc.c.jj  2017-10-03 13:24:00.000000000 +0200
>+++ gcc/tree-ssa-reassoc.c     2017-10-03 13:41:23.098183270 +0200
>@@ -495,10 +495,13 @@ sort_by_operand_rank (const void *pa, co
>   const operand_entry *oea = *(const operand_entry *const *)pa;
>   const operand_entry *oeb = *(const operand_entry *const *)pb;
> 
>+  if (oeb->rank != oea->rank)
>+    return oeb->rank > oea->rank ? 1 : -1;
>+
>   /* It's nicer for optimize_expression if constants that are likely
>-     to fold when added/multiplied//whatever are put next to each
>+     to fold when added/multiplied/whatever are put next to each
>      other.  Since all constants have rank 0, order them by type.  */
>-  if (oeb->rank == 0 && oea->rank == 0)
>+  if (oea->rank == 0)
>     {
>       if (constant_type (oeb->op) != constant_type (oea->op))
>       return constant_type (oeb->op) - constant_type (oea->op);
>@@ -508,51 +511,50 @@ sort_by_operand_rank (const void *pa, co
>       return oeb->id > oea->id ? 1 : -1;
>     }
> 
>+  if (TREE_CODE (oea->op) != SSA_NAME)
>+    {
>+      if (TREE_CODE (oeb->op) != SSA_NAME)
>+      return oeb->id > oea->id ? 1 : -1;
>+      else
>+      return 1;
>+    }
>+  else if (TREE_CODE (oeb->op) != SSA_NAME)
>+    return -1;
>+
>   /* Lastly, make sure the versions that are the same go next to each
>      other.  */
>-  if (oeb->rank == oea->rank
>-      && TREE_CODE (oea->op) == SSA_NAME
>-      && TREE_CODE (oeb->op) == SSA_NAME)
>+  if (SSA_NAME_VERSION (oeb->op) != SSA_NAME_VERSION (oea->op))
>     {
>-      if (SSA_NAME_VERSION (oeb->op) != SSA_NAME_VERSION (oea->op))
>+      /* As SSA_NAME_VERSION is assigned pretty randomly, because we
>reuse
>+       versions of removed SSA_NAMEs, so if possible, prefer to sort
>+       based on basic block and gimple_uid of the SSA_NAME_DEF_STMT.
>+       See PR60418.  */
>+      gimple *stmta = SSA_NAME_DEF_STMT (oea->op);
>+      gimple *stmtb = SSA_NAME_DEF_STMT (oeb->op);
>+      basic_block bba = gimple_bb (stmta);
>+      basic_block bbb = gimple_bb (stmtb);
>+      if (bbb != bba)
>       {
>-        /* As SSA_NAME_VERSION is assigned pretty randomly, because we
>reuse
>-           versions of removed SSA_NAMEs, so if possible, prefer to sort
>-           based on basic block and gimple_uid of the SSA_NAME_DEF_STMT.
>-           See PR60418.  */
>-        gimple *stmta = SSA_NAME_DEF_STMT (oea->op);
>-        gimple *stmtb = SSA_NAME_DEF_STMT (oeb->op);
>-        basic_block bba = gimple_bb (stmta);
>-        basic_block bbb = gimple_bb (stmtb);
>-        if (bbb != bba)
>-          {
>-            /* One of the SSA_NAMEs can be defined in oeN->stmt_to_insert
>-               but the other might not.  */
>-            if (!bba)
>-              return 1;
>-            if (!bbb)
>-              return -1;
>-            /* If neither is, compare bb_rank.  */
>-            if (bb_rank[bbb->index] != bb_rank[bba->index])
>-              return bb_rank[bbb->index] - bb_rank[bba->index];
>-          }
>-
>-        bool da = reassoc_stmt_dominates_stmt_p (stmta, stmtb);
>-        bool db = reassoc_stmt_dominates_stmt_p (stmtb, stmta);
>-        if (da != db)
>-          return da ? 1 : -1;
>-
>-        return (SSA_NAME_VERSION (oeb->op) > SSA_NAME_VERSION (oea->op)
>-                ? 1 : -1);
>+        /* One of the SSA_NAMEs can be defined in oeN->stmt_to_insert
>+           but the other might not.  */
>+        if (!bba)
>+          return 1;
>+        if (!bbb)
>+          return -1;
>+        /* If neither is, compare bb_rank.  */
>+        if (bb_rank[bbb->index] != bb_rank[bba->index])
>+          return bb_rank[bbb->index] - bb_rank[bba->index];
>       }
>-      else
>-      return oeb->id > oea->id ? 1 : -1;
>+
>+      bool da = reassoc_stmt_dominates_stmt_p (stmta, stmtb);
>+      bool db = reassoc_stmt_dominates_stmt_p (stmtb, stmta);
>+      if (da != db)
>+      return da ? 1 : -1;
>+
>+      return SSA_NAME_VERSION (oeb->op) > SSA_NAME_VERSION (oea->op) ?
>1 : -1;
>     }
> 
>-  if (oeb->rank != oea->rank)
>-    return oeb->rank > oea->rank ? 1 : -1;
>-  else
>-    return oeb->id > oea->id ? 1 : -1;
>+  return oeb->id > oea->id ? 1 : -1;
> }
> 
> /* Add an operand entry to *OPS for the tree operand OP.  */
>
>
>       Jakub

Reply via email to