X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-stdarg.c;h=4e030b12fa9ca728c4f52eb0c3fa1d6be50223c1;hb=e80c6822beb7e2c86a1c4abf8658af24e68b8df2;hp=8a275295aa4158f52f92ae3b9251745abbda35eb;hpb=c039429494a2dec15ad4bf0b4a6d2fcc13ce8298;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c index 8a275295aa4..4e030b12fa9 100644 --- a/gcc/tree-stdarg.c +++ b/gcc/tree-stdarg.c @@ -1,5 +1,5 @@ /* Pass computing data for optimizing stdarg functions. - Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Jakub Jelinek This file is part of GCC. @@ -112,7 +112,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 +131,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) @@ -144,39 +147,32 @@ 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); + 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) == 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)) - { - 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; @@ -197,6 +193,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; @@ -207,32 +205,22 @@ 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); + 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) == 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)) - { - 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; } @@ -249,7 +237,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) @@ -444,13 +432,6 @@ 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) - || 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, DECL_UID (SSA_NAME_VAR (rhs)))) @@ -507,11 +488,12 @@ 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; FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_USES) @@ -520,16 +502,13 @@ check_all_va_list_escapes (struct stdarg_info *si) 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 (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) @@ -553,14 +532,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) - || 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, DECL_UID (SSA_NAME_VAR (lhs)))) @@ -576,7 +557,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; @@ -595,7 +576,7 @@ static bool gate_optimize_stdarg (void) { /* This optimization is only for stdarg functions. */ - return current_function_stdarg != 0; + return cfun->stdarg != 0; } @@ -608,7 +589,9 @@ 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; cfun->va_list_gpr_size = 0; cfun->va_list_fpr_size = 0; @@ -619,25 +602,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); - gcc_assert (is_gimple_reg_type (va_list_type_node) == va_list_simple_ptr); + 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; @@ -657,7 +640,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) { @@ -675,7 +658,7 @@ execute_optimize_stdarg (void) ap = TREE_OPERAND (ap, 0); } if (TYPE_MAIN_VARIANT (TREE_TYPE (ap)) - != TYPE_MAIN_VARIANT (va_list_type_node) + != TYPE_MAIN_VARIANT (targetm.fn_abi_va_list (cfun->decl)) || TREE_CODE (ap) != VAR_DECL) { va_list_escapes = true; @@ -733,10 +716,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; @@ -747,12 +732,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)) @@ -768,14 +754,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; @@ -784,18 +768,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 @@ -804,44 +786,54 @@ 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 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; } } @@ -853,13 +845,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; @@ -904,19 +895,21 @@ finish: } -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 */ + } };