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 <rguent...@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 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: -- 2.31.1