/* Pass computing data for optimizing stdarg functions.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>
This file is part of GCC.
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"
static bool
reachable_at_most_once (basic_block va_arg_bb, basic_block va_start_bb)
{
- edge *stack, e;
+ VEC (edge, heap) *stack = NULL;
+ edge e;
edge_iterator ei;
- int sp;
sbitmap visited;
bool ret;
if (! dominated_by_p (CDI_DOMINATORS, va_arg_bb, va_start_bb))
return false;
- stack = xmalloc ((n_basic_blocks + 1) * sizeof (edge));
- sp = 0;
-
visited = sbitmap_alloc (last_basic_block);
sbitmap_zero (visited);
ret = true;
FOR_EACH_EDGE (e, ei, va_arg_bb->preds)
- stack[sp++] = e;
+ VEC_safe_push (edge, heap, stack, e);
- while (sp)
+ while (! VEC_empty (edge, stack))
{
basic_block src;
- --sp;
- e = stack[sp];
+ e = VEC_pop (edge, stack);
src = e->src;
if (e->flags & EDGE_COMPLEX)
{
SET_BIT (visited, src->index);
FOR_EACH_EDGE (e, ei, src->preds)
- stack[sp++] = e;
+ VEC_safe_push (edge, heap, stack, e);
}
}
- free (stack);
+ VEC_free (edge, heap, stack);
sbitmap_free (visited);
return ret;
}
{
unsigned int i;
- si->offsets = xmalloc (num_ssa_names * sizeof (int));
+ si->offsets = XNEWVEC (int, num_ssa_names);
for (i = 0; i < num_ssa_names; ++i)
si->offsets[i] = -1;
}
stmt = SSA_NAME_DEF_STMT (lhs);
- if (TREE_CODE (stmt) != MODIFY_EXPR
- || TREE_OPERAND (stmt, 0) != lhs)
+ if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT
+ || GIMPLE_STMT_OPERAND (stmt, 0) != lhs)
return (unsigned HOST_WIDE_INT) -1;
- rhs = TREE_OPERAND (stmt, 1);
+ rhs = GIMPLE_STMT_OPERAND (stmt, 1);
if (TREE_CODE (rhs) == WITH_SIZE_EXPR)
rhs = TREE_OPERAND (rhs, 0);
continue;
}
- if ((TREE_CODE (rhs) == NOP_EXPR
- || TREE_CODE (rhs) == CONVERT_EXPR)
+ if (CONVERT_EXPR_P (rhs)
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
{
lhs = TREE_OPERAND (rhs, 0);
continue;
}
- if (TREE_CODE (rhs) == PLUS_EXPR
+ if ((TREE_CODE (rhs) == POINTER_PLUS_EXPR
+ || TREE_CODE (rhs) == PLUS_EXPR)
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
&& TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST
&& host_integerp (TREE_OPERAND (rhs, 1), 1))
stmt = SSA_NAME_DEF_STMT (lhs);
- rhs = TREE_OPERAND (stmt, 1);
+ rhs = GIMPLE_STMT_OPERAND (stmt, 1);
if (TREE_CODE (rhs) == WITH_SIZE_EXPR)
rhs = TREE_OPERAND (rhs, 0);
continue;
}
- if ((TREE_CODE (rhs) == NOP_EXPR
- || TREE_CODE (rhs) == CONVERT_EXPR)
+ if (CONVERT_EXPR_P (rhs)
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
{
lhs = TREE_OPERAND (rhs, 0);
continue;
}
- if (TREE_CODE (rhs) == PLUS_EXPR
+ if ((TREE_CODE (rhs) == POINTER_PLUS_EXPR
+ || TREE_CODE (rhs) == PLUS_EXPR)
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
&& TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST
&& host_integerp (TREE_OPERAND (rhs, 1), 1))
if (! POINTER_TYPE_P (TREE_TYPE (rhs)))
return;
- if ((TREE_CODE (rhs) == PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
- || TREE_CODE (rhs) == NOP_EXPR
- || TREE_CODE (rhs) == CONVERT_EXPR)
+ if (((TREE_CODE (rhs) == POINTER_PLUS_EXPR
+ || TREE_CODE (rhs) == PLUS_EXPR)
+ && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
+ || CONVERT_EXPR_P (rhs))
rhs = TREE_OPERAND (rhs, 0);
if (TREE_CODE (rhs) != SSA_NAME
DECL_UID (SSA_NAME_VAR (use))))
continue;
- if (TREE_CODE (stmt) == MODIFY_EXPR)
+ if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
{
- tree lhs = TREE_OPERAND (stmt, 0);
- tree rhs = TREE_OPERAND (stmt, 1);
+ tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
if (TREE_CODE (rhs) == WITH_SIZE_EXPR)
rhs = TREE_OPERAND (rhs, 0);
other_ap_temp = (some_type *) ap_temp;
ap = ap_temp;
statements. */
- if ((TREE_CODE (rhs) == PLUS_EXPR
+ if ((TREE_CODE (rhs) == POINTER_PLUS_EXPR
&& TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
- || TREE_CODE (rhs) == NOP_EXPR
- || TREE_CODE (rhs) == CONVERT_EXPR)
+ || CONVERT_EXPR_P (rhs))
rhs = TREE_OPERAND (rhs, 0);
if (rhs == use)
gate_optimize_stdarg (void)
{
/* This optimization is only for stdarg functions. */
- return current_function_stdarg != 0;
+ return cfun->stdarg != 0;
}
/* Entry point to the stdarg optimization pass. */
-static void
+static unsigned int
execute_optimize_stdarg (void)
{
basic_block bb;
va_list_simple_ptr = POINTER_TYPE_P (va_list_type_node)
&& (TREE_TYPE (va_list_type_node) == void_type_node
|| TREE_TYPE (va_list_type_node) == char_type_node);
+ gcc_assert (is_gimple_reg_type (va_list_type_node) == va_list_simple_ptr);
FOR_EACH_BB (bb)
{
break;
/* If old style builtins are used, don't optimize anything. */
case BUILT_IN_SAVEREGS:
- case BUILT_IN_STDARG_START:
case BUILT_IN_ARGS_INFO:
case BUILT_IN_NEXT_ARG:
va_list_escapes = true;
}
si.va_start_count++;
- ap = TREE_VALUE (TREE_OPERAND (call, 1));
+ ap = CALL_EXPR_ARG (call, 0);
if (TREE_CODE (ap) != ADDR_EXPR)
{
if (va_list_simple_ptr)
cfun->va_list_fpr_size = VA_LIST_MAX_FPR_SIZE;
+ calculate_dominance_info (CDI_DOMINATORS);
+
FOR_EACH_BB (bb)
{
block_stmt_iterator i;
si.compute_sizes = -1;
si.bb = bb;
+
+ /* For va_list_simple_ptr, we have to check PHI nodes too. We treat
+ them as assignments for the purpose of escape analysis. This is
+ not needed for non-simple va_list because virtual phis don't perform
+ any real data movement. */
+ if (va_list_simple_ptr)
+ {
+ tree phi, lhs, rhs;
+ use_operand_p uop;
+ ssa_op_iter soi;
+
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ {
+ lhs = PHI_RESULT (phi);
+
+ if (!is_gimple_reg (lhs))
+ continue;
+
+ FOR_EACH_PHI_ARG (uop, phi, soi, SSA_OP_USE)
+ {
+ rhs = USE_FROM_PTR (uop);
+ if (va_list_ptr_read (&si, rhs, lhs))
+ continue;
+ else if (va_list_ptr_write (&si, lhs, rhs))
+ continue;
+ else
+ check_va_list_escapes (&si, lhs, rhs);
+
+ if (si.va_list_escapes
+ || walk_tree (&phi, find_va_list_reference,
+ si.va_list_vars, NULL))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fputs ("va_list escapes in ", dump_file);
+ print_generic_expr (dump_file, phi, dump_flags);
+ fputc ('\n', dump_file);
+ }
+ va_list_escapes = true;
+ }
+ }
+ }
+ }
+
for (i = bsi_start (bb);
!bsi_end_p (i) && !va_list_escapes;
bsi_next (&i))
continue;
}
- if (TREE_CODE (stmt) == MODIFY_EXPR)
+ if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
{
- tree lhs = TREE_OPERAND (stmt, 0);
- tree rhs = TREE_OPERAND (stmt, 1);
+ tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
if (TREE_CODE (rhs) == WITH_SIZE_EXPR)
rhs = TREE_OPERAND (rhs, 0);
fprintf (dump_file, "%d", cfun->va_list_fpr_size);
fputs (" FPR units.\n", dump_file);
}
+ return 0;
}
-struct tree_opt_pass pass_stdarg =
+struct gimple_opt_pass pass_stdarg =
{
+ {
+ GIMPLE_PASS,
"stdarg", /* name */
gate_optimize_stdarg, /* gate */
execute_optimize_stdarg, /* execute */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func, /* todo_flags_finish */
- 0 /* letter */
+ TODO_dump_func /* todo_flags_finish */
+ }
};