[RTL-ifcvt] PR rtl-optimization/67465: Handle pairs of complex+simple blocks and...
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Mon, 28 Sep 2015 08:23:47 +0000 (08:23 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Mon, 28 Sep 2015 08:23:47 +0000 (08:23 +0000)
        PR rtl-optimization/67456
        PR rtl-optimization/67464
        PR rtl-optimization/67465
        * 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.

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

From-SVN: r228194

gcc/ChangeLog
gcc/ifcvt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr67465.c [new file with mode: 0644]

index da6022916d92e796fc7c4ad18887d8887f0b2e19..b3419b62f00ed3b17e38964879dac8d093bbea09 100644 (file)
@@ -1,3 +1,12 @@
+2015-09-28  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       PR rtl-optimization/67456
+       PR rtl-optimization/67464
+       PR rtl-optimization/67465
+       * 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-28  Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>
 
        * doc/gimple.texi: Update references to gimple_statement_base.
index 157a716ff6e8f2c80d8ef2acea815e8d59549260..2b63216b9dd4e0355a9eb9bcfb5997150b45f3cc 100644 (file)
@@ -1961,6 +1961,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)
@@ -1997,13 +2002,38 @@ 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);
+      /* Perform the simplest kind of set.  The register allocator
+        should remove it if it's not actually needed.  If this set is not
+        a valid insn (can happen on the is_mem path) then end_ifcvt_sequence
+        will cancel the whole sequence.  Don't try any of the fallback paths
+        from noce_emit_move_insn since we want this to be the simplest kind
+        of move.  */
+      emit_insn (gen_rtx_SET (tmp_b, b));
+      b = tmp_b;
+    }
+
+  if (a_simple || !then_bb)
+    {
+      rtx tmp_a = gen_reg_rtx (x_mode);
+      emit_insn (gen_rtx_SET (tmp_a, a));
+      a = tmp_a;
+    }
+
   orig_a = a;
   orig_b = b;
 
index f197512961a9a2a063364baeca8496eb7a2285ab..86049cadf5a18312e7665a08ca121ca4ffad2c42 100644 (file)
@@ -1,3 +1,10 @@
+2015-09-28  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       PR rtl-optimization/67456
+       PR rtl-optimization/67464
+       PR rtl-optimization/67465
+       * gcc.dg/pr67465.c: New test.
+
 2015-09-28  Tom de Vries  <tom@codesourcery.com>
 
        * gcc.dg/vect/pr62171.c: New test.
diff --git a/gcc/testsuite/gcc.dg/pr67465.c b/gcc/testsuite/gcc.dg/pr67465.c
new file mode 100644 (file)
index 0000000..321fd38
--- /dev/null
@@ -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;
+}
+