Hi! In rtl.texi we say: @findex const_vector @item (const_vector:@var{m} [@var{x0} @var{x1} @dots{}]) Represents a vector constant. The square brackets stand for the vector containing the constant elements. @var{x0}, @var{x1} and so on are the @code{const_int}, @code{const_wide_int}, @code{const_double} or @code{const_fixed} elements. and it is a very reasonable requirement. simplify_const_{unary,binary}_operation can violate that though, because the recursion can return also other expressions, like in this case a (mult (const_double) (const_double)) that can't be simplified because of -frounding-math. We need to punt on those.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-12-20 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/82973 * simplify-rtx.c (simplify_const_unary_operation): Don't optimize into CONST_VECTOR if some element isn't simplified into CONST_{,WIDE_}INT, CONST_DOUBLE or CONST_FIXED. (simplify_const_binary_operation): Likewise. Use CONST_FIXED_P macro instead of GET_CODE == CONST_FIXED. (simplify_subreg): Use CONST_FIXED_P macro instead of GET_CODE == CONST_FIXED. * gfortran.dg/pr82973.f90: New test. --- gcc/simplify-rtx.c.jj 2017-12-19 18:09:05.000000000 +0100 +++ gcc/simplify-rtx.c 2017-12-20 18:29:55.190089315 +0100 @@ -1776,7 +1776,12 @@ simplify_const_unary_operation (enum rtx rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode), CONST_VECTOR_ELT (op, i), GET_MODE_INNER (opmode)); - if (!x) + /* Only CONST_INT, CONST_WIDE_INT, CONST_DOUBLE or CONST_FIXED + is valid inside of CONST_VECTOR. */ + if (!x + || !(CONST_SCALAR_INT_P (x) + || CONST_DOUBLE_AS_FLOAT_P (x) + || CONST_FIXED_P (x))) return 0; RTVEC_ELT (v, i) = x; } @@ -4006,7 +4011,12 @@ simplify_const_binary_operation (enum rt rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode), CONST_VECTOR_ELT (op0, i), CONST_VECTOR_ELT (op1, i)); - if (!x) + /* Only CONST_INT, CONST_WIDE_INT, CONST_DOUBLE or CONST_FIXED + is valid inside of CONST_VECTOR. */ + if (!x + || !(CONST_SCALAR_INT_P (x) + || CONST_DOUBLE_AS_FLOAT_P (x) + || CONST_FIXED_P (x))) return 0; RTVEC_ELT (v, i) = x; } @@ -4017,11 +4027,11 @@ simplify_const_binary_operation (enum rt if (VECTOR_MODE_P (mode) && code == VEC_CONCAT && (CONST_SCALAR_INT_P (op0) - || GET_CODE (op0) == CONST_FIXED + || CONST_FIXED_P (op0) || CONST_DOUBLE_AS_FLOAT_P (op0)) && (CONST_SCALAR_INT_P (op1) || CONST_DOUBLE_AS_FLOAT_P (op1) - || GET_CODE (op1) == CONST_FIXED)) + || CONST_FIXED_P (op1))) { unsigned n_elts = GET_MODE_NUNITS (mode); rtvec v = rtvec_alloc (n_elts); @@ -6193,7 +6203,7 @@ simplify_subreg (machine_mode outermode, if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op) - || GET_CODE (op) == CONST_FIXED + || CONST_FIXED_P (op) || GET_CODE (op) == CONST_VECTOR) { /* simplify_immed_subreg deconstructs OP into bytes and constructs --- gcc/testsuite/gfortran.dg/pr82973.f90.jj 2017-12-20 18:53:14.392540473 +0100 +++ gcc/testsuite/gfortran.dg/pr82973.f90 2017-12-20 18:52:47.000000000 +0100 @@ -0,0 +1,31 @@ +! PR rtl-optimization/82973 +! { dg-do compile } +! { dg-options "-Ofast -frounding-math" } + +program pr82973 + integer, parameter :: n=16 + real, dimension(n) :: ar, br, modulo_result, floor_result + integer, dimension(n) :: ai, bi , imodulo_result, ifloor_result + ai(1:4) = 5 + ai(5:8) = -5 + ai(9:12) = 1 + ai(13:16) = -1 + bi(1:4) = (/ 3,-3, 1, -1/) + bi(5:8) = bi(1:4) + bi(9:12) = bi(1:4) + bi(13:16) = bi(1:4) + ar = ai + br = bi + modulo_result = modulo(ar,br) + imodulo_result = modulo(ai,bi) + floor_result = ar-floor(ar/br)*br + ifloor_result = nint(real(ai-floor(real(ai)/real(bi))*bi)) + do i=1,n + if (modulo_result(i) /= floor_result(i)) then + call abort() + end if + if (imodulo_result(i) /= ifloor_result(i)) then + call abort () + end if + end do +end program pr82973 Jakub