Message ID | 49b03b9a-9a0c-44e3-9134-b01ebc758167@linux.ibm.com |
---|---|
State | New |
Headers | show |
Series | [PATCH-1v2] Value Range: Add range op for builtin isinf | expand |
Hi, Gently ping the series of patches which add range op. [PATCH-1v2] Value Range: Add range op for builtin isinf https://gcc.gnu.org/pipermail/gcc-patches/2024-May/652219.html [PATCH-2v3] Value Range: Add range op for builtin isfinite https://gcc.gnu.org/pipermail/gcc-patches/2024-May/652220.html [PATCH-3] Value Range: Add range op for builtin isnormal https://gcc.gnu.org/pipermail/gcc-patches/2024-May/652221.html Thanks Gui Haochen 在 2024/5/21 10:52, HAO CHEN GUI 写道: > Hi, > The builtin isinf is not folded at front end if the corresponding optab > exists. It causes the range evaluation failed on the targets which has > optab_isinf. For instance, range-sincos.c will fail on the targets which > has optab_isinf as it calls builtin_isinf. > > This patch fixed the problem by adding range op for builtin isinf. > > Compared with previous version, the main change is to set varying if > nothing is known about the range. > https://gcc.gnu.org/pipermail/gcc-patches/2024-March/648303.html > > Bootstrapped and tested on x86 and powerpc64-linux BE and LE with no > regressions. Is it OK for the trunk? > > Thanks > Gui Haochen > > > ChangeLog > 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/ > * 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/ > * gcc/testsuite/gcc.dg/tree-ssa/range-isinf.c: New test. > > patch.diff > diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc > index 55dfbb23ce2..eb1b0aff77c 100644 > --- a/gcc/gimple-range-op.cc > +++ b/gcc/gimple-range-op.cc > @@ -1175,6 +1175,62 @@ 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 ()) > + { > + 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; > + } > + > + 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 > @@ -1268,6 +1324,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/gimple-range-op.cc b/gcc/gimple-range-op.cc index 55dfbb23ce2..eb1b0aff77c 100644 --- a/gcc/gimple-range-op.cc +++ b/gcc/gimple-range-op.cc @@ -1175,6 +1175,62 @@ 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 ()) + { + 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; + } + + 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 @@ -1268,6 +1324,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" } } */ +