optabs: Don't create pseudos in prepare_cmp_insn when not allowed [PR102478]

Message ID 20220121070019.GA2646553@tucnak
State New
Headers
Series optabs: Don't create pseudos in prepare_cmp_insn when not allowed [PR102478] |

Commit Message

Jakub Jelinek Jan. 21, 2022, 7 a.m. UTC
  Hi!

cond traps can be created during ce3 after reload (and e.g. PR103028
recently fixed some ce3 cond trap related bug, so I think often that
works fine and we shouldn't disable cond traps after RA altogether),
but it calls prepare_cmp_insn.  This function can fail, so I don't
see why we couldn't make it work after RA (in most cases it already
just works).  The first hunk is just an optimization which doesn't
make sense after RA, so I've guarded it with can_create_pseudo_p.
The second hunk is just a theoretical case, I don't have a testcase for it.
prepare_cmp_insn has some other spots that can create pseudos, like when
both operands have VOIDmode, or when it is BLKmode comparison, or
not OPTAB_DIRECT, but I think none of that applies to ce3, we punt on
BLKmode earlier, use OPTAB_DIRECT and shouldn't be comparing two
VOIDmode CONST_INTs.

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

2022-01-21  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/102478
	* optabs.cc (prepare_cmp_insn): If !can_create_pseudo_p (), don't
	force_reg constants and for -fnon-call-exceptions fail if copy_to_reg
	would be needed.

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


	Jakub
  

Comments

Richard Biener Jan. 21, 2022, 7:17 a.m. UTC | #1
On Fri, 21 Jan 2022, Jakub Jelinek wrote:

> Hi!
> 
> cond traps can be created during ce3 after reload (and e.g. PR103028
> recently fixed some ce3 cond trap related bug, so I think often that
> works fine and we shouldn't disable cond traps after RA altogether),
> but it calls prepare_cmp_insn.  This function can fail, so I don't
> see why we couldn't make it work after RA (in most cases it already
> just works).  The first hunk is just an optimization which doesn't
> make sense after RA, so I've guarded it with can_create_pseudo_p.
> The second hunk is just a theoretical case, I don't have a testcase for it.
> prepare_cmp_insn has some other spots that can create pseudos, like when
> both operands have VOIDmode, or when it is BLKmode comparison, or
> not OPTAB_DIRECT, but I think none of that applies to ce3, we punt on
> BLKmode earlier, use OPTAB_DIRECT and shouldn't be comparing two
> VOIDmode CONST_INTs.
> 
> Bootstrapped/regtested on x86_64-linux, i686-linux and powerpc64le-linux,
> ok for trunk?

OK.

Richard.

> 2022-01-21  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR rtl-optimization/102478
> 	* optabs.cc (prepare_cmp_insn): If !can_create_pseudo_p (), don't
> 	force_reg constants and for -fnon-call-exceptions fail if copy_to_reg
> 	would be needed.
> 
> 	* gcc.dg/pr102478.c: New test.
> 
> --- gcc/optabs.cc.jj	2022-01-20 11:30:45.586578023 +0100
> +++ gcc/optabs.cc	2022-01-20 16:54:35.439409550 +0100
> @@ -4398,12 +4398,14 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx
>    /* If we are optimizing, force expensive constants into a register.  */
>    if (CONSTANT_P (x) && optimize
>        && (rtx_cost (x, mode, COMPARE, 0, optimize_insn_for_speed_p ())
> -          > COSTS_N_INSNS (1)))
> +          > COSTS_N_INSNS (1))
> +      && can_create_pseudo_p ())
>      x = force_reg (mode, x);
>  
>    if (CONSTANT_P (y) && optimize
>        && (rtx_cost (y, mode, COMPARE, 1, optimize_insn_for_speed_p ())
> -          > COSTS_N_INSNS (1)))
> +          > COSTS_N_INSNS (1))
> +      && can_create_pseudo_p ())
>      y = force_reg (mode, y);
>  
>    /* Don't let both operands fail to indicate the mode.  */
> @@ -4472,6 +4474,8 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx
>       compare and branch in different basic blocks.  */
>    if (cfun->can_throw_non_call_exceptions)
>      {
> +      if (!can_create_pseudo_p () && (may_trap_p (x) || may_trap_p (y)))
> +	goto fail;
>        if (may_trap_p (x))
>  	x = copy_to_reg (x);
>        if (may_trap_p (y))
> --- gcc/testsuite/gcc.dg/pr102478.c.jj	2022-01-20 17:00:52.220192056 +0100
> +++ gcc/testsuite/gcc.dg/pr102478.c	2022-01-20 17:00:30.917487026 +0100
> @@ -0,0 +1,29 @@
> +/* PR rtl-optimization/102478 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fno-if-conversion -Wno-div-by-zero" } */
> +
> +unsigned a, b, c;
> +
> +void
> +foo (void)
> +{
> +  c |= __builtin_expect (65535 / a, 0) && 0 / 0;
> +  b = 0;
> +}
> +
> +void
> +bar (void)
> +{
> +  if (a <= 65535)
> +    __builtin_trap ();
> +  b = 0;
> +}
> +
> +void
> +baz (void)
> +{
> +  if (a > 65535)
> +    b = 0;
> +  else
> +    __builtin_trap ();
> +}
> 
> 	Jakub
> 
>
  

Patch

--- gcc/optabs.cc.jj	2022-01-20 11:30:45.586578023 +0100
+++ gcc/optabs.cc	2022-01-20 16:54:35.439409550 +0100
@@ -4398,12 +4398,14 @@  prepare_cmp_insn (rtx x, rtx y, enum rtx
   /* If we are optimizing, force expensive constants into a register.  */
   if (CONSTANT_P (x) && optimize
       && (rtx_cost (x, mode, COMPARE, 0, optimize_insn_for_speed_p ())
-          > COSTS_N_INSNS (1)))
+          > COSTS_N_INSNS (1))
+      && can_create_pseudo_p ())
     x = force_reg (mode, x);
 
   if (CONSTANT_P (y) && optimize
       && (rtx_cost (y, mode, COMPARE, 1, optimize_insn_for_speed_p ())
-          > COSTS_N_INSNS (1)))
+          > COSTS_N_INSNS (1))
+      && can_create_pseudo_p ())
     y = force_reg (mode, y);
 
   /* Don't let both operands fail to indicate the mode.  */
@@ -4472,6 +4474,8 @@  prepare_cmp_insn (rtx x, rtx y, enum rtx
      compare and branch in different basic blocks.  */
   if (cfun->can_throw_non_call_exceptions)
     {
+      if (!can_create_pseudo_p () && (may_trap_p (x) || may_trap_p (y)))
+	goto fail;
       if (may_trap_p (x))
 	x = copy_to_reg (x);
       if (may_trap_p (y))
--- gcc/testsuite/gcc.dg/pr102478.c.jj	2022-01-20 17:00:52.220192056 +0100
+++ gcc/testsuite/gcc.dg/pr102478.c	2022-01-20 17:00:30.917487026 +0100
@@ -0,0 +1,29 @@ 
+/* PR rtl-optimization/102478 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-if-conversion -Wno-div-by-zero" } */
+
+unsigned a, b, c;
+
+void
+foo (void)
+{
+  c |= __builtin_expect (65535 / a, 0) && 0 / 0;
+  b = 0;
+}
+
+void
+bar (void)
+{
+  if (a <= 65535)
+    __builtin_trap ();
+  b = 0;
+}
+
+void
+baz (void)
+{
+  if (a > 65535)
+    b = 0;
+  else
+    __builtin_trap ();
+}