]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Value Range: Add range op for builtin isinf
authorHaochen Gui <guihaoc@gcc.gnu.org>
Thu, 15 Aug 2024 03:19:10 +0000 (11:19 +0800)
committerHaochen Gui <guihaoc@gcc.gnu.org>
Thu, 15 Aug 2024 03:19:10 +0000 (11:19 +0800)
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.

gcc/gimple-range-op.cc
gcc/testsuite/gcc.dg/tree-ssa/range-isinf.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/range-sincos.c
gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c

index a80b93cf063153b819c82aec3931f1c760cfdaa3..24559951dd692a255e922cc31e83c00b801041ef 100644 (file)
@@ -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 (file)
index 0000000..468f1bc
--- /dev/null
@@ -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" } } */
+
index 35b38c3c9147c5f997fad16ad5b32f0e0c187665..337f9cda02f235dfd8d545b0de90f24aebe2dac6 100644 (file)
@@ -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 } } } } }
index a814a9739633cabe80fbfb0a1f7be2b0f7b18004..4b7b75833e016048b1517ae34da5857577cb8266 100644 (file)
@@ -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" } }