X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-stdarg.c;h=9b7a126b1ef4bc8e2b2319d1b98d4777eb571f87;hb=176ff0f9a1016553978d6cf41770703e2ad90958;hp=f9228872dc2c6379c240f61dad51c68b7f7cdb7f;hpb=92667ff7f2525ea5d9422fb2e7a472bbf0386020;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c index f9228872dc2..9b7a126b1ef 100644 --- a/gcc/tree-stdarg.c +++ b/gcc/tree-stdarg.c @@ -1,5 +1,6 @@ /* 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, 2011 + Free Software Foundation, Inc. Contributed by Jakub Jelinek This file is part of GCC. @@ -25,7 +26,7 @@ along with GCC; see the file COPYING3. If not see #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" @@ -112,7 +113,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; @@ -130,6 +132,9 @@ va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, orig_lhs = lhs = rhs; while (lhs) { + enum tree_code rhs_code; + tree rhs1; + if (si->offsets[SSA_NAME_VERSION (lhs)] != -1) { if (counter_val >= max_size) @@ -144,38 +149,43 @@ va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, stmt = SSA_NAME_DEF_STMT (lhs); - if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT - || GIMPLE_STMT_OPERAND (stmt, 0) != lhs) + if (!is_gimple_assign (stmt) || gimple_assign_lhs (stmt) != lhs) return (unsigned HOST_WIDE_INT) -1; - rhs = GIMPLE_STMT_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); + rhs1 = gimple_assign_rhs1 (stmt); + if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS + || gimple_assign_cast_p (stmt)) + && TREE_CODE (rhs1) == SSA_NAME) { - lhs = rhs; + lhs = rhs1; continue; } - if (CONVERT_EXPR_P (rhs) - && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME) + if ((rhs_code == POINTER_PLUS_EXPR + || rhs_code == PLUS_EXPR) + && TREE_CODE (rhs1) == SSA_NAME + && host_integerp (gimple_assign_rhs2 (stmt), 1)) { - lhs = TREE_OPERAND (rhs, 0); + ret += tree_low_cst (gimple_assign_rhs2 (stmt), 1); + lhs = rhs1; continue; } - 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 (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 (rhs, 1), 1); - lhs = TREE_OPERAND (rhs, 0); + ret += tree_low_cst (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1); + lhs = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 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; @@ -196,6 +206,9 @@ va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, val = ret + counter_val; while (lhs) { + enum tree_code rhs_code; + tree rhs1; + if (si->offsets[SSA_NAME_VERSION (lhs)] != -1) break; @@ -206,31 +219,33 @@ va_list_counter_bump (struct stdarg_info *si, tree counter, tree rhs, stmt = SSA_NAME_DEF_STMT (lhs); - rhs = GIMPLE_STMT_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); + rhs1 = gimple_assign_rhs1 (stmt); + if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS + || gimple_assign_cast_p (stmt)) + && TREE_CODE (rhs1) == SSA_NAME) { - lhs = rhs; + lhs = rhs1; continue; } - if (CONVERT_EXPR_P (rhs) - && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME) + if ((rhs_code == POINTER_PLUS_EXPR + || rhs_code == PLUS_EXPR) + && TREE_CODE (rhs1) == SSA_NAME + && host_integerp (gimple_assign_rhs2 (stmt), 1)) { - lhs = TREE_OPERAND (rhs, 0); + val -= tree_low_cst (gimple_assign_rhs2 (stmt), 1); + lhs = rhs1; continue; } - 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 (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 (rhs, 1), 1); - lhs = TREE_OPERAND (rhs, 0); + val -= tree_low_cst (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1); + lhs = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0); continue; } @@ -247,7 +262,7 @@ 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) @@ -442,15 +457,22 @@ check_va_list_escapes (struct stdarg_info *si, tree lhs, tree rhs) if (! POINTER_TYPE_P (TREE_TYPE (rhs))) return; - 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 - || ! 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))) @@ -504,29 +526,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, DECL_UID (SSA_NAME_VAR (use)))) continue; - if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT) + if (is_gimple_assign (stmt)) { - 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); + 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 (rhs_code == MEM_REF && TREE_OPERAND (rhs, 0) == use && TYPE_SIZE_UNIT (TREE_TYPE (rhs)) && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), 1) @@ -536,6 +559,7 @@ check_all_va_list_escapes (struct stdarg_info *si) 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; @@ -550,13 +574,16 @@ check_all_va_list_escapes (struct stdarg_info *si) other_ap_temp = (some_type *) ap_temp; ap = ap_temp; statements. */ - if ((TREE_CODE (rhs) == POINTER_PLUS_EXPR - && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST) - || CONVERT_EXPR_P (rhs)) - 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, DECL_UID (SSA_NAME_VAR (lhs)))) @@ -567,12 +594,22 @@ check_all_va_list_escapes (struct stdarg_info *si) 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)) { 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; @@ -604,6 +641,7 @@ execute_optimize_stdarg (void) 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; @@ -624,18 +662,17 @@ execute_optimize_stdarg (void) 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; @@ -646,7 +683,6 @@ execute_optimize_stdarg (void) 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; @@ -655,7 +691,7 @@ execute_optimize_stdarg (void) } si.va_start_count++; - ap = CALL_EXPR_ARG (call, 0); + ap = gimple_call_arg (stmt, 0); if (TREE_CODE (ap) != ADDR_EXPR) { @@ -731,10 +767,12 @@ execute_optimize_stdarg (void) 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; @@ -745,12 +783,13 @@ execute_optimize_stdarg (void) any real data movement. */ if (va_list_simple_ptr) { - tree phi, lhs, rhs; + tree lhs, rhs; use_operand_p uop; ssa_op_iter soi; - for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) + 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)) @@ -766,14 +805,12 @@ execute_optimize_stdarg (void) 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 (si.va_list_escapes) { if (dump_file && (dump_flags & TDF_DETAILS)) { fputs ("va_list escapes in ", dump_file); - print_generic_expr (dump_file, phi, dump_flags); + print_gimple_stmt (dump_file, phi, 0, dump_flags); fputc ('\n', dump_file); } va_list_escapes = true; @@ -782,18 +819,16 @@ execute_optimize_stdarg (void) } } - for (i = bsi_start (bb); - !bsi_end_p (i) && !va_list_escapes; - bsi_next (&i)) + for (i = gsi_start_bb (bb); + !gsi_end_p (i) && !va_list_escapes; + gsi_next (&i)) { - tree stmt = bsi_stmt (i); - tree call; + 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 @@ -802,47 +837,67 @@ execute_optimize_stdarg (void) continue; } - if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT) + if (is_gimple_assign (stmt)) { - 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); + 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 ap ={v} {}. */ + if (TREE_CLOBBER_P (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; + /* Check for tem = ap. */ + else if (va_list_ptr_read (&si, rhs, lhs)) + continue; - else + /* Check for the last insn in: + tem1 = ap; + tem2 = tem1 + CST; + ap = tem2; + sequence. */ + else if (va_list_ptr_write (&si, lhs, rhs)) + continue; + } + + 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 ={v} {}. */ + if (TREE_CLOBBER_P (rhs)) + continue; - /* Check for temp = ap[0].field. */ - else if (va_list_counter_struct_op (&si, rhs, lhs, false)) - continue; + /* Check for ap[0].field = temp. */ + else 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; + } /* 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 @@ -851,13 +906,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; @@ -912,11 +966,11 @@ struct gimple_opt_pass pass_stdarg = 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 */ } };