On Wed, Aug 27, 2025 at 6:58 PM Jakub Jelinek <ja...@redhat.com> wrote:

> On Wed, Aug 27, 2025 at 03:18:55PM +0200, Tomasz Kamiński wrote:
> > For any minimum value of a signed type, its negation (with wraparound)
> results
> > in the same value, behaving like zero. Representing the unordered result
> with
> > this minimum value, along with 0 for equal, 1 for greater, and -1 for
> less
> > in partial_ordering, allows its value to be reversed using unary
> negation.
> >
> > The operator<=(partial_order, 0) now checks if the reversed value is
> positive.
> > This works correctly because the unordered value remains unchanged and
> thus
> > negative.
> >
> > libstdc++-v3/ChangeLog:
> >
> >       * libsupc++/compare (_Ncmp::_Unordered): Rename and change the
> value
> >       to minimum value of signed char.
> >       (_Ncomp::unordered): Renamed from _Unordered, the name is reserved
> >       by partial_ordered::unordered.
> >       (partial_ordering::_M_reverse()): Define.
> >       (operator<=(partial_ordering, __cmp_cat::__unspec))
> >       (operator>=(__cmp_cat::__unspec, partial_ordering)): Implemented
> >       in terms of negated _M_value.
> >       (operator>=(partial_ordering, __cmp_cat::__unspec))
> >       (operator<=(__cmp_cat::__unspec, partial_ordering)): Directly
> >       compare _M_value, as unordered value is negative.
> >       (partial_ordering::unordered): Handle _Ncmp::unoredred rename.
> >       * python/libstdcxx/v6/printers.py: Add -128 as integer value
> >       for unordered, keeping 2 to preserve backward compatibility.
> >
> > Reviewed-by: Jonathan Wakely <jwak...@redhat.com>
> > Signed-off-by: Tomasz Kamiński <tkami...@redhat.com>
>
> This broke
> +FAIL: g++.dg/opt/pr94589-2.C  -std=gnu++20  scan-tree-dump-times
> optimized "i_[0-9]+\\\\(D\\\\) (?:<|<=|==|!=|>|>=) 5\\\\.0" 12
> +FAIL: g++.dg/opt/pr94589-2.C  -std=gnu++23  scan-tree-dump-times
> optimized "i_[0-9]+\\\\(D\\\\) (?:<|<=|==|!=|>|>=) 5\\\\.0" 12
> +FAIL: g++.dg/opt/pr94589-2.C  -std=gnu++26  scan-tree-dump-times
> optimized "i_[0-9]+\\\\(D\\\\) (?:<|<=|==|!=|>|>=) 5\\\\.0" 12
> on i686-linux, x86_64-linux or powerpc64le-linux, additionally
> FAIL: g++.dg/opt/pr94589-5.C  -std=gnu++20  scan-tree-dump-times optimized
> "[ij]_[0-9]+\\\\(D\\\\) (?:<|<=|>|>=) [ij]_[0-9]+\\\\(D\\\\)" 8
> FAIL: g++.dg/opt/pr94589-5.C  -std=gnu++20  scan-tree-dump-times optimized
> "i_[0-9]+\\\\(D\\\\) (?:<|<=|>|>=) 5\\\\.0" 8
> FAIL: g++.dg/opt/pr94589-5.C  -std=gnu++23  scan-tree-dump-times optimized
> "[ij]_[0-9]+\\\\(D\\\\) (?:<|<=|>|>=) [ij]_[0-9]+\\\\(D\\\\)" 8
> FAIL: g++.dg/opt/pr94589-5.C  -std=gnu++23  scan-tree-dump-times optimized
> "i_[0-9]+\\\\(D\\\\) (?:<|<=|>|>=) 5\\\\.0" 8
> FAIL: g++.dg/opt/pr94589-5.C  -std=gnu++26  scan-tree-dump-times optimized
> "[ij]_[0-9]+\\\\(D\\\\) (?:<|<=|>|>=) [ij]_[0-9]+\\\\(D\\\\)" 8
> FAIL: g++.dg/opt/pr94589-5.C  -std=gnu++26  scan-tree-dump-times optimized
> "i_[0-9]+\\\\(D\\\\) (?:<|<=|>|>=) 5\\\\.0" 8
> on powerpc64le-linux.
> Both tree-ssa-phiopt.cc (spaceship_replacement)
> and tree-ssa-math-opts.cc (optimize_spaceship)
> attempt to optimize some spaceship comparisons.
>
I have no experience with backend optimization, so I would need help to fix
the above.
>From my side I could only offer reverting the change, but I do not think we
should do so,
see below.


> Although I wrote both, my memory is weak, so just judging from function
> comments, the latter likely should deal with values -1, 0, 1 and X where
> X is some other value, so perhaps all we want to change there is
>       other than -1, 0, 1, for libstdc++ 2, for libc++ -127.  */
> to
>       other than -1, 0, 1, for libstdc++ -128, for libc++ -127.  */
> and adjust other comments that show the 2 value to show -128 instead.
> But tree-ssa-phiopt.cc clearly optimizes only the 2 case and has pattern
> recognition of the (x & ~1) == 0 and similar cases, which all will now be
> different for -128.  So, either spaceship_replacement needs to be rewritten
> to only handle -128 instead of 2, or depending on the source either -128 or
> 2.
>
I have selected the value -128, because it should not require any special
optimization
for spaceship replacement. The (x & ~1) == 0 are most likely product of
implementation
of one of the following functions:
     operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept
    { return __cmp_cat::type(__v._M_value & 1) == __v._M_value;

     operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept
     {
       if (__v._M_value & 1)
        return partial_ordering(__cmp_cat::_Ord(-__v._M_value));
      else
        return __v;
    }

However, with my patch I have replaced them with:
     operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept
     { return __v._M_value >= 0; } // unordered is now negative, so
positive check is simple

     operator<=(partial_ordering __v, __cmp_cat::__unspec) noexcept
    { return __v._M_reverse() >= 0;  } // negating -128 in 8bit produces
-128, so unordered remains negative
                                                          // so simple
positive check is fine

     operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept
     { return partial_ordering(__cmp_cat::_Ord(__v._M_reverse())); }
Where _M_reverse is simply doing static_cast<__cmp_cat::type>(-_M_value).
That means that we are now using just simple negation of 8 bit value (the
cast
is truncating it back from integer).

I have updated the reversing operator<=> here r16-3417-gb3038e1ace2a4e,
and now is doing the same operations as for strong and weak order.

Regards,
Tomasz




>
>         Jakub
>
>

Reply via email to