+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
--- /dev/null
+/* { 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" } } */
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 *);
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);
}
}
-/* 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. */
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);
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));
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;