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

Reply via email to