[PATCH] range: Add some non-negative function support [PR126827]

Andrea Pinski <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
This adds some simple non-negative support for some
builtins that return a real type.
There are 3 categories of functions:
* non-negative independent of arguments
* non-negative dependent on the first argument
* non-negative dependent on the first argument
  and sets the nan-ness based on if the first argument contains a nan.

This is the first step in removing gimple_stmt_nonnegative_p or rather
moving it just use the current ranger rather than doing a recusive walk.

I have not added the functions which return an integer and a double value
yet.  This will be done in a seperate patch.

For sinhatanh-3.c I had turn off jump threading otherwise there are more
copies of atanhl on x86_64 due to ATANHL being an optab and cdce would
create some conditions that could be jump threaded now. This is ok since
what this is testing to make sure the pattern added r9-4480-g4aff6d17446ade
in does not happen.

Bootstrapped and tested on x86_64-linux-gnu.

	PR tree-optimization/126827

gcc/ChangeLog:

	* gimple-range-op.cc (class cfn_fp_nonnegative): New class.
	(class cfn_fp_nonnegative_arg0): New class.
	(gimple_range_op_handler::maybe_builtin_call): Handle some
	functions which were handled in nonnegative.

gcc/testsuite/ChangeLog:

	* gcc.dg/sinhatanh-3.c: Turn off jump threading.
	* gcc.dg/tree-ssa/ceil-1.c: New test.

Signed-off-by: Andrea Pinski <[email protected]>
---
 gcc/gimple-range-op.cc                 | 134 +++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/sinhatanh-3.c     |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ceil-1.c |  17 ++++
 3 files changed, 152 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ceil-1.c

diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 63eccc3fb9f..20666ff0356 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -794,6 +794,54 @@ private:
   combined_fn m_cfn;
 } op_cfn_sin (CFN_SIN), op_cfn_cos (CFN_COS);
 
