middle-end/103181 - fix operation_could_trap_p for vector division

Message ID 66nqqp2q-36pr-88q0-pq92-rs62177r5soq@fhfr.qr
State New
Headers
Series middle-end/103181 - fix operation_could_trap_p for vector division |

Commit Message

Richard Biener Nov. 11, 2021, 9:32 a.m. UTC
  For integer vector division we only checked for all zero vector
constants rather than checking whether any element in the constant
vector is zero.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

2021-11-11  Richard Biener  <rguenther@suse.de>

	PR middle-end/103181
	* tree-eh.c (operation_could_trap_helper_p): Properly
	check vector constants for a zero element for integer
	division.  Separate floating point and integer division code.

	* gcc.dg/torture/pr103181.c: New testcase.
---
 gcc/testsuite/gcc.dg/torture/pr103181.c | 24 +++++++++++++++++++++++
 gcc/tree-eh.c                           | 26 ++++++++++++++++++++-----
 2 files changed, 45 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr103181.c
  

Patch

diff --git a/gcc/testsuite/gcc.dg/torture/pr103181.c b/gcc/testsuite/gcc.dg/torture/pr103181.c
new file mode 100644
index 00000000000..6bc705ab52e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr103181.c
@@ -0,0 +1,24 @@ 
+/* { dg-do run } */
+
+typedef unsigned char __attribute__((__vector_size__ (2))) U;
+typedef unsigned short S;
+typedef unsigned int __attribute__((__vector_size__ (64))) V;
+
+V v;
+U a, b, c;
+
+U
+foo (S s)
+{
+  v += __builtin_bswap16 (s) || (S) (a / ((U){3, 0}));
+  return b + c;
+}
+
+int
+main (void)
+{
+  U x = foo (4);
+  if (x[0] || x[1])
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 3a09de95025..3eff07fc8fe 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2454,15 +2454,31 @@  operation_could_trap_helper_p (enum tree_code op,
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
     case TRUNC_MOD_EXPR:
-    case RDIV_EXPR:
-      if (honor_snans)
-	return true;
-      if (fp_operation)
-	return flag_trapping_math;
       if (!TREE_CONSTANT (divisor) || integer_zerop (divisor))
         return true;
+      if (TREE_CODE (divisor) == VECTOR_CST)
+	{
+	  /* Inspired by initializer_each_zero_or_onep.  */
+	  unsigned HOST_WIDE_INT nelts = vector_cst_encoded_nelts (divisor);
+	  if (VECTOR_CST_STEPPED_P (divisor)
+	      && !TYPE_VECTOR_SUBPARTS (TREE_TYPE (divisor))
+		    .is_constant (&nelts))
+	    return true;
+	  for (unsigned int i = 0; i < nelts; ++i)
+	    {
+	      tree elt = vector_cst_elt (divisor, i);
+	      if (integer_zerop (elt))
+		return true;
+	    }
+	}
       return false;
 
+    case RDIV_EXPR:
+      if (honor_snans)
+	return true;
+      gcc_assert (fp_operation);
+      return flag_trapping_math;
+
     case LT_EXPR:
     case LE_EXPR:
     case GT_EXPR: