diff mbox

Fix up simplify_truncation (PR rtl-optimization/56494)

Message ID 20130304210128.GR12913@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek March 4, 2013, 9:01 p.m. UTC
Hi!

Optimizing (truncate:A (subreg:B (truncate:C X) 0)) into
(truncate:A X) is wrong if C mode is narrower than A mode.
The following patch fixes that and simplifies it into
(subreg:A (truncate:C X 0)) instead.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2013-03-04  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/56494
	* simplify-rtx.c (simplify_truncation): Don't optimize
	(truncate:A (subreg:B (truncate:C X) 0)) into (truncate:A X)
	if C is narrower than A.  If subreg is paradoxical, optimize
	it into (subreg:A (truncate:C X) 0) instead.

	* gcc.dg/pr56494.c: New test.


	Jakub

Comments

Richard Sandiford March 4, 2013, 9:08 p.m. UTC | #1
[Sorry Jakub, mid-air collision.  I just posted this comment to the PR.]

Jakub Jelinek <jakub@redhat.com> writes:
> Optimizing (truncate:A (subreg:B (truncate:C X) 0)) into
> (truncate:A X) is wrong if C mode is narrower than A mode.
> The following patch fixes that and simplifies it into
> (subreg:A (truncate:C X 0)) instead.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Thanks for the fix.  Looks good to me FWIW.  However...

> --- gcc/simplify-rtx.c.jj	2013-02-12 11:23:37.000000000 +0100
> +++ gcc/simplify-rtx.c	2013-03-04 11:32:44.111721542 +0100
> @@ -757,8 +757,18 @@ simplify_truncation (enum machine_mode m
>        && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op)))
>        && GET_CODE (SUBREG_REG (op)) == TRUNCATE
>        && subreg_lowpart_p (op))
> -    return simplify_gen_unary (TRUNCATE, mode, XEXP (SUBREG_REG (op), 0),
> -			       GET_MODE (XEXP (SUBREG_REG (op), 0)));
> +    {
> +      rtx inner = XEXP (SUBREG_REG (op), 0);
> +      if (GET_MODE_PRECISION (mode)
> +	  <= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))))
> +	return simplify_gen_unary (TRUNCATE, mode, inner, GET_MODE (inner));
> +      /* If subreg above is paradoxical and C is narrower
> +	 than A, return (subreg:A (truncate:C X) 0).  */
> +      if (GET_MODE_PRECISION (op_mode)
> +	  > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))))
> +	return simplify_gen_subreg (mode, SUBREG_REG (op),
> +				    GET_MODE (SUBREG_REG (op)), 0);
> +    }

...truncations can't be to a narrower mode (already asserted at the top
of the function) so in some ways I think it would be clearer to have an
"if ... else" rather than two "if"s.

Richard
diff mbox

Patch

--- gcc/simplify-rtx.c.jj	2013-02-12 11:23:37.000000000 +0100
+++ gcc/simplify-rtx.c	2013-03-04 11:32:44.111721542 +0100
@@ -757,8 +757,18 @@  simplify_truncation (enum machine_mode m
       && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op)))
       && GET_CODE (SUBREG_REG (op)) == TRUNCATE
       && subreg_lowpart_p (op))
-    return simplify_gen_unary (TRUNCATE, mode, XEXP (SUBREG_REG (op), 0),
-			       GET_MODE (XEXP (SUBREG_REG (op), 0)));
+    {
+      rtx inner = XEXP (SUBREG_REG (op), 0);
+      if (GET_MODE_PRECISION (mode)
+	  <= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))))
+	return simplify_gen_unary (TRUNCATE, mode, inner, GET_MODE (inner));
+      /* If subreg above is paradoxical and C is narrower
+	 than A, return (subreg:A (truncate:C X) 0).  */
+      if (GET_MODE_PRECISION (op_mode)
+	  > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))))
+	return simplify_gen_subreg (mode, SUBREG_REG (op),
+				    GET_MODE (SUBREG_REG (op)), 0);
+    }
 
   /* (truncate:A (truncate:B X)) is (truncate:A X).  */
   if (GET_CODE (op) == TRUNCATE)
--- gcc/testsuite/gcc.dg/pr56494.c.jj	2013-03-04 11:37:16.285155928 +0100
+++ gcc/testsuite/gcc.dg/pr56494.c	2013-03-04 11:36:59.000000000 +0100
@@ -0,0 +1,13 @@ 
+/* PR rtl-optimization/56494 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftracer -w" } */
+
+char a;
+short b;
+void bar (int);
+
+void
+foo (void)
+{
+  bar ((!!b ? : (a *= a / 0)) >= (a = b));
+}