middle-end/103181 - fix operation_could_trap_p for vector division
Commit Message
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
new file mode 100644
@@ -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;
+}
@@ -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: