Allow non-overflow ops in reductions
authorTom de Vries <tom@codesourcery.com>
Sat, 1 Aug 2015 08:29:29 +0000 (08:29 +0000)
committerTom de Vries <vries@gcc.gnu.org>
Sat, 1 Aug 2015 08:29:29 +0000 (08:29 +0000)
2015-08-01  Tom de Vries  <tom@codesourcery.com>

* tree.c (operation_can_overflow, operation_no_trapping_overflow): New
function.
* tree.h (operation_can_overflow, operation_no_trapping_overflow):
Declare.
* tree-vect-loop.c (vect_is_simple_reduction_1): Use
operation_no_trapping_overflow.  Allow non-overflow operations.
* graphite-sese-to-poly.c (is_reduction_operation_p): Allow non-overflow
operations.

* gcc.dg/autopar/reduc-2char.c (init_arrays): Mark with attribute
optimize ("-ftree-parallelize-loops=0").
Add successful scans for 2 detected reductions.  Add xfail scans for 3
detected reductions.
* gcc.dg/autopar/reduc-2short.c: Same.
* gcc.dg/autopar/reduc-8.c (init_arrays): Mark with attribute
optimize ("-ftree-parallelize-loops=0").  Add successful scans for 2
detected reductions.
* gcc.dg/vect/trapv-vect-reduc-4.c: Update scan to match vectorized min
and max reductions.

From-SVN: r226463

gcc/ChangeLog
gcc/graphite-sese-to-poly.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/autopar/reduc-2char.c
gcc/testsuite/gcc.dg/autopar/reduc-2short.c
gcc/testsuite/gcc.dg/autopar/reduc-8.c
gcc/testsuite/gcc.dg/vect/trapv-vect-reduc-4.c
gcc/tree-vect-loop.c
gcc/tree.c
gcc/tree.h

index ead355e5a0fd89a7678f9b1c1ed878862f0334dc..53b44c1bbc48f3920bd32d991eba2abc5a175e73 100644 (file)
@@ -1,3 +1,14 @@
+2015-08-01  Tom de Vries  <tom@codesourcery.com>
+
+       * tree.c (operation_can_overflow, operation_no_trapping_overflow): New
+       function.
+       * tree.h (operation_can_overflow, operation_no_trapping_overflow):
+       Declare.
+       * tree-vect-loop.c (vect_is_simple_reduction_1): Use
+       operation_no_trapping_overflow.  Allow non-overflow operations.
+       * graphite-sese-to-poly.c (is_reduction_operation_p): Allow non-overflow
+       operations.
+
 2015-07-31  Kaz Kojima  <kkojima@gcc.gnu.org>
 
        PR target/67049
index c583f167157048c134ccf23c2ed569f82cd7895a..fdcc790336ca87b4fd95f049061755944a4dd6e1 100644 (file)
@@ -2614,8 +2614,11 @@ is_reduction_operation_p (gimple stmt)
   if (FLOAT_TYPE_P (type))
     return flag_associative_math;
 
-  return (INTEGRAL_TYPE_P (type)
-         && TYPE_OVERFLOW_WRAPS (type));
+  if (ANY_INTEGRAL_TYPE_P (type))
+    return (TYPE_OVERFLOW_WRAPS (type)
+           || !operation_can_overflow (code));
+
+  return false;
 }
 
 /* Returns true when PHI contains an argument ARG.  */
index 6513cf01b2c00be1e561cc9d41af1c0d5d322468..8117434d1586705261e932a7d0a48ba0291fb222 100644 (file)
@@ -1,3 +1,16 @@
+2015-08-01  Tom de Vries  <tom@codesourcery.com>
+
+       * gcc.dg/autopar/reduc-2char.c (init_arrays): Mark with attribute
+       optimize ("-ftree-parallelize-loops=0").
+       Add successful scans for 2 detected reductions.  Add xfail scans for 3
+       detected reductions.
+       * gcc.dg/autopar/reduc-2short.c: Same.
+       * gcc.dg/autopar/reduc-8.c (init_arrays): Mark with attribute
+       optimize ("-ftree-parallelize-loops=0").  Add successful scans for 2
+       detected reductions.
+       * gcc.dg/vect/trapv-vect-reduc-4.c: Update scan to match vectorized min
+       and max reductions.
+
 2015-07-31  Marek Polacek  <polacek@redhat.com>
 
        PR sanitizer/66977
index 14867f343277cdc9b162806a6eba34217ed486bc..a2dad4465119d6d67ad77b7a3d919d95bfb54771 100644 (file)
@@ -39,8 +39,9 @@ void main1 (signed char x, signed char max_result, signed char min_result)
     abort ();
 }
 
- __attribute__((noinline))
- void init_arrays ()
+void __attribute__((noinline))
+  __attribute__((optimize ("-ftree-parallelize-loops=0")))
+init_arrays ()
  {
    int i;
 
@@ -60,7 +61,10 @@ int main (void)
 }
 
 
-/* { dg-final { scan-tree-dump-times "Detected reduction" 2 "parloops" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "Detected reduction" 2 "parloops" } } */
+/* { dg-final { scan-tree-dump-times "Detected reduction" 3 "parloops" { xfail *-*-* } } } */
+
+/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 2 "parloops" } } */
 /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops" { xfail *-*-* } } } */
 
 
index 7c19cc59fd33b7edc91f424f8f7ce309c4cf6d67..a50e14f0cb4be37289361ccf7ac3336c902fde37 100644 (file)
@@ -38,8 +38,9 @@ void main1 (short x, short max_result, short min_result)
     abort ();
 }
 
- __attribute__((noinline))
- void init_arrays ()
+void __attribute__((noinline))
+  __attribute__((optimize ("-ftree-parallelize-loops=0")))
+init_arrays ()
  {
    int i;
 
@@ -58,7 +59,8 @@ int main (void)
   return 0;
 }
 
+/* { dg-final { scan-tree-dump-times "Detected reduction" 2 "parloops" } } */
+/* { dg-final { scan-tree-dump-times "Detected reduction" 3 "parloops" { xfail *-*-* } } } */
 
-/* { dg-final { scan-tree-dump-times "Detected reduction" 2 "parloops" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 2 "parloops" } } */
 /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops" { xfail *-*-* } } } */
-
index 1d05c48274e7b6f45167a86fce04abd82cbb9e9b..18ba03d56322ac103dfdedf9a2b68d5cafe3c824 100644 (file)
@@ -40,7 +40,8 @@ testmin (const T *c, T init, T result)
     abort ();
 }
 
-int main (void)
+int __attribute__((optimize ("-ftree-parallelize-loops=0")))
+main (void)
 { 
   static signed char A[N] = {
     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
@@ -84,5 +85,5 @@ int main (void)
 }
 
 
-/* { dg-final { scan-tree-dump-times "Detected reduction" 2 "parloops" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "Detected reduction" 2 "parloops" } } */
+/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 2 "parloops" } } */
index 21297178a002901649e1b3a9b7db9e054eb63729..86f9b9002baa4e1a245b2edf00a3fb1e5754f46c 100644 (file)
@@ -46,4 +46,4 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
index c31bfbdbad42d4f77c5207a38809fa7ccc90f805..59c75af73237f6f6b74607de6adf3199fbae790a 100644 (file)
@@ -2615,7 +2615,7 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi,
     }
   else if (INTEGRAL_TYPE_P (type) && check_reduction)
     {
-      if (TYPE_OVERFLOW_TRAPS (type))
+      if (!operation_no_trapping_overflow (type, code))
        {
          /* Changing the order of operations changes the semantics.  */
          if (dump_enabled_p ())
@@ -2624,7 +2624,9 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi,
                            " (overflow traps): ");
          return NULL;
        }
-      if (need_wrapping_integral_overflow && !TYPE_OVERFLOW_WRAPS (type))
+      if (need_wrapping_integral_overflow
+         && !TYPE_OVERFLOW_WRAPS (type)
+         && operation_can_overflow (code))
        {
          /* Changing the order of operations changes the semantics.  */
          if (dump_enabled_p ())
index 94263af9a15511fc6812ab28aada2b1f71dc1a6d..3c2c20a82b4fea5ba20c75faef1cdccb5c61a120 100644 (file)
@@ -7597,6 +7597,75 @@ commutative_ternary_tree_code (enum tree_code code)
   return false;
 }
 
+/* Returns true if CODE can overflow.  */
+
+bool
+operation_can_overflow (enum tree_code code)
+{
+  switch (code)
+    {
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case LSHIFT_EXPR:
+      /* Can overflow in various ways.  */
+      return true;
+    case TRUNC_DIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+      /* For INT_MIN / -1.  */
+      return true;
+    case NEGATE_EXPR:
+    case ABS_EXPR:
+      /* For -INT_MIN.  */
+      return true;
+    default:
+      /* These operators cannot overflow.  */
+      return false;
+    }
+}
+
+/* Returns true if CODE operating on operands of type TYPE doesn't overflow, or
+   ftrapv doesn't generate trapping insns for CODE.  */
+
+bool
+operation_no_trapping_overflow (tree type, enum tree_code code)
+{
+  gcc_checking_assert (ANY_INTEGRAL_TYPE_P (type));
+
+  /* We don't generate instructions that trap on overflow for complex or vector
+     types.  */
+  if (!INTEGRAL_TYPE_P (type))
+    return true;
+
+  if (!TYPE_OVERFLOW_TRAPS (type))
+    return true;
+
+  switch (code)
+    {
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case NEGATE_EXPR:
+    case ABS_EXPR:
+      /* These operators can overflow, and -ftrapv generates trapping code for
+        these.  */
+      return false;
+    case TRUNC_DIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case LSHIFT_EXPR:
+      /* These operators can overflow, but -ftrapv does not generate trapping
+        code for these.  */
+      return true;
+    default:
+      /* These operators cannot overflow.  */
+      return true;
+    }
+}
+
 namespace inchash
 {
 
index 6df22177fc22bb0209d119434c1931228908b59c..d280ea7fae5dc17a50ab19a717f45456114755d4 100644 (file)
@@ -4369,6 +4369,8 @@ extern int type_num_arguments (const_tree);
 extern bool associative_tree_code (enum tree_code);
 extern bool commutative_tree_code (enum tree_code);
 extern bool commutative_ternary_tree_code (enum tree_code);
+extern bool operation_can_overflow (enum tree_code);
+extern bool operation_no_trapping_overflow (tree, enum tree_code);
 extern tree upper_bound_in_type (tree, tree);
 extern tree lower_bound_in_type (tree, tree);
 extern int operand_equal_for_phi_arg_p (const_tree, const_tree);