aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-tailcall.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-tailcall.c')
-rw-r--r--gcc/tree-tailcall.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index a6c44933f79..34ac8ee5834 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -431,15 +431,27 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
param = TREE_CHAIN (param), args = TREE_CHAIN (args))
{
tree arg = TREE_VALUE (args);
- if (param != arg
- /* Make sure there are no problems with copying. Note we must
+ if (param != arg)
+ {
+ /* Make sure there are no problems with copying. The parameter
have a copyable type and the two arguments must have reasonably
equivalent types. The latter requirement could be relaxed if
we emitted a suitable type conversion statement. */
- && (!is_gimple_reg_type (TREE_TYPE (param))
+ if (!is_gimple_reg_type (TREE_TYPE (param))
|| !lang_hooks.types_compatible_p (TREE_TYPE (param),
- TREE_TYPE (arg))))
- break;
+ TREE_TYPE (arg)))
+ break;
+
+ /* The parameter should be a real operand, so that phi node
+ created for it at the start of the function has the meaning
+ of copying the value. This test implies is_gimple_reg_type
+ from the previous condition, however this one could be
+ relaxed by being more careful with copying the new value
+ of the parameter (emitting appropriate MODIFY_EXPR and
+ updating the virtual operands). */
+ if (!is_gimple_reg (param))
+ break;
+ }
}
if (!args && !param)
tail_recursion = true;
@@ -884,7 +896,11 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
add_referenced_tmp_var (tmp);
phi = create_phi_node (tmp, first);
- add_phi_arg (&phi, build_int_cst (ret_type, 0), EDGE_PRED (first, 0));
+ add_phi_arg (&phi,
+ /* RET_TYPE can be a float when -ffast-maths is
+ enabled. */
+ fold_convert (ret_type, integer_zero_node),
+ EDGE_PRED (first, 0));
a_acc = PHI_RESULT (phi);
}
@@ -896,7 +912,11 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
add_referenced_tmp_var (tmp);
phi = create_phi_node (tmp, first);
- add_phi_arg (&phi, build_int_cst (ret_type, 1), EDGE_PRED (first, 0));
+ add_phi_arg (&phi,
+ /* RET_TYPE can be a float when -ffast-maths is
+ enabled. */
+ fold_convert (ret_type, integer_one_node),
+ EDGE_PRED (first, 0));
m_acc = PHI_RESULT (phi);
}
}