With recent SLP vectorization patches I see RISC-V divison by zero for gfortran.dg/matmul_10.f90 and others in get_group_load_store_type which does
&& can_div_trunc_p (group_size * LOOP_VINFO_VECT_FACTOR (loop_vinfo) - gap, nunits, &tem, &remain) && (known_eq (remain, 0u) || (constant_multiple_p (nunits, remain, &num) && (vector_vector_composition_type (vectype, num, &half_vtype) != NULL_TREE)))) overrun_p = false; where for [2, 2] / [0, 2] the condition doesn't reflect what we are trying to test - that, when remain is zero or, when non-zero, nunits is a multiple of remain, we can avoid touching a gap via loading smaller pieces and vector composition. Changing known_eq to maybe_eq wouldn't be correct I think since for example if it were [0, 4] then we cannot load smaller parts. Note we know that remain is in [0, nunits - 1] given we compute it as X % nunits so maybe we can indeed use maybe_eq (remain, 0u) here in this particular case? The following adds constant_multiple_if_divisor_nonzero_p to express the intent of no interest in the 'multiple' value for the case B is zero. Bootstrapped and tested on x86_64-unknown-linux-gnu. Is the reasoning that maybe_eq is "safe" sound in this particular case? I think we should avoid adding constant_multiple_if_divisor_nonzero_p if not absolutely necessary. Thanks, Richard. * poly-int.h (constant_multiple_if_divisor_nonzero_p): New. * tree-vect-stmts.cc (get_group_load_store_type): Use it. --- gcc/poly-int.h | 45 ++++++++++++++++++++++++++++++++++++++++++ gcc/tree-vect-stmts.cc | 3 ++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/gcc/poly-int.h b/gcc/poly-int.h index 94708165961..29337513eb8 100644 --- a/gcc/poly-int.h +++ b/gcc/poly-int.h @@ -1986,6 +1986,51 @@ constant_multiple_p (const poly_int<N, Ca> &a, return true; } +/* Return true if A is a constant multiple of B, storing the + multiple in *MULTIPLE if so. The case of B being zero is + excluded but it shall not be known equal to zero. */ + +template<unsigned int N, typename Ca, typename Cb, typename Cm> +inline bool +constant_multiple_if_divisor_nonzero_p (const poly_int<N, Ca> &a, + const poly_int<N, Cb> &b, Cm *multiple) +{ + typedef POLY_CAST (Ca, Cb) NCa; + typedef POLY_CAST (Cb, Ca) NCb; + typedef POLY_INT_TYPE (Ca) ICa; + typedef POLY_INT_TYPE (Cb) ICb; + typedef POLY_BINARY_COEFF (Ca, Cb) C; + + C r = 0; + if (b.coeffs[0] != ICb (0)) + { + if (NCa (a.coeffs[0]) % NCb (b.coeffs[0]) != 0) + return false; + r = NCa (a.coeffs[0]) / NCb (b.coeffs[0]); + } + for (unsigned int i = 1; i < N; ++i) + if (b.coeffs[i] == ICb (0)) + { + if (a.coeffs[i] != ICa (0)) + return false; + } + else + { + if (NCa (a.coeffs[i]) % NCb (b.coeffs[i]) != 0) + return false; + if (r == 0) + r = NCa (a.coeffs[i]) / NCb (b.coeffs[i]); + else if (NCa (a.coeffs[i]) / NCb (b.coeffs[i]) != r) + return false; + } + + if (r == 0) + return false; + + *multiple = r; + return true; +} + /* Return true if A is a constant multiple of B. */ template<unsigned int N, typename Ca, typename Cb> diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index f8bb637342e..2641833b3aa 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -2135,7 +2135,8 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, * LOOP_VINFO_VECT_FACTOR (loop_vinfo) - gap, nunits, &tem, &remain) && (known_eq (remain, 0u) - || (constant_multiple_p (nunits, remain, &num) + || (constant_multiple_if_divisor_nonzero_p (nunits, remain, + &num) && (vector_vector_composition_type (vectype, num, &half_vtype) != NULL_TREE)))) -- 2.43.0