https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126564

--- Comment #5 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-16 branch has been updated by Jakub Jelinek
<[email protected]>:

https://gcc.gnu.org/g:24699eedf51ad307dd9463fa6c0a10222fdd56a2

commit r16-9503-g24699eedf51ad307dd9463fa6c0a10222fdd56a2
Author: Jakub Jelinek <[email protected]>
Date:   Tue Aug 4 10:35:19 2026 +0200

    phiopt: Fix up spaceship_replacement [PR126564]

    spaceship_replacement is for optimization of code like
        <bb 2> :  // cond3_bb
        if (a_3(D) == b_5(D))
          goto <bb 6>; [50.00%]
        else
          goto <bb 3>; [50.00%]

        <bb 3> [local count: 536870913]:  // cond2_bb
        if (a_3(D) < b_5(D))
          goto <bb 6>; [50.00%]
        else
          goto <bb 4>; [50.00%]

        <bb 4> [local count: 268435456]:  // cond_bb
        if (a_3(D) > b_5(D))
          goto <bb 6>; [50.00%]
        else
          goto <bb 5>; [50.00%]

        <bb 5> [local count: 134217728]:  // middle_bb

        <bb 6> [local count: 1073741824]:  // phi_bb
        # SR.27_4 = PHI <0(2), -1(3), 1(4), -128(5)>
        _2 = SR.27_4 > 0;
    to a single comparison (i.e. say (a <=> b) > 0 in C++) (it handles
    also just 2 comparisons instead of 3, but this bug is about the 3
    comparisons).
    In
          if (e1->flags & EDGE_TRUE_VALUE)
            {
              if (tree_to_shwi (arg0) != -128
                  || absu_hwi (tree_to_shwi (arg1)) != 1
                  || wi::to_widest (arg1) == wi::to_widest (arg2))
                return false;
            }
          else if (tree_to_shwi (arg1) != -128
                   || absu_hwi (tree_to_shwi (arg0)) != 1
                   || wi::to_widest (arg0) == wi::to_widest (arg2))
            return false;
    (where e1 is 4->6 edge above, arg0 is -128(5), arg1 is 1(4),
    arg2 is -1(3), cond2_phi_edge is 3->6 edge above) we deal with
    the different cases of whether the TRUE edge goes directly to
    phi_bb or through the empty middle_bb in between.
    Right above the above checks is
          if ((cond2_phi_edge->flags & EDGE_FALSE_VALUE)
              && HONOR_NANS (TREE_TYPE (lhs1)))
            return false;
    so for HONOR_NANS, cond2_phi_edge must be TRUE edge, otherwise
    it can be either.  The problematic check that causes the miscompilation
    of the testcase below wants to verify that the two comparisons
    (cmp1 being code of a_3(D) > b_5(D) and cmp2 a_3(D) < b_5(D)))
    are actually different, not just non-removed useless duplications
    (which is what causes miscompilation of the testcase below).
    The lhs2 == lhs1 xored case is whether the 2 comparisons are
    x cmp1 y vs. x cmp2 y or x cmp1 y vs. y cmp2 x (earlier code verifies
    the operands aren't different in other way with the exception of
    integral comparisons and < 4 vs. <= 3 etc.).
    For the HONOR_NANS case where we know cond2_phi_edge is TRUE
    the other xor operand is whether both cmp2 and cmp1 are </<= or
    >/>= (note, we can treat LT_EXPR and LE_EXPR the same because
    the optimization requires an equality comparison first, so
    LT_EXPR vs. LE_EXPR doesn't matter).  But for !HONOR_NANS I wrote
    a condition checking both the comparison codes and corresponding
    edge flags.  That is wrong because whether e1 is TRUE or FALSE
    edge has been accounted already in the if (e1->flags & EDGE_TRUE_VALUE)
    code above, all we care about is whether cond2_phi_edge is EDGE_TRUE_VALUE
    or EDGE_FALSE_VALUE or the comparison codes of the two comparisons
    (and order of their arguments).
    So, instead this xors lhs2 == lhs1 with whether cmp{1,2} are the same
    with whether cond2_phi_edge is EDGE_FALSE_VALUE.
    For HONOR_NANS there is no difference because the last term will be false.
    The pr94589*.c tests already cover quite a lot of different cases that
    should or shouldn't be matched.

    For 15 and older the testcase will need to be tweaked slightly (see the
PR),
    so that it tests miscompilation in those releases.

    2026-08-04  Jakub Jelinek  <[email protected]>

            PR tree-optimization/126564
            * tree-ssa-phiopt.cc (spaceship_replacement): Fix up condition
            when to punt because of redundant cmp1 with cmp2, xor in
            lhs1 == lhs2 with difference of cmp2 from cmp1 (ignoring
            LT_EXPR vs. LE_EXPR and GT_EXPR vs. GE_EXPR differences) and
            1 if cond2_phi_edge is EDGE_FALSE_VALUE.

            * gcc.dg/torture/pr126564.c: New test.

    Reviewed-by: Richard Biener <[email protected]>
    (cherry picked from commit 5e9087929abff340ff8b132da837372875c584aa)

Reply via email to