GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "tree-pass.h"
#include "flags.h"
#include "langhooks.h"
+#include "dbgcnt.h"
/* The file implements the tail recursion elimination. It is also used to
analyze the tail calls in general, passing the results to the rtl level
referenced_var_iterator rvi;
tree var;
- if (current_function_stdarg)
+ if (cfun->stdarg)
return false;
/* No local variable nor structure field should be call-clobbered. We
/* alloca (until we have stack slot life analysis) inhibits
sibling call optimizations, but not tail recursion. */
- if (current_function_calls_alloca)
+ if (cfun->calls_alloca)
return false;
/* If we are using sjlj exceptions, we may need to add a call to
/* Any function that calls setjmp might have longjmp called from
any called function. ??? We really should represent this
properly in the CFG so that this needn't be special cased. */
- if (current_function_calls_setjmp)
+ if (cfun->calls_setjmp)
return false;
/* ??? It is OK if the argument of a function is taken in some cases,
/* Accumulator optimizations will reverse the order of operations.
We can only do that for floating-point types if we're assuming
that addition and multiplication are associative. */
- if (!flag_unsafe_math_optimizations)
+ if (!flag_associative_math)
if (FLOAT_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
return false;
*ass_var = dest;
return true;
- /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR). */
+ /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR, POINTER_PLUS_EXPR). */
default:
return false;
/* If the statement has virtual or volatile operands, fail. */
ann = stmt_ann (stmt);
if (!ZERO_SSA_OPERANDS (stmt, (SSA_OP_VUSE | SSA_OP_VIRTUAL_DEFS))
- || ann->has_volatile_ops)
+ || ann->has_volatile_ops
+ || (!gimple_aliases_computed_p (cfun) && ann->references_memory))
return;
}
equivalent types. The latter requirement could be relaxed if
we emitted a suitable type conversion statement. */
if (!is_gimple_reg_type (TREE_TYPE (param))
- || !lang_hooks.types_compatible_p (TREE_TYPE (param),
- TREE_TYPE (arg)))
+ || !useless_type_conversion_p (TREE_TYPE (param),
+ TREE_TYPE (arg)))
break;
/* The parameter should be a real operand, so that phi node
static bool
gate_tail_calls (void)
{
- return flag_optimize_sibling_calls != 0;
+ return flag_optimize_sibling_calls != 0 && dbg_cnt (tail_call);
}
static unsigned int
return tree_optimize_tail_calls_1 (true);
}
-struct tree_opt_pass pass_tail_recursion =
+struct gimple_opt_pass pass_tail_recursion =
{
+ {
+ GIMPLE_PASS,
"tailr", /* name */
gate_tail_calls, /* gate */
execute_tail_recursion, /* execute */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func | TODO_verify_ssa, /* todo_flags_finish */
- 0 /* letter */
+ TODO_dump_func | TODO_verify_ssa /* todo_flags_finish */
+ }
};
-struct tree_opt_pass pass_tail_calls =
+struct gimple_opt_pass pass_tail_calls =
{
+ {
+ GIMPLE_PASS,
"tailc", /* name */
gate_tail_calls, /* gate */
execute_tail_calls, /* execute */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func | TODO_verify_ssa, /* todo_flags_finish */
- 0 /* letter */
+ TODO_dump_func | TODO_verify_ssa /* todo_flags_finish */
+ }
};