diff mbox

Fix simplify-rtx.c ICE with vector float (not (neg)) (PR rtl-optimization/80385)

Message ID 20170411112043.GO1809@tucnak
State New
Headers show

Commit Message

Jakub Jelinek April 11, 2017, 11:20 a.m. UTC
Hi!

The x86 intrinsics allow andnot on MODE_VECTOR_FLOAT modes, but
such modes have NULL CONSTM1_RTX and are not appropriate for the
transformation anyway.

The following patch fixes that, ok if bootstrap/regtest passes?
Or would you prefer to replace the
&& CONSTM1_RTX (mode)
check with e.g.
&& (MODE_CLASS (mode) == MODE_INT
    || MODE_CLASS (mode) == MODE_VECTOR_INT)
(dunno if we want to handle that way also partial int modes or not,
no experience with those)?
The transformation relies on 2's complement, so certainly doesn't apply
to floating modes (scalar or vector), but even MODE_COMPLEX_INT doesn't
have CONSTM1_RTX.

2017-04-11  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/80385
	* simplify-rtx.c (simplify_unary_operation_1): Don't transform
	(not (neg X)) into (plus X -1) for complex or non-integral modes.

	* g++.dg/opt/pr80385.C: New test.


	Jakub

Comments

Richard Biener April 11, 2017, 11:37 a.m. UTC | #1
On Tue, 11 Apr 2017, Jakub Jelinek wrote:

> Hi!
> 
> The x86 intrinsics allow andnot on MODE_VECTOR_FLOAT modes, but
> such modes have NULL CONSTM1_RTX and are not appropriate for the
> transformation anyway.
> 
> The following patch fixes that, ok if bootstrap/regtest passes?
> Or would you prefer to replace the
> && CONSTM1_RTX (mode)
> check with e.g.
> && (MODE_CLASS (mode) == MODE_INT
>     || MODE_CLASS (mode) == MODE_VECTOR_INT)
> (dunno if we want to handle that way also partial int modes or not,
> no experience with those)?
> The transformation relies on 2's complement, so certainly doesn't apply
> to floating modes (scalar or vector), but even MODE_COMPLEX_INT doesn't
> have CONSTM1_RTX.

I think the patch is ok as-is.

Richard.

> 2017-04-11  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR rtl-optimization/80385
> 	* simplify-rtx.c (simplify_unary_operation_1): Don't transform
> 	(not (neg X)) into (plus X -1) for complex or non-integral modes.
> 
> 	* g++.dg/opt/pr80385.C: New test.
> 
> --- gcc/simplify-rtx.c.jj	2017-04-04 07:32:57.000000000 +0200
> +++ gcc/simplify-rtx.c	2017-04-11 12:26:05.550834274 +0200
> @@ -932,8 +932,10 @@ simplify_unary_operation_1 (enum rtx_cod
>  	  && XEXP (op, 1) == constm1_rtx)
>  	return simplify_gen_unary (NEG, mode, XEXP (op, 0), mode);
>  
> -      /* Similarly, (not (neg X)) is (plus X -1).  */
> -      if (GET_CODE (op) == NEG)
> +      /* Similarly, (not (neg X)) is (plus X -1).  Only do this for
> +	 modes that have CONSTM1_RTX, i.e. MODE_INT, MODE_PARTIAL_INT
> +	 and MODE_VECTOR_INT.  */
> +      if (GET_CODE (op) == NEG && CONSTM1_RTX (mode))
>  	return simplify_gen_binary (PLUS, mode, XEXP (op, 0),
>  				    CONSTM1_RTX (mode));
>  
> --- gcc/testsuite/g++.dg/opt/pr80385.C.jj	2017-04-11 12:36:36.421806796 +0200
> +++ gcc/testsuite/g++.dg/opt/pr80385.C	2017-04-11 12:36:11.000000000 +0200
> @@ -0,0 +1,14 @@
> +// PR rtl-optimization/80385
> +// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
> +// { dg-options "-Ofast -msse2" }
> +
> +#include <x86intrin.h>
> +
> +__m128 a, e;
> +struct A { __m128 b; A (); A (__m128 x) : b(x) {} };
> +A operator+ (A, A);
> +A operator- (A) { __m128 c = -a; return c; }
> +A foo (A x) { __m128 d = x.b; return _mm_andnot_ps (d, e); }
> +struct B { A n[1]; };
> +void bar (B x) { A f = foo (x.n[0]); A g = f + A (); }
> +void baz () { B h; B i; A j; i.n[0] = -j; h = i; B k = h; bar (k); }
> 
> 	Jakub
> 
>
Richard Sandiford April 14, 2017, 2:15 p.m. UTC | #2
Jakub Jelinek <jakub@redhat.com> writes:
> Hi!
>
> The x86 intrinsics allow andnot on MODE_VECTOR_FLOAT modes, but
> such modes have NULL CONSTM1_RTX and are not appropriate for the
> transformation anyway.
>
> The following patch fixes that, ok if bootstrap/regtest passes?
> Or would you prefer to replace the
> && CONSTM1_RTX (mode)
> check with e.g.
> && (MODE_CLASS (mode) == MODE_INT
>     || MODE_CLASS (mode) == MODE_VECTOR_INT)
> (dunno if we want to handle that way also partial int modes or not,
> no experience with those)?
> The transformation relies on 2's complement, so certainly doesn't apply
> to floating modes (scalar or vector), but even MODE_COMPLEX_INT doesn't
> have CONSTM1_RTX.

Is it valid to have (not: ...) of a floating-point mode?  I thought
it had to have an integer mode.

FWIW, in the SVE patches, we deliberately used unspecs for floating-point
logic to avoid this.

Thanks,
Richard
diff mbox

Patch

--- gcc/simplify-rtx.c.jj	2017-04-04 07:32:57.000000000 +0200
+++ gcc/simplify-rtx.c	2017-04-11 12:26:05.550834274 +0200
@@ -932,8 +932,10 @@  simplify_unary_operation_1 (enum rtx_cod
 	  && XEXP (op, 1) == constm1_rtx)
 	return simplify_gen_unary (NEG, mode, XEXP (op, 0), mode);
 
-      /* Similarly, (not (neg X)) is (plus X -1).  */
-      if (GET_CODE (op) == NEG)
+      /* Similarly, (not (neg X)) is (plus X -1).  Only do this for
+	 modes that have CONSTM1_RTX, i.e. MODE_INT, MODE_PARTIAL_INT
+	 and MODE_VECTOR_INT.  */
+      if (GET_CODE (op) == NEG && CONSTM1_RTX (mode))
 	return simplify_gen_binary (PLUS, mode, XEXP (op, 0),
 				    CONSTM1_RTX (mode));
 
--- gcc/testsuite/g++.dg/opt/pr80385.C.jj	2017-04-11 12:36:36.421806796 +0200
+++ gcc/testsuite/g++.dg/opt/pr80385.C	2017-04-11 12:36:11.000000000 +0200
@@ -0,0 +1,14 @@ 
+// PR rtl-optimization/80385
+// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
+// { dg-options "-Ofast -msse2" }
+
+#include <x86intrin.h>
+
+__m128 a, e;
+struct A { __m128 b; A (); A (__m128 x) : b(x) {} };
+A operator+ (A, A);
+A operator- (A) { __m128 c = -a; return c; }
+A foo (A x) { __m128 d = x.b; return _mm_andnot_ps (d, e); }
+struct B { A n[1]; };
+void bar (B x) { A f = foo (x.n[0]); A g = f + A (); }
+void baz () { B h; B i; A j; i.n[0] = -j; h = i; B k = h; bar (k); }