@@ -1140,6 +1140,57 @@ 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 cnf_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 ())
+ {
+ r.set_nonzero (type);
+ return true;
+ }
+
+ if (op1.known_isnan ()
+ || (!real_isinf (&op1.lower_bound ())
+ && !real_isinf (&op1.upper_bound ())))
+ {
+ r.set_zero (type);
+ return true;
+ }
+
+ return false;
+ }
+ virtual bool op1_range (frange &r, tree type, const irange &lhs,
+ const frange &, relation_trio) const override
+ {
+ 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;
+ }
+
+ return false;
+ }
+} op_cfn_isinf;
// Implement range operator for CFN_BUILT_IN_
class cfn_parity : public range_operator
@@ -1232,6 +1283,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);
new file mode 100644
@@ -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" } } */
+