public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug middle-end/85811] Invalid optimization with fmax, fabs and nan
       [not found] <bug-85811-4@http.gcc.gnu.org/bugzilla/>
@ 2020-11-18 22:10 ` cvs-commit at gcc dot gnu.org
  2020-12-02  5:32 ` asolokha at gmx dot com
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 5+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-11-18 22:10 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #10 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jeff Law <law@gcc.gnu.org>:

https://gcc.gnu.org/g:1be4878116a2be82552bd59c3c1c9adcac3d106b

commit r11-5152-g1be4878116a2be82552bd59c3c1c9adcac3d106b
Author: Roger Sayle <roger@nextmovesoftware.com>
Date:   Wed Nov 18 15:09:46 2020 -0700

    Fix middle-end/85811: Introduce tree_expr_maybe_non_p et al.

    The motivation for this patch is PR middle-end/85811, a wrong-code
    regression entitled "Invalid optimization with fmax, fabs and nan".
    The optimization involves assuming max(x,y) is non-negative if (say)
    y is non-negative, i.e. max(x,2.0).  Unfortunately, this is an invalid
    assumption in the presence of NaNs.  Hence max(x,+qNaN), with IEEE fmax
    semantics will always return x even though the qNaN is non-negative.
    Worse, max(x,2.0) may return a negative value if x is -sNaN.

    I'll quote Joseph Myers (many thanks) who describes things clearly as:
    > (a) When both arguments are NaNs, the return value should be a qNaN,
    > but sometimes it is an sNaN if at least one argument is an sNaN.
    > (b) Under TS 18661-1 semantics, if either argument is an sNaN then the
    > result should be a qNaN (whereas if one argument is a qNaN and the
    > other is not a NaN, the result should be the non-NaN argument).
    > Various implementations treat sNaNs like qNaNs here.

    Under this logic, the tree_expr_nonnegative_p for IEEE fmax should be:

        CASE_CFN_FMAX:
        CASE_CFN_FMAX_FN:
          /* Usually RECURSE (arg0) || RECURSE (arg1) but NaNs complicate
             things.  In the presence of sNaNs, we're only guaranteed to be
             non-negative if both operands are non-negative.  In the presence
             of qNaNs, we're non-negative if either operand is non-negative
             and can't be a qNaN, or if both operands are non-negative.  */
          if (tree_expr_maybe_signaling_nan_p (arg0) ||
              tree_expr_maybe_signaling_nan_p (arg1))
            return RECURSE (arg0) && RECURSE (arg1);
          return RECURSE (arg0) ? (!tree_expr_maybe_nan_p (arg0)
                                  || RECURSE (arg1))
                                : (RECURSE (arg1)
                                  && !tree_expr_maybe_nan_p (arg1));

    Which indeed resolves the wrong code in the PR.  The infrastructure that
    makes this possible are the two new functions tree_expr_maybe_nan_p and
    tree_expr_maybe_signaling_nan_p which test whether a value may potentially
    be a NaN or a signaling NaN respectively.  In fact, this patch adds seven
    new predicates to the middle-end:

    bool tree_expr_finite_p (const_tree);
    bool tree_expr_infinite_p (const_tree);
    bool tree_expr_maybe_infinite_p (const_tree);
    bool tree_expr_signaling_nan_p (const_tree);
    bool tree_expr_maybe_signaling_nan_p (const_tree);
    bool tree_expr_nan_p (const_tree);
    bool tree_expr_maybe_nan_p (const_tree);

    These functions correspond to the "must" and "may" operators in modal
