Hi! If any of the operands of the UBSAN_{ADD,SUB,MUL}_OVERFLOW ifn with vector operand is a uniform vector, expanding it as VCE on the VECTOR_CST followed by ARRAY_REF with variable index in the loop is unnecessarily expensive and nothing fixes it afterwards. This works around ICE on s390 at least for the uniform vectors.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-03-07 Jakub Jelinek <ja...@redhat.com> PR sanitizer/79904 * internal-fn.c (expand_vector_ubsan_overflow): If arg0 or arg1 is a uniform vector, use uniform_vector_p return value instead of building ARRAY_REF on folded VIEW_CONVERT_EXPR to array type. * gcc.dg/ubsan/pr79904.c: New test. --- gcc/internal-fn.c.jj 2017-02-23 08:48:40.000000000 +0100 +++ gcc/internal-fn.c 2017-03-07 11:55:56.261465702 +0100 @@ -1869,12 +1869,20 @@ expand_vector_ubsan_overflow (location_t if (cnt > 4) { tree atype = build_array_type_nelts (eltype, cnt); - op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0); - op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv, - NULL_TREE, NULL_TREE); - op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1); - op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv, - NULL_TREE, NULL_TREE); + op0 = uniform_vector_p (arg0); + if (op0 == NULL_TREE) + { + op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0); + op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv, + NULL_TREE, NULL_TREE); + } + op1 = uniform_vector_p (arg1); + if (op1 == NULL_TREE) + { + op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1); + op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv, + NULL_TREE, NULL_TREE); + } if (resv) { res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv); --- gcc/testsuite/gcc.dg/ubsan/pr79904.c.jj 2017-03-07 11:58:53.266120958 +0100 +++ gcc/testsuite/gcc.dg/ubsan/pr79904.c 2017-03-07 11:58:46.000000000 +0100 @@ -0,0 +1,11 @@ +/* PR sanitizer/79904 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=signed-integer-overflow -Wno-psabi" } */ + +typedef signed char V __attribute__((vector_size (8))); + +void +foo (V *a) +{ + *a = *a * 3; +} Jakub