X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Ftree-stdarg.c;h=8401747a020655c6cd7b8be0fcef88be0e39583f;hp=5c3b81b724a6874fcbacdf4aca4acb1609d35cb5;hb=3ab97505ae0ccdbf56f501da272327f768217aaf;hpb=ffa47ae0a75a37b1a2feb5c3b1b4a3c5eee7d55b diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c index 5c3b81b724a..8401747a020 100644 --- a/gcc/tree-stdarg.c +++ b/gcc/tree-stdarg.c @@ -1,12 +1,13 @@ /* Pass computing data for optimizing stdarg functions. - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. Contributed by Jakub Jelinek 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, @@ -15,9 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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 +. */ #include "config.h" #include "system.h" @@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */ #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" @@ -47,9 +48,9 @@ Boston, MA 02111-1307, USA. */ 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; @@ -59,22 +60,18 @@ reachable_at_most_once (basic_block va_arg_bb, basic_block va_start_bb) 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) @@ -99,11 +96,11 @@ reachable_at_most_once (basic_block va_arg_bb, basic_block va_start_bb) { 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; } @@ -117,7 +114,8 @@ static unsigned HOST_WIDE_INT va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, bool gpr_p) { - tree stmt, lhs, orig_lhs; + tree lhs, orig_lhs; + gimple stmt; unsigned HOST_WIDE_INT ret = 0, val, counter_val; unsigned int max_size; @@ -125,7 +123,7 @@ va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, { 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; } @@ -135,6 +133,8 @@ va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, orig_lhs = lhs = rhs; while (lhs) { + enum tree_code rhs_code; + if (si->offsets[SSA_NAME_VERSION (lhs)] != -1) { if (counter_val >= max_size) @@ -149,38 +149,32 @@ va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, stmt = SSA_NAME_DEF_STMT (lhs); - if (TREE_CODE (stmt) != MODIFY_EXPR - || TREE_OPERAND (stmt, 0) != lhs) + if (!is_gimple_assign (stmt) || gimple_assign_lhs (stmt) != lhs) return (unsigned HOST_WIDE_INT) -1; - rhs = TREE_OPERAND (stmt, 1); - if (TREE_CODE (rhs) == WITH_SIZE_EXPR) - rhs = TREE_OPERAND (rhs, 0); - - if (TREE_CODE (rhs) == SSA_NAME) + rhs_code = gimple_assign_rhs_code (stmt); + if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS + || gimple_assign_cast_p (stmt)) + && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME) { - lhs = rhs; + lhs = gimple_assign_rhs1 (stmt); continue; } - if ((TREE_CODE (rhs) == NOP_EXPR - || TREE_CODE (rhs) == CONVERT_EXPR) - && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME) + if ((rhs_code == POINTER_PLUS_EXPR + || rhs_code == PLUS_EXPR) + && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME + && host_integerp (gimple_assign_rhs2 (stmt), 1)) { - lhs = TREE_OPERAND (rhs, 0); + ret += tree_low_cst (gimple_assign_rhs2 (stmt), 1); + lhs = gimple_assign_rhs1 (stmt); continue; } - if (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)) - { - ret += tree_low_cst (TREE_OPERAND (rhs, 1), 1); - lhs = TREE_OPERAND (rhs, 0); - continue; - } + if (get_gimple_rhs_class (rhs_code) != GIMPLE_SINGLE_RHS) + return (unsigned HOST_WIDE_INT) -1; + rhs = gimple_assign_rhs1 (stmt); if (TREE_CODE (counter) != TREE_CODE (rhs)) return (unsigned HOST_WIDE_INT) -1; @@ -201,6 +195,8 @@ va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, val = ret + counter_val; while (lhs) { + enum tree_code rhs_code; + if (si->offsets[SSA_NAME_VERSION (lhs)] != -1) break; @@ -211,31 +207,22 @@ va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, stmt = SSA_NAME_DEF_STMT (lhs); - rhs = TREE_OPERAND (stmt, 1); - if (TREE_CODE (rhs) == WITH_SIZE_EXPR) - rhs = TREE_OPERAND (rhs, 0); - - if (TREE_CODE (rhs) == SSA_NAME) + rhs_code = gimple_assign_rhs_code (stmt); + if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS + || gimple_assign_cast_p (stmt)) + && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME) { - lhs = rhs; + lhs = gimple_assign_rhs1 (stmt); continue; } - if ((TREE_CODE (rhs) == NOP_EXPR - || TREE_CODE (rhs) == CONVERT_EXPR) - && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME) + if ((rhs_code == POINTER_PLUS_EXPR + || rhs_code == PLUS_EXPR) + && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME + && host_integerp (gimple_assign_rhs2 (stmt), 1)) { - lhs = TREE_OPERAND (rhs, 0); - continue; - } - - if (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)) - { - val -= tree_low_cst (TREE_OPERAND (rhs, 1), 1); - lhs = TREE_OPERAND (rhs, 0); + val -= tree_low_cst (gimple_assign_rhs2 (stmt), 1); + lhs = gimple_assign_rhs1 (stmt); continue; } @@ -252,14 +239,14 @@ static tree find_va_list_reference (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data) { - bitmap va_list_vars = (bitmap) data; + bitmap va_list_vars = (bitmap) ((struct walk_stmt_info *) data)->info; tree var = *tp; if (TREE_CODE (var) == SSA_NAME) 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; @@ -337,12 +324,12 @@ va_list_counter_struct_op (struct stdarg_info *si, tree ap, tree var, 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) @@ -361,12 +348,12 @@ static bool 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; @@ -396,7 +383,7 @@ va_list_ptr_read (struct stdarg_info *si, tree ap, tree tem) /* 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; } @@ -413,11 +400,11 @@ va_list_ptr_write (struct stdarg_info *si, tree ap, tree tem2) 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) @@ -447,15 +434,9 @@ check_va_list_escapes (struct stdarg_info *si, tree lhs, tree rhs) 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) - 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))) @@ -495,7 +476,7 @@ check_va_list_escapes (struct stdarg_info *si, tree lhs, tree rhs) } bitmap_set_bit (si->va_list_escape_vars, - var_ann (SSA_NAME_VAR (lhs))->uid); + DECL_UID (SSA_NAME_VAR (lhs))); } @@ -509,29 +490,30 @@ check_all_va_list_escapes (struct stdarg_info *si) FOR_EACH_BB (bb) { - block_stmt_iterator i; + gimple_stmt_iterator i; - for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i)) + for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) { - tree stmt = bsi_stmt (i), use; + gimple stmt = gsi_stmt (i); + 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, - var_ann (SSA_NAME_VAR (use))->uid)) + DECL_UID (SSA_NAME_VAR (use)))) continue; - if (TREE_CODE (stmt) == MODIFY_EXPR) + if (is_gimple_assign (stmt)) { - tree lhs = TREE_OPERAND (stmt, 0); - tree rhs = TREE_OPERAND (stmt, 1); - - if (TREE_CODE (rhs) == WITH_SIZE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + tree rhs = gimple_assign_rhs1 (stmt); + enum tree_code rhs_code = gimple_assign_rhs_code (stmt); /* x = *ap_temp; */ - if (TREE_CODE (rhs) == INDIRECT_REF + if (gimple_assign_rhs_code (stmt) == INDIRECT_REF && TREE_OPERAND (rhs, 0) == use && TYPE_SIZE_UNIT (TREE_TYPE (rhs)) && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), 1) @@ -555,22 +537,24 @@ check_all_va_list_escapes (struct stdarg_info *si) other_ap_temp = (some_type *) ap_temp; ap = ap_temp; statements. */ - if ((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 (rhs == use) + if (rhs == use + && ((rhs_code == POINTER_PLUS_EXPR + && (TREE_CODE (gimple_assign_rhs2 (stmt)) + == INTEGER_CST)) + || gimple_assign_cast_p (stmt) + || (get_gimple_rhs_class (rhs_code) + == GIMPLE_SINGLE_RHS))) { + tree lhs = gimple_assign_lhs (stmt); + 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; } } @@ -578,7 +562,7 @@ check_all_va_list_escapes (struct stdarg_info *si) if (dump_file && (dump_flags & TDF_DETAILS)) { fputs ("va_list escapes in ", dump_file); - print_generic_expr (dump_file, stmt, dump_flags); + print_gimple_stmt (dump_file, stmt, 0, dump_flags); fputc ('\n', dump_file); } return true; @@ -597,20 +581,22 @@ static bool 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; bool va_list_escapes = false; bool va_list_simple_ptr; struct stdarg_info si; + struct walk_stmt_info wi; const char *funcname = NULL; + tree cfun_va_list; cfun->va_list_gpr_size = 0; cfun->va_list_fpr_size = 0; @@ -621,24 +607,25 @@ execute_optimize_stdarg (void) if (dump_file) funcname = lang_hooks.decl_printable_name (current_function_decl, 2); - 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); + cfun_va_list = targetm.fn_abi_va_list (cfun->decl); + va_list_simple_ptr = POINTER_TYPE_P (cfun_va_list) + && (TREE_TYPE (cfun_va_list) == void_type_node + || TREE_TYPE (cfun_va_list) == char_type_node); + gcc_assert (is_gimple_reg_type (cfun_va_list) == va_list_simple_ptr); FOR_EACH_BB (bb) { - block_stmt_iterator i; + gimple_stmt_iterator i; - for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i)) + for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) { - tree stmt = bsi_stmt (i); - tree call = get_call_expr_in (stmt), callee; - tree ap; + gimple stmt = gsi_stmt (i); + tree callee, ap; - if (!call) + if (!is_gimple_call (stmt)) continue; - callee = get_callee_fndecl (call); + callee = gimple_call_fndecl (stmt); if (!callee || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL) continue; @@ -649,7 +636,6 @@ execute_optimize_stdarg (void) 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; @@ -659,24 +645,38 @@ execute_optimize_stdarg (void) } si.va_start_count++; - ap = TREE_VALUE (TREE_OPERAND (call, 1)); - if (TREE_CODE (ap) != ADDR_EXPR - || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (ap, 0))) - != TYPE_MAIN_VARIANT (va_list_type_node) - || TREE_CODE (TREE_OPERAND (ap, 0)) != VAR_DECL) + ap = gimple_call_arg (stmt, 0); + + if (TREE_CODE (ap) != ADDR_EXPR) { va_list_escapes = true; break; } - ap = TREE_OPERAND (ap, 0); + if (TREE_CODE (ap) == ARRAY_REF) + { + if (! integer_zerop (TREE_OPERAND (ap, 1))) + { + va_list_escapes = true; + break; + } + ap = TREE_OPERAND (ap, 0); + } + if (TYPE_MAIN_VARIANT (TREE_TYPE (ap)) + != TYPE_MAIN_VARIANT (targetm.fn_abi_va_list (cfun->decl)) + || TREE_CODE (ap) != VAR_DECL) + { + va_list_escapes = true; + break; + } + if (is_global_var (ap)) { va_list_escapes = true; 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. */ @@ -720,24 +720,69 @@ execute_optimize_stdarg (void) if (va_list_simple_ptr) cfun->va_list_fpr_size = VA_LIST_MAX_FPR_SIZE; + calculate_dominance_info (CDI_DOMINATORS); + memset (&wi, 0, sizeof (wi)); + wi.info = si.va_list_vars; + FOR_EACH_BB (bb) { - block_stmt_iterator i; + gimple_stmt_iterator i; si.compute_sizes = -1; si.bb = bb; - for (i = bsi_start (bb); - !bsi_end_p (i) && !va_list_escapes; - bsi_next (&i)) + + /* 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 stmt = bsi_stmt (i); - tree call; + tree lhs, rhs; + use_operand_p uop; + ssa_op_iter soi; + + for (i = gsi_start_phis (bb); !gsi_end_p (i); gsi_next (&i)) + { + gimple phi = gsi_stmt (i); + 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) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fputs ("va_list escapes in ", dump_file); + print_gimple_stmt (dump_file, phi, 0, dump_flags); + fputc ('\n', dump_file); + } + va_list_escapes = true; + } + } + } + } + + for (i = gsi_start_bb (bb); + !gsi_end_p (i) && !va_list_escapes; + gsi_next (&i)) + { + gimple stmt = gsi_stmt (i); /* Don't look at __builtin_va_{start,end}, they are ok. */ - call = get_call_expr_in (stmt); - if (call) + if (is_gimple_call (stmt)) { - tree callee = get_callee_fndecl (call); + tree callee = gimple_call_fndecl (stmt); if (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL @@ -746,47 +791,59 @@ execute_optimize_stdarg (void) continue; } - if (TREE_CODE (stmt) == MODIFY_EXPR) + if (is_gimple_assign (stmt)) { - tree lhs = TREE_OPERAND (stmt, 0); - tree rhs = TREE_OPERAND (stmt, 1); - - if (TREE_CODE (rhs) == WITH_SIZE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); if (va_list_simple_ptr) { - /* Check for tem = ap. */ - if (va_list_ptr_read (&si, rhs, lhs)) - continue; + if (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)) + == GIMPLE_SINGLE_RHS) + { + /* Check for tem = ap. */ + if (va_list_ptr_read (&si, rhs, lhs)) + continue; - /* Check for the last insn in: - tem1 = ap; - tem2 = tem1 + CST; - ap = tem2; - sequence. */ - else if (va_list_ptr_write (&si, lhs, rhs)) - continue; + /* Check for the last insn in: + tem1 = ap; + tem2 = tem1 + CST; + ap = tem2; + sequence. */ + else if (va_list_ptr_write (&si, lhs, rhs)) + continue; + } - else + if ((gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR + && TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST) + || CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt)) + || (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)) + == GIMPLE_SINGLE_RHS)) check_va_list_escapes (&si, lhs, rhs); } else { - /* Check for ap[0].field = temp. */ - if (va_list_counter_struct_op (&si, lhs, rhs, true)) - continue; + if (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)) + == GIMPLE_SINGLE_RHS) + { + /* Check for ap[0].field = temp. */ + if (va_list_counter_struct_op (&si, lhs, rhs, true)) + continue; - /* Check for temp = ap[0].field. */ - else if (va_list_counter_struct_op (&si, rhs, lhs, false)) - continue; + /* Check for temp = ap[0].field. */ + else if (va_list_counter_struct_op (&si, rhs, lhs, + false)) + continue; + } /* Do any architecture specific checking. */ - else if (targetm.stdarg_optimize_hook - && targetm.stdarg_optimize_hook (&si, lhs, rhs)) + if (targetm.stdarg_optimize_hook + && targetm.stdarg_optimize_hook (&si, stmt)) 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 @@ -795,13 +852,12 @@ execute_optimize_stdarg (void) fully), or some unexpected use of va_list. None of these should happen in a gimplified VA_ARG_EXPR. */ if (si.va_list_escapes - || walk_tree (&stmt, find_va_list_reference, - si.va_list_vars, NULL)) + || walk_gimple_op (stmt, find_va_list_reference, &wi)) { if (dump_file && (dump_flags & TDF_DETAILS)) { fputs ("va_list escapes in ", dump_file); - print_generic_expr (dump_file, stmt, dump_flags); + print_gimple_stmt (dump_file, stmt, 0, dump_flags); fputc ('\n', dump_file); } va_list_escapes = true; @@ -842,22 +898,25 @@ finish: 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 */ 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 /* letter */ + TODO_dump_func /* todo_flags_finish */ + } };