logic,
    and allow us to triage expressions in the middle-end; definitely a NaN,
    definitely not a NaN, and unknown at compile-time, etc.  A prime example of
    the utility of these functions is that a IEEE floating point value promoted
    from an integer type can't be a NaN or infinite.  Hence (double)i+0.0 where
    i is an integer can be simplified to (double)i even with -fsignaling-nans.
    Currently in GCC optimizations are enabled/disabled based on whether the
    expression's type supports NaNs or sNaNs; with these new predicates they
    can be controlled by whether the actual operands may or may not be NaNs.

    Having added these extremely useful helper functions to the middle-end,
    I couldn't help by use then in a few places in fold-const.c, builtins.c
    and match.pd.  In the near term, these can/should be used in places
    where the tree optimizers test for HONOR_NANS, HONOR_INFINITIES or
    HONOR_SNANS, or explicitly test whether a REAL_CST is a NaN or Inf.
    In the longer term (I'm not volunteering) these predicates could perhaps
    be hooked into the middle-end's SSA chaining and/or VRP machinery,
    allowing finiteness to propagated around the CFG, much like we
    currently propagate value ranges.

    This patch has been tested on x86_64-pc-linux-gnu with a "make bootstrap"
    and "make -k check".
    Ok for mainline?

    2020-08-15  Roger Sayle  <roger@nextmovesoftware.com>

    gcc/ChangeLog
            PR middle-end/85811
            * fold-const.c (tree_expr_finite_p): New function to test whether
            a tree expression must be finite, i.e. not a FP NaN or infinity.
            (tree_expr_infinite_p):  New function to test whether a tree
            expression must be infinite, i.e. a FP infinity.
            (tree_expr_maybe_infinite_p): New function to test whether a tree
            expression may be infinite, i.e. a FP infinity.
            (tree_expr_signaling_nan_p): New function to test whether a tree
            expression must evaluate to a signaling NaN (sNaN).
            (tree_expr_maybe_signaling_nan_p): New function to test whether a
            tree expression may be a signaling NaN (sNaN).
            (tree_expr_nan_p): New function to test whether a tree expression
            must evaluate to a (quiet or signaling) NaN.
            (tree_expr_maybe_nan_p): New function to test whether a tree
            expression me be a (quiet or signaling) NaN.

            (tree_binary_nonnegative_warnv_p) [MAX_EXPR]: In the presence
            of NaNs, MAX_EXPR is only guaranteed to be non-negative, if both
            operands are non-negative.
            (tree_call_nonnegative_warnv_p) [CASE_CFN_FMAX,CASE_CFN_FMAX_FN]:
            In the presence of signaling NaNs, fmax is only guaranteed to be
            non-negative if both operands are negative.  In the presence of
            quiet NaNs, fmax is non-negative if either operand is non-negative
            and not a qNaN, or both operands are non-negative.

            * fold-const.h (tree_expr_finite_p, tree_expr_infinite_p,
            tree_expr_maybe_infinite_p, tree_expr_signaling_nan_p,
            tree_expr_maybe_signaling_nan_p, tree_expr_nan_p,
            tree_expr_maybe_nan_p): Prototype new functions here.

            * builtins.c (fold_builtin_classify) [BUILT_IN_ISINF]: Fold to
            a constant if argument is known to be (or not to be) an Infinity.
            [BUILT_IN_ISFINITE]: Fold to a constant if argument is known to
            be (or not to be) finite.
            [BUILT_IN_ISNAN]: Fold to a constant if argument is known to be
            (or not to be) a NaN.
            (fold_builtin_fpclassify): Check tree_expr_maybe_infinite_p and
            tree_expr_maybe_nan_p instead of HONOR_INFINITIES and HONOR_NANS
            respectively.
            (fold_builtin_unordered_cmp): Fold UNORDERED_EXPR to a constant
            when its arguments are known to be (or not be) NaNs.  Check
            tree_expr_maybe_nan_p instead of HONOR_NANS when choosing between
            unordered and regular forms of comparison operators.

            * match.pd (ordered(x,y)->true/false): Constant fold ORDERED_EXPR
            if its operands are known to be (or not to be) NaNs.
            (unordered(x,y)->true/false): Constant fold UNORDERED_EXPR if its
            operands are known to be (or not to be) NaNs.
            (sqrt(x)*sqrt(x)->x): Check tree_expr_maybe_signaling_nan_p instead
            of HONOR_SNANS.

    gcc/testsuite/ChangeLog
            PR middle-end/85811
            * gcc.dg/pr85811.c: New test.
            * gcc.dg/fold-isfinite-1.c: New test.
            * gcc.dg/fold-isfinite-2.c: New test.
            * gcc.dg/fold-isinf-1.c: New test.
            * gcc.dg/fold-isinf-2.c: New test.
            * gcc.dg/fold-isnan-1.c: New test.
            * gcc.dg/fold-isnan-2.c: New test.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/85811] Invalid optimization with fmax, fabs and nan
       [not found] <bug-85811-4@http.gcc.gnu.org/bugzilla/>
  2020-11-18 22:10 ` [Bug middle-end/85811] Invalid optimization with fmax, fabs and nan cvs-commit at gcc dot gnu.org
@ 2020-12-02  5:32 ` asolokha at gmx dot com
  2020-12-02  7:54 ` rguenth at gcc dot gnu.org
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 5+ messages in thread
From: asolokha at gmx dot com @ 2020-12-02  5:32 UTC (permalink / raw)
  To: gcc-bugs

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

Arseny Solokha <asolokha at gmx dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |asolokha at gmx dot com

--- Comment #11 from Arseny Solokha <asolokha at gmx dot com> ---
Are there backports pending?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/85811] Invalid optimization with fmax, fabs and nan
       [not found] <bug-85811-4@http.gcc.gnu.org/bugzilla/>
  2020-11-18 22:10 ` [Bug middle-end/85811] Invalid optimization with fmax, fabs and nan cvs-commit at gcc dot gnu.org
  2020-12-02  5:32 ` asolokha at gmx dot com
@ 2020-12-02  7:54 ` rguenth at gcc dot gnu.org
  2021-01-11 12:23 ` rguenth at gcc dot gnu.org
  2022-02-05 17:55 ` roger at nextmovesoftware dot com
  4 siblings, 0 replies; 5+ messages in thread
