[RTL-ifcvt] PR rtl-optimization/68841: Make sure one basic block doesn't clobber...
authorKyrylo Tkachov <ktkachov@gcc.gnu.org>
Mon, 11 Jan 2016 12:13:50 +0000 (12:13 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Mon, 11 Jan 2016 12:13:50 +0000 (12:13 +0000)
        PR rtl-optimization/68841
        * ifcvt.c (struct noce_if_info): Add orig_x field.
        (bbs_ok_for_cmove_arith): Add to_rename parameter.
        Don't record conflicts on to_rename if it's present.
        Allow memory destinations in sets.
        (noce_try_cmove_arith): Call bbs_ok_for_cmove_arith even on simple
        blocks, passing orig_x to the checks.
        (noce_process_if_block): Set if_info->orig_x appropriately.

        * gcc.dg/pr68841.c: New test.
        * gcc.c-torture/execute/pr68841.c: New test.

From-SVN: r232223

gcc/ChangeLog
gcc/ifcvt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr68841.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr68841.c [new file with mode: 0644]

index 5124d69..c910e89 100644 (file)
@@ -1,3 +1,15 @@
+2016-01-11  Bernd Schmidt  <bschmidt@redhat.com>
+            Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       PR rtl-optimization/68841
+       * ifcvt.c (struct noce_if_info): Add orig_x field.
+       (bbs_ok_for_cmove_arith): Add to_rename parameter.
+       Don't record conflicts on to_rename if it's present.
+       Allow memory destinations in sets.
+       (noce_try_cmove_arith): Call bbs_ok_for_cmove_arith even on simple
+       blocks, passing orig_x to the checks.
+       (noce_process_if_block): Set if_info->orig_x appropriately.
+
 2016-01-11  Tom de Vries  <tom@codesourcery.com>
 
        PR tree-optimization/69069
index 723ea3e..7d94e75 100644 (file)
@@ -793,6 +793,9 @@ struct noce_if_info
   /* The SET_DEST of INSN_A.  */
   rtx x;
 
+  /* The original set destination that the THEN and ELSE basic blocks finally
+     write their result to.  */
+  rtx orig_x;
   /* True if this if block is not canonical.  In the canonical form of
      if blocks, the THEN_BB is the block reached via the fallthru edge
      from TEST_BB.  For the noce transformations, we allow the symmetric
@@ -1867,11 +1870,13 @@ insn_valid_noce_process_p (rtx_insn *insn, rtx cc)
 }
 
 
-/* Return true iff the registers that the insns in BB_A set do not
-   get used in BB_B.  */
+/* Return true iff the registers that the insns in BB_A set do not get
+   used in BB_B.  If TO_RENAME is non-NULL then it is a location that will be
+   renamed later by the caller and so conflicts on it should be ignored
+   in this function.  */
 
 static bool
-bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b)
+bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
 {
   rtx_insn *a_insn;
   bitmap bba_sets = BITMAP_ALLOC (&reg_obstack);
@@ -1891,10 +1896,10 @@ bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b)
          BITMAP_FREE (bba_sets);
          return false;
        }
-
       /* Record all registers that BB_A sets.  */
       FOR_EACH_INSN_DEF (def, a_insn)
-       bitmap_set_bit (bba_sets, DF_REF_REGNO (def));
+       if (!(to_rename && DF_REF_REG (def) == to_rename))
+         bitmap_set_bit (bba_sets, DF_REF_REGNO (def));
     }
 
   rtx_insn *b_insn;
@@ -1913,8 +1918,15 @@ bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b)
        }
 
       /* Make sure this is a REG and not some instance
-        of ZERO_EXTRACT or SUBREG or other dangerous stuff.  */
-      if (!REG_P (SET_DEST (sset_b)))
+        of ZERO_EXTRACT or SUBREG or other dangerous stuff.
+        If we have a memory destination then we have a pair of simple
+        basic blocks performing an operation of the form [addr] = c ? a : b.
+        bb_valid_for_noce_process_p will have ensured that these are
+        the only stores present.  In that case [addr] should be the location
+        to be renamed.  Assert that the callers set this up properly.  */
+      if (MEM_P (SET_DEST (sset_b)))
+       gcc_assert (rtx_equal_p (SET_DEST (sset_b), to_rename));
+      else if (!REG_P (SET_DEST (sset_b)))
        {
          BITMAP_FREE (bba_sets);
          return false;
@@ -2083,9 +2095,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
        }
     }
 
-  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)))
+  if (then_bb && else_bb
+      && (!bbs_ok_for_cmove_arith (then_bb, else_bb,  if_info->orig_x)
+         || !bbs_ok_for_cmove_arith (else_bb, then_bb,  if_info->orig_x)))
     return FALSE;
 
   start_sequence ();
@@ -3403,6 +3415,7 @@ noce_process_if_block (struct noce_if_info *if_info)
   /* Only operate on register destinations, and even then avoid extending
      the lifetime of hard registers on small register class machines.  */
   orig_x = x;
+  if_info->orig_x = orig_x;
   if (!REG_P (x)
       || (HARD_REGISTER_P (x)
          && targetm.small_register_classes_for_mode_p (GET_MODE (x))))
index c1ae6ef..8157e43 100644 (file)
@@ -1,3 +1,9 @@
+2016-01-11  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       PR rtl-optimization/68841
+       * gcc.dg/pr68841.c: New test.
+       * gcc.c-torture/execute/pr68841.c: New test.
+
 2016-01-11  Yuri Rumyantsev  <ysrumyan@gmail.com>
 
        PR rtl-optimization/68920
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr68841.c b/gcc/testsuite/gcc.c-torture/execute/pr68841.c
new file mode 100644 (file)
index 0000000..15a27e7
--- /dev/null
@@ -0,0 +1,31 @@
+static inline int
+foo (int *x, int y)
+{
+  int z = *x;
+  while (y > z)
+    z *= 2;
+  return z;
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 1; i < 17; i++)
+    {
+      int j;
+      int k;
+      j = foo (&i, 7);
+      if (i >= 7)
+       k = i;
+      else if (i >= 4)
+       k = 8 + (i - 4) * 2;
+      else if (i == 3)
+       k = 12;
+      else
+       k = 8;
+      if (j != k)
+       __builtin_abort ();
+    }
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr68841.c b/gcc/testsuite/gcc.dg/pr68841.c
new file mode 100644 (file)
index 0000000..470048c
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-Og -fif-conversion -flive-range-shrinkage -fpeel-loops -frerun-cse-after-loop" } */
+
+static inline int
+foo (int *x, int y)
+{
+  int z = *x;
+  while (y > z)
+    z *= 2;
+  return z;
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 1; i < 17; i++)
+    {
+      int j;
+      int k;
+      j = foo (&i, 7);
+      if (i >= 7)
+       k = i;
+      else if (i >= 4)
+       k = 8 + (i - 4) * 2;
+      else if (i == 3)
+       k = 12;
+      else
+       k = 8;
+      if (j != k)
+       __builtin_abort ();
+    }
+  return 0;
+}