From 2a6218e97782f63dfe9836e6024fbb28c8cbb803 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Mon, 21 Mar 2022 16:26:40 +0100 Subject: [PATCH] [frange] Implement NAN aware stubs for FLOAT_EXPR, UNORDERED_EXPR, and MULT_EXPR. --- gcc/range-op-float.cc | 90 ++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c | 14 +++ gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c | 14 +++ gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c | 15 ++++ 4 files changed, 133 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index 988a3938959..52aaa01ab0f 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -922,6 +922,93 @@ foperator_cst::fold_range (frange &r, tree type ATTRIBUTE_UNUSED, return true; } +class foperator_cast : public range_operator +{ + using range_operator::fold_range; +public: + virtual bool fold_range (frange &r, tree type, + const irange &inner, + const frange &outer, + relation_kind rel = VREL_NONE) const override; +} fop_convert; + +bool +foperator_cast::fold_range (frange &r, tree type, + const irange &inner, + const frange &outer, + relation_kind) const +{ + if (empty_range_varying (r, type, inner, outer)) + return true; + + r.set_varying (type); + + // Some flags can be cleared when converting from ints. + r.clear_prop (FRANGE_PROP_NAN); + + return true; +} + +class foperator_unordered : public range_operator +{ + using range_operator::fold_range; +public: + virtual bool fold_range (irange &r, tree type, + const frange &lh, + const frange &rh, + relation_kind rel = VREL_NONE) const override; +} fop_unordered; + +bool +foperator_unordered::fold_range (irange &r, tree type, + const frange &lh, + const frange &rh, + relation_kind) const +{ + if (empty_range_varying (r, type, lh, rh)) + return true; + + // Return FALSE if both operands are !NaN. + if (!lh.get_prop (FRANGE_PROP_NAN) && !rh.get_prop (FRANGE_PROP_NAN)) + { + r = range_false (type); + return true; + } + + return false; +} + +class foperator_mult : public range_operator +{ + using range_operator::fold_range; +public: + virtual bool fold_range (frange &r, tree type, + const frange &lh, + const frange &rh, + relation_kind rel = VREL_NONE) const override; +} fop_mult; + +bool +foperator_mult::fold_range (frange &r, tree type, + const frange &lh, + const frange &rh, + relation_kind) const +{ + if (empty_range_varying (r, type, lh, rh)) + return true; + + // When x is !Nan, x * 0.0 = 0.0 + if (rh.zero_p () + && !rh.get_prop (FRANGE_PROP_NAN) + && !lh.get_prop (FRANGE_PROP_NAN)) + { + r.set_zero (type); + return true; + } + + return false; +} + class floating_table : public range_op_table { public: @@ -944,6 +1031,9 @@ floating_table::floating_table () set (PAREN_EXPR, fop_identity); set (OBJ_TYPE_REF, fop_identity); set (REAL_CST, fop_real_cst); + set (FLOAT_EXPR, fop_convert); + set (UNORDERED_EXPR, fop_unordered); + set (MULT_EXPR, fop_mult); } #if CHECKING_P diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c new file mode 100644 index 00000000000..92af87091a8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-O2 -fno-tree-forwprop -fno-tree-ccp -fno-tree-fre -fdump-tree-evrp" } + +extern void link_error (); + +void +foo () +{ + float z = 0.0; + if (__builtin_isnan (z)) + link_error (); +} + +// { dg-final { scan-tree-dump-not "link_error" "evrp" } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c new file mode 100644 index 00000000000..d38ea523bea --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-O2 -fno-tree-forwprop -fno-thread-jumps -fdump-tree-evrp" } + +extern void link_error (); + +void +foo (int i) +{ + float z = i; + if (__builtin_isnan (z)) + link_error (); +} + +// { dg-final { scan-tree-dump-not "link_error" "evrp" } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c new file mode 100644 index 00000000000..6c26a295f94 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-options "-O2 -fno-tree-forwprop -fno-thread-jumps -fdump-tree-evrp -fdump-tree-optimized" } + +extern void link_error (); + +int foo(int x, double y) +{ + return (x * 0.0) < y; +} + +// The multiply should be gone by *vrp time. +// { dg-final { scan-tree-dump-not " \\* " "evrp" } } + +// Ultimately, there sound be no references to "x". +// { dg-final { scan-tree-dump-not "x_" "optimized" } } -- 2.35.1