/* 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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, 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) == 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) == 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))
var = SSA_NAME_VAR (var);
if (TREE_CODE (var) == VAR_DECL
- && bitmap_bit_p (va_list_vars, var_ann (var)->uid))
+ && bitmap_bit_p (va_list_vars, DECL_UID (var)))
return var;
return NULL_TREE;
return false;
if (TREE_CODE (var) != SSA_NAME
- || bitmap_bit_p (si->va_list_vars, var_ann (SSA_NAME_VAR (var))->uid))
+ || bitmap_bit_p (si->va_list_vars, DECL_UID (SSA_NAME_VAR (var))))
return false;
base = get_base_address (ap);
if (TREE_CODE (base) != VAR_DECL
- || !bitmap_bit_p (si->va_list_vars, var_ann (base)->uid))
+ || !bitmap_bit_p (si->va_list_vars, DECL_UID (base)))
return false;
if (TREE_OPERAND (ap, 1) == va_list_gpr_counter_field)
va_list_ptr_read (struct stdarg_info *si, tree ap, tree tem)
{
if (TREE_CODE (ap) != VAR_DECL
- || !bitmap_bit_p (si->va_list_vars, var_ann (ap)->uid))
+ || !bitmap_bit_p (si->va_list_vars, DECL_UID (ap)))
return false;
if (TREE_CODE (tem) != SSA_NAME
|| bitmap_bit_p (si->va_list_vars,
- var_ann (SSA_NAME_VAR (tem))->uid)
+ DECL_UID (SSA_NAME_VAR (tem)))
|| is_global_var (SSA_NAME_VAR (tem)))
return false;
/* Note the temporary, as we need to track whether it doesn't escape
the current function. */
bitmap_set_bit (si->va_list_escape_vars,
- var_ann (SSA_NAME_VAR (tem))->uid);
+ DECL_UID (SSA_NAME_VAR (tem)));
return true;
}
unsigned HOST_WIDE_INT increment;
if (TREE_CODE (ap) != VAR_DECL
- || !bitmap_bit_p (si->va_list_vars, var_ann (ap)->uid))
+ || !bitmap_bit_p (si->va_list_vars, DECL_UID (ap)))
return false;
if (TREE_CODE (tem2) != SSA_NAME
- || bitmap_bit_p (si->va_list_vars, var_ann (SSA_NAME_VAR (tem2))->uid))
+ || bitmap_bit_p (si->va_list_vars, DECL_UID (SSA_NAME_VAR (tem2))))
return false;
if (si->compute_sizes <= 0)
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)
+ || TREE_CODE (rhs) == NOP_EXPR
+ || TREE_CODE (rhs) == CONVERT_EXPR)
rhs = TREE_OPERAND (rhs, 0);
if (TREE_CODE (rhs) != SSA_NAME
|| ! bitmap_bit_p (si->va_list_escape_vars,
- var_ann (SSA_NAME_VAR (rhs))->uid))
+ DECL_UID (SSA_NAME_VAR (rhs))))
return;
if (TREE_CODE (lhs) != SSA_NAME || is_global_var (SSA_NAME_VAR (lhs)))
}
bitmap_set_bit (si->va_list_escape_vars,
- var_ann (SSA_NAME_VAR (lhs))->uid);
+ DECL_UID (SSA_NAME_VAR (lhs)));
}
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_USES)
{
if (! bitmap_bit_p (si->va_list_escape_vars,
- var_ann (SSA_NAME_VAR (use))->uid))
+ 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)
{
if (TREE_CODE (lhs) == SSA_NAME
&& bitmap_bit_p (si->va_list_escape_vars,
- var_ann (SSA_NAME_VAR (lhs))->uid))
+ DECL_UID (SSA_NAME_VAR (lhs))))
continue;
if (TREE_CODE (lhs) == VAR_DECL
&& bitmap_bit_p (si->va_list_vars,
- var_ann (lhs)->uid))
+ DECL_UID (lhs)))
continue;
}
}
/* 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)
{
}
si.va_start_count++;
- ap = TREE_VALUE (TREE_OPERAND (call, 1));
+ ap = CALL_EXPR_ARG (call, 0);
if (TREE_CODE (ap) != ADDR_EXPR)
{
break;
}
- bitmap_set_bit (si.va_list_vars, var_ann (ap)->uid);
+ bitmap_set_bit (si.va_list_vars, DECL_UID (ap));
/* VA_START_BB and VA_START_AP will be only used if there is just
one va_start in the function. */
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;
}