/* Pass computing data for optimizing stdarg functions.
- Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>
This file is part of GCC.
#include "tree.h"
#include "function.h"
#include "langhooks.h"
-#include "diagnostic.h"
+#include "gimple-pretty-print.h"
#include "target.h"
#include "tree-flow.h"
#include "tree-pass.h"
while (lhs)
{
enum tree_code rhs_code;
+ tree rhs1;
if (si->offsets[SSA_NAME_VERSION (lhs)] != -1)
{
return (unsigned HOST_WIDE_INT) -1;
rhs_code = gimple_assign_rhs_code (stmt);
+ rhs1 = gimple_assign_rhs1 (stmt);
if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS
|| gimple_assign_cast_p (stmt))
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
+ && TREE_CODE (rhs1) == SSA_NAME)
{
- lhs = gimple_assign_rhs1 (stmt);
+ lhs = rhs1;
continue;
}
if ((rhs_code == POINTER_PLUS_EXPR
|| rhs_code == PLUS_EXPR)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
+ && TREE_CODE (rhs1) == SSA_NAME
&& host_integerp (gimple_assign_rhs2 (stmt), 1))
{
ret += tree_low_cst (gimple_assign_rhs2 (stmt), 1);
- lhs = gimple_assign_rhs1 (stmt);
+ lhs = rhs1;
+ continue;
+ }
+
+ if (rhs_code == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0)) == SSA_NAME
+ && host_integerp (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1))
+ {
+ ret += tree_low_cst (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1);
+ lhs = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
continue;
}
while (lhs)
{
enum tree_code rhs_code;
+ tree rhs1;
if (si->offsets[SSA_NAME_VERSION (lhs)] != -1)
break;
stmt = SSA_NAME_DEF_STMT (lhs);
rhs_code = gimple_assign_rhs_code (stmt);
+ rhs1 = gimple_assign_rhs1 (stmt);
if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS
|| gimple_assign_cast_p (stmt))
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
+ && TREE_CODE (rhs1) == SSA_NAME)
{
- lhs = gimple_assign_rhs1 (stmt);
+ lhs = rhs1;
continue;
}
if ((rhs_code == POINTER_PLUS_EXPR
|| rhs_code == PLUS_EXPR)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
+ && TREE_CODE (rhs1) == SSA_NAME
&& host_integerp (gimple_assign_rhs2 (stmt), 1))
{
val -= tree_low_cst (gimple_assign_rhs2 (stmt), 1);
- lhs = gimple_assign_rhs1 (stmt);
+ lhs = rhs1;
+ continue;
+ }
+
+ if (rhs_code == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0)) == SSA_NAME
+ && host_integerp (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1))
+ {
+ val -= tree_low_cst (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1);
+ lhs = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
continue;
}
if (! POINTER_TYPE_P (TREE_TYPE (rhs)))
return;
- if (TREE_CODE (rhs) != SSA_NAME
- || ! bitmap_bit_p (si->va_list_escape_vars,
- DECL_UID (SSA_NAME_VAR (rhs))))
+ if (TREE_CODE (rhs) == SSA_NAME)
+ {
+ if (! bitmap_bit_p (si->va_list_escape_vars,
+ DECL_UID (SSA_NAME_VAR (rhs))))
+ return;
+ }
+ else if (TREE_CODE (rhs) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0)) == SSA_NAME)
+ {
+ if (! bitmap_bit_p (si->va_list_escape_vars,
+ DECL_UID (SSA_NAME_VAR (TREE_OPERAND
+ (TREE_OPERAND (rhs, 0), 0)))))
+ return;
+ }
+ else
return;
if (TREE_CODE (lhs) != SSA_NAME || is_global_var (SSA_NAME_VAR (lhs)))
tree use;
ssa_op_iter iter;
+ if (is_gimple_debug (stmt))
+ continue;
+
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_USES)
{
if (! bitmap_bit_p (si->va_list_escape_vars,
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
/* x = *ap_temp; */
- if (gimple_assign_rhs_code (stmt) == INDIRECT_REF
+ if (rhs_code == MEM_REF
&& TREE_OPERAND (rhs, 0) == use
&& TYPE_SIZE_UNIT (TREE_TYPE (rhs))
&& host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), 1)
tree access_size = TYPE_SIZE_UNIT (TREE_TYPE (rhs));
gpr_size = si->offsets[SSA_NAME_VERSION (use)]
+ + tree_low_cst (TREE_OPERAND (rhs, 1), 0)
+ tree_low_cst (access_size, 1);
if (gpr_size >= VA_LIST_MAX_GPR_SIZE)
cfun->va_list_gpr_size = VA_LIST_MAX_GPR_SIZE;
DECL_UID (lhs)))
continue;
}
+ else if (rhs_code == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF
+ && TREE_OPERAND (TREE_OPERAND (rhs, 0), 0) == use)
+ {
+ tree lhs = gimple_assign_lhs (stmt);
+
+ if (bitmap_bit_p (si->va_list_escape_vars,
+ DECL_UID (SSA_NAME_VAR (lhs))))
+ continue;
+ }
}
if (dump_file && (dump_flags & TDF_DETAILS))
break;
/* If old style builtins are used, don't optimize anything. */
case BUILT_IN_SAVEREGS:
- case BUILT_IN_ARGS_INFO:
case BUILT_IN_NEXT_ARG:
va_list_escapes = true;
continue;
continue;
}
}
+ else if (is_gimple_debug (stmt))
+ continue;
/* All other uses of va_list are either va_copy (that is not handled
in this optimization), taking address of va_list variable or
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
- PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
+ TV_NONE, /* tv_id */
+ PROP_cfg | PROP_ssa, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func /* todo_flags_finish */
+ 0 /* todo_flags_finish */
}
};