diff mbox

[RTL-ifcvt] PR rtl-optimization/67465: Handle pairs of complex+simple blocks and empty blocks more gracefully

Message ID 55F197EB.3010404@arm.com
State New
Headers show

Commit Message

Kyrylo Tkachov Sept. 10, 2015, 2:47 p.m. UTC
On 10/09/15 12:43, Rainer Orth wrote:
> Hi Kyrill,
>
>> Rainer, could you please check that this patch still fixes the SPARC
>> regressions?
> unfortunately, it breaks sparc-sun-solaris2.10 bootstrap: compiling
> stage2 libiberty/regex.c FAILs:
>
>

Thanks for providing the preprocessed file.
I've reproduced and fixed the ICE in this version of the patch.
The problem was that I was taking the mode of x before the check
of whether a and b are MEMs, after which we would change x to an address_mode reg,
thus confusing emit_move_insn.

The fix is to take the mode of x and perform the can_conditionally_move_p check
after that transformation.

Bootstrapped and tested on aarch64 and x86_64.
The preprocessed regex.i that Rainer provided now compiles successfully for me
on a sparc-sun-solaris2.10 stage-1 cross-compiler.

Rainer, thanks for your help so far, could you please try out this patch?

Thanks,
Kyrill

2015-09-10  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

      PR rtl-optimization/67456
      PR rtl-optimization/67464
      PR rtl-optimization/67465
      PR rtl-optimization/67481
      * ifcvt.c (noce_try_cmove_arith): Bail out if cannot conditionally
      move in the mode of x.  Handle combination of complex and simple
      block pairs as well as the case when one is empty.

2015-09-10  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

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

Comments

Rainer Orth Sept. 11, 2015, 8:51 a.m. UTC | #1
Kyrill Tkachov <kyrylo.tkachov@arm.com> writes:

> On 10/09/15 12:43, Rainer Orth wrote:
>> Hi Kyrill,
>>
>>> Rainer, could you please check that this patch still fixes the SPARC
>>> regressions?
>> unfortunately, it breaks sparc-sun-solaris2.10 bootstrap: compiling
>> stage2 libiberty/regex.c FAILs:
>>
>>
>
> Thanks for providing the preprocessed file.
> I've reproduced and fixed the ICE in this version of the patch.
> The problem was that I was taking the mode of x before the check
> of whether a and b are MEMs, after which we would change x to an
> address_mode reg,
> thus confusing emit_move_insn.
>
> The fix is to take the mode of x and perform the can_conditionally_move_p check
> after that transformation.
>
> Bootstrapped and tested on aarch64 and x86_64.
> The preprocessed regex.i that Rainer provided now compiles successfully for me
> on a sparc-sun-solaris2.10 stage-1 cross-compiler.
>
> Rainer, thanks for your help so far, could you please try out this patch?

While bootstrap succeeds again, the testsuite regression in
gcc.c-torture/execute/20071216-1.c reoccured.

	Rainer
diff mbox

Patch

commit 90c12de20cdc8a8a5e81c25accc640ab517a3f7c
Author: Kyrylo Tkachov <kyrylo.tkachov@arm.com>
Date:   Mon Sep 7 14:58:01 2015 +0100

    [RTL-ifcvt] PR rtl-optimization/67465: Do not ifcvt complex blocks if the else block is empty

diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index d2f5b66..e708ac4 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -2043,6 +2043,11 @@  noce_try_cmove_arith (struct noce_if_info *if_info)
   insn_a = if_info->insn_a;
   insn_b = if_info->insn_b;
 
+  machine_mode x_mode = GET_MODE (x);
+
+  if (!can_conditionally_move_p (x_mode))
+    return FALSE;
+
   unsigned int then_cost;
   unsigned int else_cost;
   if (insn_a)
@@ -2079,13 +2084,32 @@  noce_try_cmove_arith (struct noce_if_info *if_info)
 	}
     }
 
-  if (!a_simple && then_bb && !b_simple && else_bb
+  if (then_bb && else_bb && !a_simple && !b_simple
       && (!bbs_ok_for_cmove_arith (then_bb, else_bb)
 	  || !bbs_ok_for_cmove_arith (else_bb, then_bb)))
     return FALSE;
 
   start_sequence ();
 
+  /* If one of the blocks is empty then the corresponding B or A value
+     came from the test block.  The non-empty complex block that we will
+     emit might clobber the register used by B or A, so move it to a pseudo
+     first.  */
+
+  if (b_simple || !else_bb)
+    {
+      rtx tmp_b = gen_reg_rtx (x_mode);
+      noce_emit_move_insn (tmp_b, b);
+      b = tmp_b;
+    }
+
+  if (a_simple || !then_bb)
+    {
+      rtx tmp_a = gen_reg_rtx (x_mode);
+      noce_emit_move_insn (tmp_a, a);
+      a = tmp_a;
+    }
+
   orig_a = a;
   orig_b = b;
 
diff --git a/gcc/testsuite/gcc.dg/pr67465.c b/gcc/testsuite/gcc.dg/pr67465.c
new file mode 100644
index 0000000..321fd38
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr67465.c
@@ -0,0 +1,53 @@ 
+/* { dg-do run } */
+/* { dg-options "-O3 -std=gnu99" } */
+
+int a, b, c, d, e, h;
+
+int
+fn1 (int p1)
+{
+  {
+    int g[2];
+    for (int i = 0; i < 1; i++)
+      g[i] = 0;
+    if (g[0] < c)
+      {
+	a = (unsigned) (1 ^ p1) % 2;
+	return 0;
+      }
+  }
+  return 0;
+}
+
+void
+fn2 ()
+{
+  for (h = 0; h < 1; h++)
+    {
+      for (int j = 0; j < 2; j++)
+	{
+	  for (b = 1; b; b = 0)
+	    a = 1;
+	  for (; b < 1; b++)
+	    ;
+	  if (e)
+	    continue;
+	  a = 2;
+	}
+      fn1 (h);
+      short k = -16;
+      d = k > a;
+    }
+}
+
+int
+main ()
+{
+  fn2 ();
+
+  if (a != 2)
+    __builtin_abort ();
+
+  return 0;
+}
+