On Tue, 18 May 2021, Jakub Jelinek wrote:

> Hi!
> 
> As mentioned earlier, spaceship_replacement didn't optimize partial_ordering
> >= 0 comparisons, because the possible values are -1, 0, 1, 2 and the
> >= comparison is implemented as (res & 1) == res to choose the 0 and 1
> cases from that.  As we optimize that only with -ffinite-math-only, the
> 2 case is assumed not to happen and my earlier match.pd change optimizes
> (res & 1) == res into (res & ~1) == 0, so this patch pattern matches
> that case and handles it like res >= 0.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

> 2021-05-18  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR tree-optimization/94589
>       * tree-ssa-phiopt.c (spaceship_replacement): Pattern match
>       phi result used in (res & ~1) == 0 comparison as res >= 0 as
>       res == 2 would be UB with -ffinite-math-only.
> 
>       * g++.dg/opt/pr94589-2.C: Adjust scan-tree-dump count from 14 to 12.
> 
> --- gcc/tree-ssa-phiopt.c.jj  2021-05-06 14:05:03.254763364 +0200
> +++ gcc/tree-ssa-phiopt.c     2021-05-17 14:51:55.648356364 +0200
> @@ -1887,8 +1887,9 @@ spaceship_replacement (basic_block cond_
>                      edge e0, edge e1, gphi *phi,
>                      tree arg0, tree arg1)
>  {
> -  if (!INTEGRAL_TYPE_P (TREE_TYPE (PHI_RESULT (phi)))
> -      || TYPE_UNSIGNED (TREE_TYPE (PHI_RESULT (phi)))
> +  tree phires = PHI_RESULT (phi);
> +  if (!INTEGRAL_TYPE_P (TREE_TYPE (phires))
> +      || TYPE_UNSIGNED (TREE_TYPE (phires))
>        || !tree_fits_shwi_p (arg0)
>        || !tree_fits_shwi_p (arg1)
>        || !IN_RANGE (tree_to_shwi (arg0), -1, 2)
> @@ -1902,12 +1903,32 @@ spaceship_replacement (basic_block cond_
>  
>    use_operand_p use_p;
>    gimple *use_stmt;
> -  if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)))
> +  if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (phires))
>      return false;
> -  if (!single_imm_use (PHI_RESULT (phi), &use_p, &use_stmt))
> +  if (!single_imm_use (phires, &use_p, &use_stmt))
>      return false;
>    enum tree_code cmp;
>    tree lhs, rhs;
> +  gimple *orig_use_stmt = use_stmt;
> +  tree orig_use_lhs = NULL_TREE;
> +  int prec = TYPE_PRECISION (TREE_TYPE (phires));
> +  if (is_gimple_assign (use_stmt)
> +      && gimple_assign_rhs_code (use_stmt) == BIT_AND_EXPR
> +      && TREE_CODE (gimple_assign_rhs2 (use_stmt)) == INTEGER_CST
> +      && (wi::to_wide (gimple_assign_rhs2 (use_stmt))
> +       == wi::shifted_mask (1, prec - 1, false, prec)))
> +    {
> +      /* For partial_ordering result operator>= with unspec as second
> +      argument is (res & 1) == res, folded by match.pd into
> +      (res & ~1) == 0.  */
> +      orig_use_lhs = gimple_assign_lhs (use_stmt);
> +      if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig_use_lhs))
> +     return false;
> +      if (EDGE_COUNT (phi_bb->preds) != 4)
> +     return false;
> +      if (!single_imm_use (orig_use_lhs, &use_p, &use_stmt))
> +     return false;
> +    }
>    if (gimple_code (use_stmt) == GIMPLE_COND)
>      {
>        cmp = gimple_cond_code (use_stmt);
> @@ -1948,10 +1969,19 @@ spaceship_replacement (basic_block cond_
>      default:
>        return false;
>      }
> -  if (lhs != PHI_RESULT (phi)
> +  if (lhs != (orig_use_lhs ? orig_use_lhs : phires)
>        || !tree_fits_shwi_p (rhs)
>        || !IN_RANGE (tree_to_shwi (rhs), -1, 1))
>      return false;
> +  if (orig_use_lhs)
> +    {
> +      if ((cmp != EQ_EXPR && cmp != NE_EXPR) || !integer_zerop (rhs))
> +     return false;
> +      /* As for -ffast-math we assume the 2 return to be
> +      impossible, canonicalize (res & ~1) == 0 into
> +      res >= 0 and (res & ~1) != 0 as res < 0.  */
> +      cmp = cmp == EQ_EXPR ? GE_EXPR : LT_EXPR;
> +    }
>  
>    if (!empty_block_p (middle_bb))
>      return false;
> @@ -2092,7 +2122,7 @@ spaceship_replacement (basic_block cond_
>                               ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) == 0)
>      return false;
>  
> -  /* lhs1 one_cmp rhs1 results in PHI_RESULT (phi) of 1.  */
> +  /* lhs1 one_cmp rhs1 results in phires of 1.  */
>    enum tree_code one_cmp;
>    if ((cmp1 == LT_EXPR)
>        ^ (!integer_onep ((e1->flags & EDGE_TRUE_VALUE) ? arg1 : arg0)))
> @@ -2185,13 +2215,29 @@ spaceship_replacement (basic_block cond_
>        use_operand_p use_p;
>        imm_use_iterator iter;
>        bool has_debug_uses = false;
> -      FOR_EACH_IMM_USE_FAST (use_p, iter, PHI_RESULT (phi))
> +      FOR_EACH_IMM_USE_FAST (use_p, iter, phires)
>       {
>         gimple *use_stmt = USE_STMT (use_p);
> +       if (orig_use_lhs && use_stmt == orig_use_stmt)
> +         continue;
>         gcc_assert (is_gimple_debug (use_stmt));
>         has_debug_uses = true;
>         break;
>       }
> +      if (orig_use_lhs)
> +     {
> +       if (!has_debug_uses)
> +         FOR_EACH_IMM_USE_FAST (use_p, iter, orig_use_lhs)
> +           {
> +             gimple *use_stmt = USE_STMT (use_p);
> +             gcc_assert (is_gimple_debug (use_stmt));
> +             has_debug_uses = true;
> +           }
> +       gimple_stmt_iterator gsi = gsi_for_stmt (orig_use_stmt);
> +       tree zero = build_zero_cst (TREE_TYPE (orig_use_lhs));
> +       gimple_assign_set_rhs_with_ops (&gsi, INTEGER_CST, zero);
> +       update_stmt (orig_use_stmt);
> +     }
>  
>        if (has_debug_uses)
>       {
> @@ -2203,7 +2249,7 @@ spaceship_replacement (basic_block cond_
>            Ignore the value of 2, because if NaNs aren't expected,
>            all floating point numbers should be comparable.  */
>         gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
> -       tree type = TREE_TYPE (PHI_RESULT (phi));
> +       tree type = TREE_TYPE (phires);
>         tree temp1 = make_node (DEBUG_EXPR_DECL);
>         DECL_ARTIFICIAL (temp1) = 1;
>         TREE_TYPE (temp1) = type;
> @@ -2221,10 +2267,18 @@ spaceship_replacement (basic_block cond_
>         t = build3 (COND_EXPR, type, t, build_zero_cst (type), temp1);
>         g = gimple_build_debug_bind (temp2, t, phi);
>         gsi_insert_before (&gsi, g, GSI_SAME_STMT);
> -       replace_uses_by (PHI_RESULT (phi), temp2);
> +       replace_uses_by (phires, temp2);
> +       if (orig_use_lhs)
> +         replace_uses_by (orig_use_lhs, temp2);
>       }
>      }
>  
> +  if (orig_use_lhs)
> +    {
> +      gimple_stmt_iterator gsi = gsi_for_stmt (orig_use_stmt);
> +      gsi_remove (&gsi, true);
> +    }
> +
>    gimple_stmt_iterator psi = gsi_for_stmt (phi);
>    remove_phi_node (&psi, true);
>  
> --- gcc/testsuite/g++.dg/opt/pr94589-2.C.jj   2021-05-06 10:15:23.712751382 
> +0200
> +++ gcc/testsuite/g++.dg/opt/pr94589-2.C      2021-05-17 14:57:21.154800488 
> +0200
> @@ -1,8 +1,8 @@
>  // PR tree-optimization/94589
>  // { dg-do compile { target c++20 } }
>  // { dg-options "-O2 -g0 -ffast-math -fdump-tree-optimized" }
> -// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) 
> (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 14 "optimized" } }
> -// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
> 5\\.0" 14 "optimized" } }
> +// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) 
> (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 12 "optimized" } }
> +// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
> 5\\.0" 12 "optimized" } }
>  
>  #include <compare>
>  
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Reply via email to