From: rguenth at gcc dot gnu.org @ 2020-12-02  7:54 UTC (permalink / raw)
  To: gcc-bugs

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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
      Known to work|                            |11.0
           Assignee|unassigned at gcc dot gnu.org      |sayle at gcc dot gnu.org
             Status|NEW                         |ASSIGNED

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/85811] Invalid optimization with fmax, fabs and nan
       [not found] <bug-85811-4@http.gcc.gnu.org/bugzilla/>
                   ` (2 preceding siblings ...)
  2020-12-02  7:54 ` rguenth at gcc dot gnu.org
@ 2021-01-11 12:23 ` rguenth at gcc dot gnu.org
  2022-02-05 17:55 ` roger at nextmovesoftware dot com
  4 siblings, 0 replies; 5+ messages in thread
From: rguenth at gcc dot gnu.org @ 2021-01-11 12:23 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> ---
Possibly could be backported even if not a regression but I guess the
wrong-code is really restricted to cases we don't hit in the wild.

That said, not objecting if anybody wants to backport to GCC 10.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/85811] Invalid optimization with fmax, fabs and nan
       [not found] <bug-85811-4@http.gcc.gnu.org/bugzilla/>
                   ` (3 preceding siblings ...)
  2021-01-11 12:23 ` rguenth at gcc dot gnu.org
@ 2022-02-05 17:55 ` roger at nextmovesoftware dot com
  4 siblings, 0 replies; 5+ messages in thread
From: roger at nextmovesoftware dot com @ 2022-02-05 17:55 UTC (permalink / raw)
  To: gcc-bugs

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

Roger Sayle <roger at nextmovesoftware dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
         Resolution|---                         |FIXED
                 CC|                            |roger at nextmovesoftware dot com

--- Comment #13 from Roger Sayle <roger at nextmovesoftware dot com> ---
Fixed on mainline.  [Sorry I've only just noticed this hadn't been closed].

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-02-05 17:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <bug-85811-4@http.gcc.gnu.org/bugzilla/>
2020-11-18 22:10 ` [Bug middle-end/85811] Invalid optimization with fmax, fabs and nan cvs-commit at gcc dot gnu.org
2020-12-02  5:32 ` asolokha at gmx dot com
2020-12-02  7:54 ` rguenth at gcc dot gnu.org
2021-01-11 12:23 ` rguenth at gcc dot gnu.org
2022-02-05 17:55 ` roger at nextmovesoftware dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).