[PR 91579] Avoid creating redundant PHI nodes in tail-call pass
authorMartin Jambor <mjambor@suse.cz>
Fri, 30 Aug 2019 08:08:42 +0000 (10:08 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Fri, 30 Aug 2019 08:08:42 +0000 (10:08 +0200)
2019-08-30  Martin Jambor  <mjambor@suse.cz>

tree-optimization/91579
* tree-tailcall.c (tailr_arg_needs_copy): New variable.
(find_tail_calls): Allocate tailr_arg_needs_copy and set its bits as
appropriate.
(arg_needs_copy_p): Removed.
(eliminate_tail_call): Test tailr_arg_needs_copy instead of calling
arg_needs_copy_p.
(tree_optimize_tail_calls_1): Likewise.  Free tailr_arg_needs_copy.

testsuite/
* gcc.dg/tree-ssa/pr91579.c: New test.

From-SVN: r275062

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr91579.c [new file with mode: 0644]
gcc/tree-tailcall.c

index e09649766e321c0d9a6722abf4ce4925da01a021..57811a5f94618295c0b0dfc50ede5500cd147716 100644 (file)
@@ -1,3 +1,14 @@
+2019-08-30  Martin Jambor  <mjambor@suse.cz>
+
+       tree-optimization/91579
+       * tree-tailcall.c (tailr_arg_needs_copy): New variable.
+       (find_tail_calls): Allocate tailr_arg_needs_copy and set its bits as
+       appropriate.
+       (arg_needs_copy_p): Removed.
+       (eliminate_tail_call): Test tailr_arg_needs_copy instead of calling
+       arg_needs_copy_p.
+       (tree_optimize_tail_calls_1): Likewise.  Free tailr_arg_needs_copy.
+
 2019-08-29  Uroš Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386-features.c
index 02734ee90ceb692af9d37b5e3d118a8807012a4a..0c5ec5325f5c12f76aafbd188fd4721abaf246df 100644 (file)
@@ -1,3 +1,8 @@
+2019-08-30  Martin Jambor  <mjambor@suse.cz>
+
+       tree-optimization/91579
+       * gcc.dg/tree-ssa/pr91579.c: New test.
+
 2019-08-29  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/91560
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91579.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91579.c
new file mode 100644 (file)
index 0000000..ee752be
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-tailr1" } */
+
+typedef long unsigned int size_t;
+typedef int (*compare_t)(const void *, const void *);
+
+int partition (void *base, size_t nmemb, size_t size, compare_t cmp);
+
+void
+my_qsort (void *base, size_t nmemb, size_t size, compare_t cmp)
+{
+  int pt;
+  if (nmemb > 1)
+    {
+      pt = partition (base, nmemb, size, cmp);
+      my_qsort (base, pt + 1, size, cmp);
+      my_qsort ((void*)((char*) base + (pt + 1) * size),
+               nmemb - pt - 1, size, cmp);
+    }
+}
+
+/* { dg-final { scan-tree-dump-not "cmp\[^\r\n\]*PHI" "tailr1" } } */
index a4b563efd73ae8e0f039ddb866b6fca53123406d..4824a5e650fbc87ebb36787025c01371d8793415 100644 (file)
@@ -126,6 +126,11 @@ struct tailcall
    accumulator.  */
 static tree m_acc, a_acc;
 
+/* Bitmap with a bit for each function parameter which is set to true if we
+   have to copy the parameter for conversion of tail-recursive calls.  */
+
+static bitmap tailr_arg_needs_copy;
+
 static bool optimize_tail_call (struct tailcall *, bool);
 static void eliminate_tail_call (struct tailcall *);
 
@@ -727,6 +732,18 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
          gimple_stmt_iterator mgsi = gsi_for_stmt (stmt);
          gsi_move_before (&mgsi, &gsi);
        }
+      if (!tailr_arg_needs_copy)
+       tailr_arg_needs_copy = BITMAP_ALLOC (NULL);
+      for (param = DECL_ARGUMENTS (current_function_decl), idx = 0;
+          param;
+          param = DECL_CHAIN (param), idx++)
+       {
+         tree ddef, arg = gimple_call_arg (call, idx);
+         if (is_gimple_reg (param)
+             && (ddef = ssa_default_def (cfun, param))
+             && (arg != ddef))
+           bitmap_set_bit (tailr_arg_needs_copy, idx);
+       }
     }
 
   nw = XNEW (struct tailcall);
@@ -905,25 +922,6 @@ decrease_profile (basic_block bb, profile_count count)
     }
 }
 
-/* Returns true if argument PARAM of the tail recursive call needs to be copied
-   when the call is eliminated.  */
-
-static bool
-arg_needs_copy_p (tree param)
-{
-  tree def;
-
-  if (!is_gimple_reg (param))
-    return false;
-
-  /* Parameters that are only defined but never used need not be copied.  */
-  def = ssa_default_def (cfun, param);
-  if (!def)
-    return false;
-
-  return true;
-}
-
 /* Eliminates tail call described by T.  TMP_VARS is a list of
    temporary variables used to copy the function arguments.  */
 
@@ -1005,7 +1003,7 @@ eliminate_tail_call (struct tailcall *t)
        param;
        param = DECL_CHAIN (param), idx++)
     {
-      if (!arg_needs_copy_p (param))
+      if (!bitmap_bit_p (tailr_arg_needs_copy, idx))
        continue;
 
       arg = gimple_call_arg (stmt, idx);
@@ -1139,10 +1137,11 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
              split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
 
          /* Copy the args if needed.  */
-         for (param = DECL_ARGUMENTS (current_function_decl);
+         unsigned idx;
+         for (param = DECL_ARGUMENTS (current_function_decl), idx = 0;
               param;
-              param = DECL_CHAIN (param))
-           if (arg_needs_copy_p (param))
+              param = DECL_CHAIN (param), idx++)
+           if (bitmap_bit_p (tailr_arg_needs_copy, idx))
              {
                tree name = ssa_default_def (cfun, param);
                tree new_name = make_ssa_name (param, SSA_NAME_DEF_STMT (name));
@@ -1206,6 +1205,9 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
   if (phis_constructed)
     mark_virtual_operands_for_renaming (cfun);
 
+  if (tailr_arg_needs_copy)
+    BITMAP_FREE (tailr_arg_needs_copy);
+
   if (changed)
     return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals;
   return 0;