Mercurial > hg > CbC > CbC_gcc
diff gcc/gimple-low.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
line wrap: on
line diff
--- a/gcc/gimple-low.c Sun Feb 07 18:28:00 2010 +0900 +++ b/gcc/gimple-low.c Fri Feb 12 23:39:51 2010 +0900 @@ -1,6 +1,6 @@ /* GIMPLE lowering pass. Converts High GIMPLE into Low GIMPLE. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -76,6 +76,9 @@ of the function. */ VEC(return_statements_t,heap) *return_statements; + /* True if the current statement cannot fall through. */ + bool cannot_fallthru; + /* True if the function calls __builtin_setjmp. */ bool calls_builtin_setjmp; }; @@ -169,7 +172,7 @@ tree disp_label, disp_var, arg; /* Build 'DISP_LABEL:' and insert. */ - disp_label = create_artificial_label (); + disp_label = create_artificial_label (cfun->function_end_locus); /* This mark will create forward edges from every call site. */ DECL_NONLOCAL (disp_label) = 1; cfun->has_nonlocal_label = 1; @@ -199,7 +202,7 @@ return 0; } -struct gimple_opt_pass pass_lower_cf = +struct gimple_opt_pass pass_lower_cf = { { GIMPLE_PASS, @@ -209,7 +212,7 @@ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - 0, /* tv_id */ + TV_NONE, /* tv_id */ PROP_gimple_any, /* properties_required */ PROP_gimple_lcf, /* properties_provided */ 0, /* properties_destroyed */ @@ -221,17 +224,14 @@ /* Verify if the type of the argument matches that of the function declaration. If we cannot verify this or there is a mismatch, - mark the call expression so it doesn't get inlined later. */ + return false. */ -static void -check_call_args (gimple stmt) +bool +gimple_check_call_args (gimple stmt) { tree fndecl, parms, p; unsigned int i, nargs; - if (gimple_call_cannot_inline_p (stmt)) - return; - nargs = gimple_call_num_args (stmt); /* Get argument types for verification. */ @@ -244,7 +244,7 @@ /* Verify if the type of the argument matches that of the function declaration. If we cannot verify this or there is a mismatch, - mark the call expression so it doesn't get inlined later. */ + return false. */ if (fndecl && DECL_ARGUMENTS (fndecl)) { for (i = 0, p = DECL_ARGUMENTS (fndecl); @@ -260,10 +260,7 @@ || gimple_call_arg (stmt, i) == error_mark_node || !fold_convertible_p (DECL_ARG_TYPE (p), gimple_call_arg (stmt, i))) - { - gimple_call_set_cannot_inline (stmt, true); - break; - } + return false; } } else if (parms) @@ -279,17 +276,15 @@ || TREE_CODE (TREE_VALUE (p)) == VOID_TYPE || !fold_convertible_p (TREE_VALUE (p), gimple_call_arg (stmt, i))) - { - gimple_call_set_cannot_inline (stmt, true); - break; - } + return false; } } else { if (nargs != 0) - gimple_call_set_cannot_inline (stmt, true); + return false; } + return true; } @@ -314,7 +309,7 @@ lower_omp_directive (gimple_stmt_iterator *gsi, struct lower_data *data) { gimple stmt; - + stmt = gsi_stmt (*gsi); lower_sequence (gimple_omp_body (stmt), data); @@ -325,7 +320,12 @@ } -/* Lower statement GSI. DATA is passed through the recursion. */ +/* Lower statement GSI. DATA is passed through the recursion. We try to + track the fallthruness of statements and get rid of unreachable return + statements in order to prevent the EH lowering pass from adding useless + edges that can cause bogus warnings to be issued later; this guess need + not be 100% accurate, simply be conservative and reset cannot_fallthru + to false if we don't know. */ static void lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) @@ -338,37 +338,62 @@ { case GIMPLE_BIND: lower_gimple_bind (gsi, data); + /* Propagate fallthruness. */ return; case GIMPLE_COND: - /* The gimplifier has already lowered this into gotos. */ - break; + case GIMPLE_GOTO: + case GIMPLE_SWITCH: + data->cannot_fallthru = true; + gsi_next (gsi); + return; case GIMPLE_RETURN: - lower_gimple_return (gsi, data); + if (data->cannot_fallthru) + { + gsi_remove (gsi, false); + /* Propagate fallthruness. */ + } + else + { + lower_gimple_return (gsi, data); + data->cannot_fallthru = true; + } return; case GIMPLE_TRY: - lower_sequence (gimple_try_eval (stmt), data); - lower_sequence (gimple_try_cleanup (stmt), data); + { + bool try_cannot_fallthru; + lower_sequence (gimple_try_eval (stmt), data); + try_cannot_fallthru = data->cannot_fallthru; + data->cannot_fallthru = false; + lower_sequence (gimple_try_cleanup (stmt), data); + /* See gimple_stmt_may_fallthru for the rationale. */ + if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY) + { + data->cannot_fallthru |= try_cannot_fallthru; + gsi_next (gsi); + return; + } + } break; case GIMPLE_CATCH: + data->cannot_fallthru = false; lower_sequence (gimple_catch_handler (stmt), data); break; case GIMPLE_EH_FILTER: + data->cannot_fallthru = false; lower_sequence (gimple_eh_filter_failure (stmt), data); break; case GIMPLE_NOP: case GIMPLE_ASM: case GIMPLE_ASSIGN: - case GIMPLE_GOTO: case GIMPLE_PREDICT: case GIMPLE_LABEL: - case GIMPLE_SWITCH: - case GIMPLE_CHANGE_DYNAMIC_TYPE: + case GIMPLE_EH_MUST_NOT_THROW: case GIMPLE_OMP_FOR: case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SECTIONS_SWITCH: @@ -391,23 +416,33 @@ && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (decl) == BUILT_IN_SETJMP) { + lower_builtin_setjmp (gsi); + data->cannot_fallthru = false; data->calls_builtin_setjmp = true; - lower_builtin_setjmp (gsi); return; } - check_call_args (stmt); + + if (decl && (flags_from_decl_or_type (decl) & ECF_NORETURN)) + { + data->cannot_fallthru = true; + gsi_next (gsi); + return; + } } break; case GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TASK: + data->cannot_fallthru = false; lower_omp_directive (gsi, data); + data->cannot_fallthru = false; return; default: gcc_unreachable (); } + data->cannot_fallthru = false; gsi_next (gsi); } @@ -507,8 +542,8 @@ default: /* This case represents statements to be executed when an exception occurs. Those statements are implicitly followed - by a RESX_EXPR to resume execution after the exception. So - in this case the TRY_CATCH never falls through. */ + by a RESX statement to resume execution after the exception. + So in this case the TRY_CATCH never falls through. */ return false; } } @@ -581,8 +616,7 @@ { case GOTO_EXPR: case RETURN_EXPR: - case RESX_EXPR: - /* Easy cases. If the last statement of the block implies + /* Easy cases. If the last statement of the block implies control transfer, then we can't fall through. */ return false; @@ -625,7 +659,7 @@ case CALL_EXPR: /* Functions that do not return do not fall through. */ return (call_expr_flags (stmt) & ECF_NORETURN) == 0; - + case CLEANUP_POINT_EXPR: return block_may_fallthru (TREE_OPERAND (stmt, 0)); @@ -652,14 +686,14 @@ case GIMPLE_GOTO: case GIMPLE_RETURN: case GIMPLE_RESX: - /* Easy cases. If the last statement of the seq implies + /* Easy cases. If the last statement of the seq implies control transfer, then we can't fall through. */ return false; case GIMPLE_SWITCH: - /* Switch has already been lowered and represents a - branch to a selected label and hence can not fall through. */ - return true; + /* Switch has already been lowered and represents a branch + to a selected label and hence can't fall through. */ + return false; case GIMPLE_COND: /* GIMPLE_COND's are already lowered into a two-way branch. They @@ -685,13 +719,10 @@ return (gimple_seq_may_fallthru (gimple_try_eval (stmt)) && gimple_seq_may_fallthru (gimple_try_cleanup (stmt))); - case GIMPLE_ASSIGN: - return true; - case GIMPLE_CALL: /* Functions that do not return do not fall through. */ return (gimple_call_flags (stmt) & ECF_NORETURN) == 0; - + default: return true; } @@ -728,7 +759,7 @@ } /* Not found. Create a new label and record the return statement. */ - tmp_rs.label = create_artificial_label (); + tmp_rs.label = create_artificial_label (cfun->function_end_locus); tmp_rs.stmt = stmt; VEC_safe_push (return_statements_t, heap, data->return_statements, &tmp_rs); @@ -741,7 +772,7 @@ gsi_remove (gsi, false); } -/* Lower a __builtin_setjmp TSI. +/* Lower a __builtin_setjmp GSI. __builtin_setjmp is passed a pointer to an array of five words (not all will be used on all machines). It operates similarly to the C @@ -798,8 +829,9 @@ lower_builtin_setjmp (gimple_stmt_iterator *gsi) { gimple stmt = gsi_stmt (*gsi); - tree cont_label = create_artificial_label (); - tree next_label = create_artificial_label (); + location_t loc = gimple_location (stmt); + tree cont_label = create_artificial_label (loc); + tree next_label = create_artificial_label (loc); tree dest, t, arg; gimple g; @@ -813,23 +845,23 @@ arg = build_addr (next_label, current_function_decl); t = implicit_built_in_decls[BUILT_IN_SETJMP_SETUP]; g = gimple_build_call (t, 2, gimple_call_arg (stmt, 0), arg); - gimple_set_location (g, gimple_location (stmt)); + gimple_set_location (g, loc); gimple_set_block (g, gimple_block (stmt)); gsi_insert_before (gsi, g, GSI_SAME_STMT); /* Build 'DEST = 0' and insert. */ if (dest) { - g = gimple_build_assign (dest, fold_convert (TREE_TYPE (dest), - integer_zero_node)); - gimple_set_location (g, gimple_location (stmt)); + g = gimple_build_assign (dest, fold_convert_loc (loc, TREE_TYPE (dest), + integer_zero_node)); + gimple_set_location (g, loc); gimple_set_block (g, gimple_block (stmt)); gsi_insert_before (gsi, g, GSI_SAME_STMT); } /* Build 'goto CONT_LABEL' and insert. */ g = gimple_build_goto (cont_label); - gsi_insert_before (gsi, g, TSI_SAME_STMT); + gsi_insert_before (gsi, g, GSI_SAME_STMT); /* Build 'NEXT_LABEL:' and insert. */ g = gimple_build_label (next_label); @@ -839,16 +871,16 @@ arg = build_addr (next_label, current_function_decl); t = implicit_built_in_decls[BUILT_IN_SETJMP_RECEIVER]; g = gimple_build_call (t, 1, arg); - gimple_set_location (g, gimple_location (stmt)); + gimple_set_location (g, loc); gimple_set_block (g, gimple_block (stmt)); gsi_insert_before (gsi, g, GSI_SAME_STMT); /* Build 'DEST = 1' and insert. */ if (dest) { - g = gimple_build_assign (dest, fold_convert (TREE_TYPE (dest), - integer_one_node)); - gimple_set_location (g, gimple_location (stmt)); + g = gimple_build_assign (dest, fold_convert_loc (loc, TREE_TYPE (dest), + integer_one_node)); + gimple_set_location (g, loc); gimple_set_block (g, gimple_block (stmt)); gsi_insert_before (gsi, g, GSI_SAME_STMT); } @@ -900,61 +932,3 @@ { record_vars_into (vars, current_function_decl); } - - -/* Mark BLOCK used if it has a used variable in it, then recurse over its - subblocks. */ - -static void -mark_blocks_with_used_vars (tree block) -{ - tree var; - tree subblock; - - if (!TREE_USED (block)) - { - for (var = BLOCK_VARS (block); - var; - var = TREE_CHAIN (var)) - { - if (TREE_USED (var)) - { - TREE_USED (block) = true; - break; - } - } - } - for (subblock = BLOCK_SUBBLOCKS (block); - subblock; - subblock = BLOCK_CHAIN (subblock)) - mark_blocks_with_used_vars (subblock); -} - -/* Mark the used attribute on blocks correctly. */ - -static unsigned int -mark_used_blocks (void) -{ - mark_blocks_with_used_vars (DECL_INITIAL (current_function_decl)); - return 0; -} - - -struct gimple_opt_pass pass_mark_used_blocks = -{ - { - GIMPLE_PASS, - "blocks", /* name */ - NULL, /* gate */ - mark_used_blocks, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - 0, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_dump_func /* todo_flags_finish */ - } -};