This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add FIXED_POINT_TYPE_OVERFLOW_WRAPS_P


[ was: [RFC, PR66873] Use graphite for parloops ]

On 22/07/15 13:02, Richard Biener wrote:
+#define FIXED_POINT_TYPE_OVERFLOW_WRAPS_P(TYPE) \
+  (NON_SAT_FIXED_POINT_TYPE_P (TYPE))

somebody with knowledge about fixed-point types needs to review this.

In vect_is_simple_reduction_1 I noticed:
...
  else if (SAT_FIXED_POINT_TYPE_P (type) && check_reduction)
    {
      /* Changing the order of operations changes the semantics.  */
      if (dump_enabled_p ())
        report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
"reduction: unsafe fixed-point math optimization: ");
      return NULL;
    }
...
In other words, you can change evaluation order if !SAT_FIXED_POINT_TYPE_P.

It is true that for saturating fixed point, you don't want to change evaluation order.

But I think that we actually want to test whether the fixed-point type wraps.

I tried to find proof that non-saturating fixed point wraps, but that doesn't seem trivial. IMHO, non-trivial enough to define a macro FIXED_POINT_TYPE_OVERFLOW_WRAPS_P, add a lengthy comment and use that instead of !SAT_FIXED_POINT_TYPE_P.

The intention of the patch is that it doesn't change behaviour of the compiler. Currently bootstrapping and reg-testing on x86_64.

OK for trunk?

Thanks,
- Tom
Add FIXED_POINT_TYPE_OVERFLOW_WRAPS_P

2015-07-24  Tom de Vries  <tom@codesourcery.com>

	* tree.h (FIXED_POINT_TYPE_OVERFLOW_WRAPS_P): Define.
	* fold-const.c (split_tree): Use FIXED_POINT_TYPE_OVERFLOW_WRAPS_P.
	* tree-ssa-reassoc.c (can_reassociate_p): Same.
	* tree-vect-loop.c (vect_is_simple_reduction_1): Same.
---
 gcc/fold-const.c       |  3 ++-
 gcc/tree-ssa-reassoc.c |  2 +-
 gcc/tree-vect-loop.c   |  4 +++-
 gcc/tree.h             | 18 ++++++++++++++++++
 4 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 886922f..2de71bb 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -808,7 +808,8 @@ split_tree (tree in, enum tree_code code, tree *conp, tree *litp,
     *litp = in;
   else if (TREE_CODE (in) == code
 	   || ((! FLOAT_TYPE_P (TREE_TYPE (in)) || flag_associative_math)
-	       && ! SAT_FIXED_POINT_TYPE_P (TREE_TYPE (in))
+	       && (!FIXED_POINT_TYPE_P (TREE_TYPE (in))
+		   || FIXED_POINT_TYPE_OVERFLOW_WRAPS_P (TREE_TYPE (in)))
 	       /* We can associate addition and subtraction together (even
 		  though the C standard doesn't say so) for integers because
 		  the value is not affected.  For reals, the value might be
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index efb813c..2851a13 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -4229,7 +4229,7 @@ can_reassociate_p (tree op)
 {
   tree type = TREE_TYPE (op);
   if ((INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
-      || NON_SAT_FIXED_POINT_TYPE_P (type)
+      || FIXED_POINT_TYPE_OVERFLOW_WRAPS_P (type)
       || (flag_associative_math && FLOAT_TYPE_P (type)))
     return true;
   return false;
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 42ba5f8..0e61a02 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -2635,7 +2635,9 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi,
 	  return NULL;
 	}
     }
-  else if (SAT_FIXED_POINT_TYPE_P (type) && check_reduction)
+  else if (FIXED_POINT_TYPE_P (type) &&
+	   !FIXED_POINT_TYPE_OVERFLOW_WRAPS_P (type)
+	   && check_reduction)
     {
       /* Changing the order of operations changes the semantics.  */
       if (dump_enabled_p ())
diff --git a/gcc/tree.h b/gcc/tree.h
index 360d13e..ab0e537 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -497,6 +497,24 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
 #define SAT_FIXED_POINT_TYPE_P(TYPE) \
   (TREE_CODE (TYPE) == FIXED_POINT_TYPE && TYPE_SATURATING (TYPE))
 
+/* Nonzero if fixed-point type TYPE wraps at overflow.
+
+   Fixed-point types that are explictly saturating do not wrap at overflow.
+
+   The draft technical report (N1169 draft of ISO/IEC DTR 18037) specifies
+   pragmas to control overflow for a fixed-point type that is not explictly
+   saturating (FX_FRACT_OVERFLOW and FX_ACCUM_OVERFLOW).  The possible states
+   of the pragmas are SAT and DEFAULT.  The default state for the pragmas is
+   DEFAULT, which means overflow has undefined behaviour.  GCC currently does
+   not support these pragmas.
+
+   The de-facto choice of GCC for fixed-point types that are not explictly
+   saturating seems to be modular wrap-around (as specified in Annex E.4 Modwrap
+   overflow).  */
+
+#define FIXED_POINT_TYPE_OVERFLOW_WRAPS_P(TYPE) \
+  (NON_SAT_FIXED_POINT_TYPE_P (TYPE))
+
 /* Nonzero if TYPE represents a fixed-point type.  */
 
 #define FIXED_POINT_TYPE_P(TYPE)	(TREE_CODE (TYPE) == FIXED_POINT_TYPE)
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]