diff options
Diffstat (limited to 'gcc/tree-tailcall.cc')
-rw-r--r-- | gcc/tree-tailcall.cc | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/gcc/tree-tailcall.cc b/gcc/tree-tailcall.cc index 477729c..c8740f9 100644 --- a/gcc/tree-tailcall.cc +++ b/gcc/tree-tailcall.cc @@ -165,8 +165,6 @@ suitable_for_tail_opt_p (gcall *call, bool diag_musttail) static bool suitable_for_tail_call_opt_p (gcall *call, bool diag_musttail) { - tree param; - /* alloca (until we have stack slot life analysis) inhibits sibling call optimizations, but not tail recursion. */ if (cfun->calls_alloca) @@ -204,18 +202,6 @@ suitable_for_tail_call_opt_p (gcall *call, bool diag_musttail) return false; } - /* ??? It is OK if the argument of a function is taken in some cases, - but not in all cases. See PR15387 and PR19616. Revisit for 4.1. */ - if (!diag_musttail || !gimple_call_must_tail_p (call)) - for (param = DECL_ARGUMENTS (current_function_decl); - param; param = DECL_CHAIN (param)) - if (TREE_ADDRESSABLE (param)) - { - maybe_error_musttail (call, _("address of caller arguments taken"), - diag_musttail); - return false; - } - if (diag_musttail && gimple_call_must_tail_p (call) && warn_musttail_local_addr) @@ -565,6 +551,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, basic_block abb; size_t idx; tree var; + bool only_tailr = false; if (!single_succ_p (bb) && (EDGE_COUNT (bb->succs) || !cfun->has_musttail || !diag_musttail)) @@ -660,6 +647,25 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, if (!suitable_for_tail_call_opt_p (call, diag_musttail)) opt_tailcalls = false; + /* ??? It is OK if the argument of a function is taken in some cases, + but not in all cases. See PR15387 and PR19616. Revisit for 4.1. */ + if (!diag_musttail || !gimple_call_must_tail_p (call)) + for (param = DECL_ARGUMENTS (current_function_decl); + param; param = DECL_CHAIN (param)) + if (TREE_ADDRESSABLE (param)) + { + maybe_error_musttail (call, _("address of caller arguments taken"), + diag_musttail); + /* If current function has musttail calls, we can't disable tail + calls altogether for the whole caller, because those might be + actually fine. So just punt if this exact call is not + a tail recursion. */ + if (cfun->has_musttail) + only_tailr = true; + else + opt_tailcalls = false; + } + /* If the LHS of our call is not just a simple register or local variable, we can't transform this into a tail or sibling call. This situation happens, in (e.g.) "*p = foo()" where foo returns a @@ -794,6 +800,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, tail_recursion = true; } + if (only_tailr && !tail_recursion) + return; + /* Compute live vars if not computed yet. */ if (live_vars == NULL) { @@ -1036,7 +1045,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail, && TREE_CONSTANT (ret_var)) if (tree type = gimple_range_type (call)) if (tree callee = gimple_call_fndecl (call)) - if ((INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type)) + if ((INTEGRAL_TYPE_P (type) + || SCALAR_FLOAT_TYPE_P (type) + || POINTER_TYPE_P (type)) && useless_type_conversion_p (TREE_TYPE (TREE_TYPE (callee)), type) && useless_type_conversion_p (TREE_TYPE (ret_var), type) |