https://gcc.gnu.org/g:cd0930768ff936b681135bf8873e7f7b796a4ed9

commit r15-2922-gcd0930768ff936b681135bf8873e7f7b796a4ed9
Author: Haochen Gui <guih...@gcc.gnu.org>
Date:   Thu Aug 15 11:19:10 2024 +0800

    Value Range: Add range op for builtin isinf
    
    The builtin isinf is not folded at front end if the corresponding optab
    exists.  So the range op for isinf is needed for value range analysis.
    This patch adds range op for builtin isinf.
    
    gcc/
            PR target/114678
            * gimple-range-op.cc (class cfn_isinf): New.
            (op_cfn_isinf): New variables.
            (gimple_range_op_handler::maybe_builtin_call): Handle
            CASE_FLT_FN (BUILT_IN_ISINF).
    
    gcc/testsuite/
            PR target/114678
            * gcc.dg/tree-ssa/range-isinf.c: New test.
            * gcc.dg/tree-ssa/range-sincos.c: Remove xfail for s390.
            * gcc.dg/tree-ssa/vrp-float-abs-1.c: Likewise.

Diff:
---
 gcc/gimple-range-op.cc                          | 62 +++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/range-isinf.c     | 44 ++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/range-sincos.c    |  2 +-
 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c |  2 +-
 4 files changed, 108 insertions(+), 2 deletions(-)

diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index a80b93cf063..24559951dd6 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -1153,6 +1153,63 @@ private:
   bool m_is_pos;
 } op_cfn_goacc_dim_size (false), op_cfn_goacc_dim_pos (true);
 
+// Implement range operator for CFN_BUILT_IN_ISINF
+class cfn_isinf : public range_operator
+{
+public:
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  virtual bool fold_range (irange &r, tree type, const frange &op1,
+                          const irange &, relation_trio) const override
+  {
+    if (op1.undefined_p ())
+      return false;
+
+    if (op1.known_isinf ())
+      {
+       wide_int one = wi::one (TYPE_PRECISION (type));
+       r.set (type, one, one);
+       return true;
+      }
+
+    if (op1.known_isnan ()
+       || (!real_isinf (&op1.lower_bound ())
+           && !real_isinf (&op1.upper_bound ())))
+      {
+       r.set_zero (type);
+       return true;
+      }
+
+    r.set_varying (type);
+    return true;
+  }
+  virtual bool op1_range (frange &r, tree type, const irange &lhs,
+                         const frange &, relation_trio) const override
+  {
+    if (lhs.undefined_p ())
+      return false;
+
+    if (lhs.zero_p ())
+      {
+       nan_state nan (true);
+       r.set (type, real_min_representable (type),
+              real_max_representable (type), nan);
+       return true;
+      }
+
+    if (!range_includes_zero_p (lhs))
+      {
+       // The range is [-INF,-INF][+INF,+INF], but it can't be represented.
+       // Set range to [-INF,+INF]
+       r.set_varying (type);
+       r.clear_nan ();
+       return true;
+      }
+
+    r.set_varying (type);
+    return true;
+  }
+} op_cfn_isinf;
 
 // Implement range operator for CFN_BUILT_IN_
 class cfn_parity : public range_operator
@@ -1246,6 +1303,11 @@ gimple_range_op_handler::maybe_builtin_call ()
       m_operator = &op_cfn_signbit;
       break;
 
+    CASE_FLT_FN (BUILT_IN_ISINF):
+      m_op1 = gimple_call_arg (call, 0);
+      m_operator = &op_cfn_isinf;
+      break;
+
     CASE_CFN_COPYSIGN_ALL:
       m_op1 = gimple_call_arg (call, 0);
       m_op2 = gimple_call_arg (call, 1);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/range-isinf.c 
b/gcc/testsuite/gcc.dg/tree-ssa/range-isinf.c
new file mode 100644
index 00000000000..468f1bcf5c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/range-isinf.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+#include <math.h>
+void link_error();
+
+void
+test1 (double x)
+{
+  if (x > __DBL_MAX__ && !__builtin_isinf (x))
+    link_error ();
+  if (x < -__DBL_MAX__ && !__builtin_isinf (x))
+    link_error ();
+}
+
+void
+test2 (float x)
+{
+  if (x > __FLT_MAX__ && !__builtin_isinf (x))
+    link_error ();
+  if (x < -__FLT_MAX__ && !__builtin_isinf (x))
+    link_error ();
+}
+
+void
+test3 (double x)
+{
+  if (!__builtin_isinf (x) && !__builtin_isnan (x) && x > __DBL_MAX__)
+    link_error ();
+  if (!__builtin_isinf (x) && !__builtin_isnan (x) && x < -__DBL_MAX__)
+    link_error ();
+}
+
+void
+test4 (float x)
+{
+  if (!__builtin_isinf (x) && !__builtin_isnan (x) && x > __FLT_MAX__)
+    link_error ();
+  if (!__builtin_isinf (x) && !__builtin_isnan (x) && x < -__FLT_MAX__)
+    link_error ();
+}
+
+/* { dg-final { scan-tree-dump-not "link_error" "evrp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/range-sincos.c 
b/gcc/testsuite/gcc.dg/tree-ssa/range-sincos.c
index 35b38c3c914..337f9cda02f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/range-sincos.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/range-sincos.c
@@ -40,4 +40,4 @@ stool (double x)
     link_error ();
 }
 
-// { dg-final { scan-tree-dump-not "link_error" "evrp" { target { { *-*-linux* 
} && { glibc } } xfail s390*-*-* } } } xfail: PR114678
+// { dg-final { scan-tree-dump-not "link_error" "evrp" { target { { *-*-linux* 
} && { glibc } } } } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c
index a814a973963..4b7b75833e0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c
@@ -14,4 +14,4 @@ foo (double x, double y)
     }
 }
 
-// { dg-final { scan-tree-dump-not "link_error" "evrp" { xfail s390*-*-* } } } 
xfail: PR114678
+// { dg-final { scan-tree-dump-not "link_error" "evrp" } }

Reply via email to