+
+// FP functions which are nonnegative independent of the arguments.
+class cfn_fp_nonnegative : public range_operator
+{
+public:
+  using range_operator::fold_range;
+  virtual bool fold_range (frange &r, tree type,
+			   const frange &, const frange &,
+			   relation_trio) const final override
+  {
+    r.set_nonnegative (type);
+    return true;
+  }
+} op_cfn_fp_nonegative;
+
+// FP functions which are nonnegative if arg0 is nonnegative.
+// Also handles pass through of if non-nan
+class cfn_fp_nonnegative_arg0 : public range_operator
+{
+public:
+  using range_operator::fold_range;
+  cfn_fp_nonnegative_arg0(bool nan) : arg_nan (nan) {}
+  virtual bool fold_range (frange &r, tree type,
+			   const frange &op1, const frange &,
+			   relation_trio) const final override
+  {
+    if (op1.undefined_p ())
+      return false;
+    bool changed = false;
+    bool sign = false;
+    if (op1.signbit_p (sign) && !sign)
+      {
+	r.set_nonnegative (type);
+	changed = true;
+      }
+    if (arg_nan && !op1.maybe_isnan ())
+      {
+	if (r.undefined_p ())
+	  r.set_varying (type);
+	r.clear_nan ();
+	changed = true;
+      }
+    return changed;
+  }
+private:
+  bool arg_nan;
+} op_cfn_fp_nonegative_arg0(false), op_cfn_fp_nonegative_nan_arg0(true);
+
 // Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER.
 class cfn_toupper_tolower : public range_operator
 {
@@ -1574,6 +1622,92 @@ gimple_range_op_handler::maybe_builtin_call ()
       m_operator = &op_cfn_parity;
       break;
 
+    CASE_CFN_ACOS:
+    CASE_CFN_ACOS_FN:
+    CASE_CFN_ACOSH:
+    CASE_CFN_ACOSH_FN:
+    CASE_CFN_ACOSPI:
+    CASE_CFN_ACOSPI_FN:
+    CASE_CFN_CABS:
+    CASE_CFN_CABS_FN:
+    CASE_CFN_COSH:
+    CASE_CFN_COSH_FN:
+    CASE_CFN_ERFC:
+    CASE_CFN_ERFC_FN:
+    CASE_CFN_EXP:
+    CASE_CFN_EXP_FN:
+    CASE_CFN_EXP10:
+    CASE_CFN_EXP2:
+    CASE_CFN_EXP2_FN:
+    CASE_CFN_FABS:
+    CASE_CFN_FABS_FN:
+    CASE_CFN_FDIM:
+    CASE_CFN_FDIM_FN:
+    CASE_CFN_HYPOT:
+    CASE_CFN_HYPOT_FN:
+    CASE_CFN_POW10:
+      m_operator = &op_cfn_fp_nonegative;
+      break;
+
+    // FIXME: some of these can do better than just nonnegative.
+    CASE_CFN_ASINH:
+    CASE_CFN_ASINH_FN:
+    CASE_CFN_ASINPI:
+    CASE_CFN_ASINPI_FN:
+    CASE_CFN_ATAN:
+    CASE_CFN_ATAN_FN:
+    CASE_CFN_ATANH:
+    CASE_CFN_ATANH_FN:
+    CASE_CFN_ATANPI:
+    CASE_CFN_ATANPI_FN:
+    CASE_CFN_CBRT:
+    CASE_CFN_CBRT_FN:
+    CASE_CFN_ERF:
+    CASE_CFN_ERF_FN:
+    CASE_CFN_EXPM1:
+    CASE_CFN_EXPM1_FN:
+    CASE_CFN_FMOD:
+    CASE_CFN_FMOD_FN:
+    CASE_CFN_FREXP:
+    CASE_CFN_FREXP_FN:
+    CASE_CFN_MODF:
+    CASE_CFN_MODF_FN:
+    CASE_CFN_SCALB:
+    CASE_CFN_SCALBLN:
+    CASE_CFN_SCALBLN_FN:
+    CASE_CFN_SCALBN:
+    CASE_CFN_SCALBN_FN:
+    CASE_CFN_SIGNIFICAND:
+    CASE_CFN_SINH:
+    CASE_CFN_SINH_FN:
+    CASE_CFN_TANH:
+    CASE_CFN_TANH_FN:
+    CASE_CFN_LDEXP:
+      m_operator = &op_cfn_fp_nonegative_arg0;
+      m_op1 = gimple_call_arg (call, 0);
+      break;
+
+
+    // FIXME: these can be improved for the rounding builtins.
+    // Currently just sets non-negative and update nan.
+    CASE_CFN_FLOOR:
+    CASE_CFN_FLOOR_FN:
+    CASE_CFN_CEIL:
+    CASE_CFN_CEIL_FN:
+    CASE_CFN_NEARBYINT:
+    CASE_CFN_NEARBYINT_FN:
+    CASE_CFN_RINT:
+    CASE_CFN_RINT_FN:
+    CASE_CFN_ROUND:
+    CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
+    CASE_CFN_TRUNC:
+    CASE_CFN_TRUNC_FN:
+      m_operator = &op_cfn_fp_nonegative_nan_arg0;
+      m_op1 = gimple_call_arg (call, 0);
+      break;
+
     default:
       {
 	unsigned arg;
diff --git a/gcc/testsuite/gcc.dg/sinhatanh-3.c b/gcc/testsuite/gcc.dg/sinhatanh-3.c
index ad0353ae828..d60c112b3f2 100644
--- a/gcc/testsuite/gcc.dg/sinhatanh-3.c
+++ b/gcc/testsuite/gcc.dg/sinhatanh-3.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-Ofast -fmath-errno -fdump-tree-optimized" } */
+/* { dg-options "-Ofast -fmath-errno -fdump-tree-optimized -fno-thread-jumps" } */
 
 extern float sinhf (float);
 extern float coshf (float);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ceil-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ceil-1.c
new file mode 100644
index 00000000000..ea3126ad5b9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ceil-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+/* PR tree-optimization/126827 */
+
+double f(double a)
+{
+    if (a > 0)
+    {
+      a = __builtin_ceil(a);
+      if (a < 0)
+        __builtin_trap();
+    }
+    return a;
+}
+
+/* The call to __builtin_trap should have been removed.  */
+/* { dg-final { scan-tree-dump-not "trap " "optimized" } } */
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.