This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix vector handling in simplify-rtx.c (PR rtl-optimization/82973)


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  <jakub@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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]