aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaochen Gui <guihaoc@gcc.gnu.org>2024-08-15 11:20:27 +0800
committerHaochen Gui <guihaoc@gcc.gnu.org>2024-08-15 11:26:45 +0800
commitb1d21582bafa1954db3a62f0972ae3a2e3bc0b48 (patch)
tree146d136fa985c2a371d827ed236b715383f9cede
parentcd0930768ff936b681135bf8873e7f7b796a4ed9 (diff)
downloadgcc-b1d21582bafa1954db3a62f0972ae3a2e3bc0b48.zip
gcc-b1d21582bafa1954db3a62f0972ae3a2e3bc0b48.tar.gz
gcc-b1d21582bafa1954db3a62f0972ae3a2e3bc0b48.tar.bz2
Value Range: Add range op for builtin isfinite
The former patch adds optab for builtin isfinite. Thus builtin isfinite might not be folded at front end. So the range op for isfinite is needed for value range analysis. This patch adds range op for builtin isfinite. gcc/ * gimple-range-op.cc (class cfn_isfinite): New. (op_cfn_finite): New variables. (gimple_range_op_handler::maybe_builtin_call): Handle CFN_BUILT_IN_ISFINITE. gcc/testsuite/ * gcc.dg/tree-ssa/range-isfinite.c: New test.
-rw-r--r--gcc/gimple-range-op.cc61
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/range-isfinite.c31
2 files changed, 92 insertions, 0 deletions
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 2455995..7edfa8e 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -1211,6 +1211,62 @@ public:
}
} op_cfn_isinf;
+//Implement range operator for CFN_BUILT_IN_ISFINITE
+class cfn_isfinite : 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_isfinite ())
+ {
+ wide_int one = wi::one (TYPE_PRECISION (type));
+ r.set (type, one, one);
+ return true;
+ }
+
+ if (op1.known_isnan ()
+ || op1.known_isinf ())
+ {
+ 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 ())
+ {
+ // The range is [-INF,-INF][+INF,+INF] NAN, but it can't be represented.
+ // Set range to varying
+ r.set_varying (type);
+ return true;
+ }
+
+ if (!range_includes_zero_p (lhs))
+ {
+ nan_state nan (false);
+ r.set (type, real_min_representable (type),
+ real_max_representable (type), nan);
+ return true;
+ }
+
+ r.set_varying (type);
+ return true;
+ }
+} op_cfn_isfinite;
+
// Implement range operator for CFN_BUILT_IN_
class cfn_parity : public range_operator
{
@@ -1308,6 +1364,11 @@ gimple_range_op_handler::maybe_builtin_call ()
m_operator = &op_cfn_isinf;
break;
+ case CFN_BUILT_IN_ISFINITE:
+ m_op1 = gimple_call_arg (call, 0);
+ m_operator = &op_cfn_isfinite;
+ 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-isfinite.c b/gcc/testsuite/gcc.dg/tree-ssa/range-isfinite.c
new file mode 100644
index 0000000..f5dce0a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/range-isfinite.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+#include <math.h>
+void link_error();
+
+void test1 (double x)
+{
+ if (x < __DBL_MAX__ && x > -__DBL_MAX__ && !__builtin_isfinite (x))
+ link_error ();
+}
+
+void test2 (float x)
+{
+ if (x < __FLT_MAX__ && x > -__FLT_MAX__ && !__builtin_isfinite (x))
+ link_error ();
+}
+
+void test3 (double x)
+{
+ if (__builtin_isfinite (x) && __builtin_isinf (x))
+ link_error ();
+}
+
+void test4 (float x)
+{
+ if (__builtin_isfinite (x) && __builtin_isinf (x))
+ link_error ();
+}
+
+/* { dg-final { scan-tree-dump-not "link_error" "evrp" } } */