diff options
author | Martin Jambor <mjambor@suse.cz> | 2010-05-04 19:34:01 +0200 |
---|---|---|
committer | Martin Jambor <jamborm@gcc.gnu.org> | 2010-05-04 19:34:01 +0200 |
commit | 6cbd3b6a699912ff879d13c0fb5ab3f4b244943f (patch) | |
tree | fbf0e8c6815f54c2f72fc7d9a758ef50fc3da37e | |
parent | ed24bfdf685375d4f82f7da01c3233e8f0898b88 (diff) | |
download | gcc-6cbd3b6a699912ff879d13c0fb5ab3f4b244943f.zip gcc-6cbd3b6a699912ff879d13c0fb5ab3f4b244943f.tar.gz gcc-6cbd3b6a699912ff879d13c0fb5ab3f4b244943f.tar.bz2 |
tree-sra.c (build_access_from_expr_1): The first parameter type changed to simple tree.
2010-05-04 Martin Jambor <mjambor@suse.cz>
* tree-sra.c (build_access_from_expr_1): The first parameter type
changed to simple tree.
(build_access_from_expr): Likewise, gsi parameter was eliminated.
(scan_assign_result): Renamed to assignment_mod_result, enum elements
renamed as well.
(build_accesses_from_assign): Removed all parameters except for a
simple gimple statement. Now returns a simple bool.
(scan_function): All non-analysis parts moved to separate functions
sra_modify_function_body and ipa_sra_modify_function_body. Removed all
parameters and updated both callers.
(sra_modify_expr): Removed parameter data.
(sra_modify_function_body): New function.
(perform_intra_sra): Call sra_modify_function_body to modify the
function body.
(replace_removed_params_ssa_names): Parameter data changed into
adjustments vector.
(sra_ipa_modify_expr): Likewise. Also removed unused parameter gsi and
changed the parameter dont_convert to convert with the opposite
meaning.
(sra_ipa_modify_assign): Parameter data changed into adjustments
vector, return value changed to bool.
(ipa_sra_modify_function_body): New function.
(sra_ipa_reset_debug_stmts): Updated a comment.
(modify_function): Use ipa_sra_modify_function_body to modify function
body.
From-SVN: r159038
-rw-r--r-- | gcc/ChangeLog | 28 | ||||
-rw-r--r-- | gcc/tree-sra.c | 468 |
2 files changed, 303 insertions, 193 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a93e111..41139cb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2010-05-04 Martin Jambor <mjambor@suse.cz> + + * tree-sra.c (build_access_from_expr_1): The first parameter type + changed to simple tree. + (build_access_from_expr): Likewise, gsi parameter was eliminated. + (scan_assign_result): Renamed to assignment_mod_result, enum elements + renamed as well. + (build_accesses_from_assign): Removed all parameters except for a + simple gimple statement. Now returns a simple bool. + (scan_function): All non-analysis parts moved to separate functions + sra_modify_function_body and ipa_sra_modify_function_body. Removed all + parameters and updated both callers. + (sra_modify_expr): Removed parameter data. + (sra_modify_function_body): New function. + (perform_intra_sra): Call sra_modify_function_body to modify the + function body. + (replace_removed_params_ssa_names): Parameter data changed into + adjustments vector. + (sra_ipa_modify_expr): Likewise. Also removed unused parameter gsi and + changed the parameter dont_convert to convert with the opposite + meaning. + (sra_ipa_modify_assign): Parameter data changed into adjustments + vector, return value changed to bool. + (ipa_sra_modify_function_body): New function. + (sra_ipa_reset_debug_stmts): Updated a comment. + (modify_function): Use ipa_sra_modify_function_body to modify function + body. + 2010-05-04 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/43671 diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 1bfb5c2..166338f 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -903,10 +903,9 @@ disqualify_base_of_expr (tree t, const char *reason) created. */ static struct access * -build_access_from_expr_1 (tree *expr_ptr, gimple stmt, bool write) +build_access_from_expr_1 (tree expr, gimple stmt, bool write) { struct access *ret = NULL; - tree expr = *expr_ptr; bool partial_ref; if (TREE_CODE (expr) == BIT_FIELD_REF @@ -958,18 +957,17 @@ build_access_from_expr_1 (tree *expr_ptr, gimple stmt, bool write) return ret; } -/* Callback of scan_function. Scan expression EXPR and create access - structures for all accesses to candidates for scalarization. Return true if - any access has been inserted. */ +/* Scan expression EXPR and create access structures for all accesses to + candidates for scalarization. Return true if any access has been inserted. + STMT must be the statement from which the expression is taken, WRITE must be + true if the expression is a store and false otherwise. */ static bool -build_access_from_expr (tree *expr_ptr, - gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, bool write, - void *data ATTRIBUTE_UNUSED) +build_access_from_expr (tree expr, gimple stmt, bool write) { struct access *access; - access = build_access_from_expr_1 (expr_ptr, gsi_stmt (*gsi), write); + access = build_access_from_expr_1 (expr, stmt, write); if (access) { /* This means the aggregate is accesses as a whole in a way other than an @@ -1001,39 +999,28 @@ disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs) return false; } - -/* Result code for scan_assign callback for scan_function. */ -enum scan_assign_result { SRA_SA_NONE, /* nothing done for the stmt */ - SRA_SA_PROCESSED, /* stmt analyzed/changed */ - SRA_SA_REMOVED }; /* stmt redundant and eliminated */ - - -/* Callback of scan_function. Scan expressions occuring in the statement - pointed to by STMT_EXPR, create access structures for all accesses to - candidates for scalarization and remove those candidates which occur in +/* Scan expressions occuring in STMT, create access structures for all accesses + to candidates for scalarization and remove those candidates which occur in statements or expressions that prevent them from being split apart. Return true if any access has been inserted. */ -static enum scan_assign_result -build_accesses_from_assign (gimple *stmt_ptr, - gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) +static bool +build_accesses_from_assign (gimple stmt) { - gimple stmt = *stmt_ptr; - tree *lhs_ptr, *rhs_ptr; + tree lhs, rhs; struct access *lacc, *racc; if (!gimple_assign_single_p (stmt)) - return SRA_SA_NONE; + return false; - lhs_ptr = gimple_assign_lhs_ptr (stmt); - rhs_ptr = gimple_assign_rhs1_ptr (stmt); + lhs = gimple_assign_lhs (stmt); + rhs = gimple_assign_rhs1 (stmt); - if (disqualify_ops_if_throwing_stmt (stmt, *lhs_ptr, *rhs_ptr)) - return SRA_SA_NONE; + if (disqualify_ops_if_throwing_stmt (stmt, lhs, rhs)) + return false; - racc = build_access_from_expr_1 (rhs_ptr, stmt, false); - lacc = build_access_from_expr_1 (lhs_ptr, stmt, true); + racc = build_access_from_expr_1 (rhs, stmt, false); + lacc = build_access_from_expr_1 (lhs, stmt, true); if (racc) { @@ -1047,7 +1034,7 @@ build_accesses_from_assign (gimple *stmt_ptr, && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA) && !lacc->grp_unscalarizable_region && !racc->grp_unscalarizable_region - && AGGREGATE_TYPE_P (TREE_TYPE (*lhs_ptr)) + && AGGREGATE_TYPE_P (TREE_TYPE (lhs)) /* FIXME: Turn the following line into an assert after PR 40058 is fixed. */ && lacc->size == racc->size @@ -1064,7 +1051,7 @@ build_accesses_from_assign (gimple *stmt_ptr, add_link_to_rhs (racc, link); } - return (lacc || racc) ? SRA_SA_PROCESSED : SRA_SA_NONE; + return lacc || racc; } /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine @@ -1091,76 +1078,46 @@ callsite_has_enough_arguments_p (gimple call) return gimple_call_num_args (call) >= (unsigned) func_param_count; } -/* Scan function and look for interesting statements. Return true if any has - been found or processed, as indicated by callbacks. SCAN_EXPR is a callback - called on all expressions within statements except assign statements and - those deemed entirely unsuitable for some reason (all operands in such - statements and expression are removed from candidate_bitmap). SCAN_ASSIGN - is a callback called on all assign statements, HANDLE_SSA_DEFS is a callback - called on assign statements and those call statements which have a lhs, it - can be NULL. ANALYSIS_STAGE is true when running in the analysis stage of a - pass and thus no statement is being modified. DATA is a pointer passed to - all callbacks. If any single callback returns true, this function also - returns true, otherwise it returns false. */ +/* Scan function and look for interesting expressions and create access + structures for them. Return true iff any access is created. */ static bool -scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *), - enum scan_assign_result (*scan_assign) (gimple *, - gimple_stmt_iterator *, - void *), - bool (*handle_ssa_defs)(gimple, void *), - bool analysis_stage, void *data) +scan_function (void) { - gimple_stmt_iterator gsi; basic_block bb; - unsigned i; - tree *t; bool ret = false; FOR_EACH_BB (bb) { - bool bb_changed = false; - - if (handle_ssa_defs) - for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - ret |= handle_ssa_defs (gsi_stmt (gsi), data); - - gsi = gsi_start_bb (bb); - while (!gsi_end_p (gsi)) + gimple_stmt_iterator gsi; + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); - enum scan_assign_result assign_result; - bool any = false, deleted = false; + tree t; + unsigned i; - if (analysis_stage && final_bbs && stmt_can_throw_external (stmt)) + if (final_bbs && stmt_can_throw_external (stmt)) bitmap_set_bit (final_bbs, bb->index); switch (gimple_code (stmt)) { case GIMPLE_RETURN: - t = gimple_return_retval_ptr (stmt); - if (*t != NULL_TREE) - any |= scan_expr (t, &gsi, false, data); - if (analysis_stage && final_bbs) + t = gimple_return_retval (stmt); + if (t != NULL_TREE) + ret |= build_access_from_expr (t, stmt, false); + if (final_bbs) bitmap_set_bit (final_bbs, bb->index); break; case GIMPLE_ASSIGN: - assign_result = scan_assign (&stmt, &gsi, data); - any |= assign_result == SRA_SA_PROCESSED; - deleted = assign_result == SRA_SA_REMOVED; - if (handle_ssa_defs && assign_result != SRA_SA_REMOVED) - any |= handle_ssa_defs (stmt, data); + ret |= build_accesses_from_assign (stmt); break; case GIMPLE_CALL: - /* Operands must be processed before the lhs. */ for (i = 0; i < gimple_call_num_args (stmt); i++) - { - tree *argp = gimple_call_arg_ptr (stmt, i); - any |= scan_expr (argp, &gsi, false, data); - } + ret |= build_access_from_expr (gimple_call_arg (stmt, i), + stmt, false); - if (analysis_stage && sra_mode == SRA_MODE_EARLY_IPA) + if (sra_mode == SRA_MODE_EARLY_IPA) { tree dest = gimple_call_fndecl (stmt); int flags = gimple_call_flags (stmt); @@ -1184,65 +1141,33 @@ scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *), bitmap_set_bit (final_bbs, bb->index); } - if (gimple_call_lhs (stmt)) - { - tree *lhs_ptr = gimple_call_lhs_ptr (stmt); - if (!analysis_stage - || !disqualify_ops_if_throwing_stmt (stmt, - *lhs_ptr, NULL)) - { - any |= scan_expr (lhs_ptr, &gsi, true, data); - if (handle_ssa_defs) - any |= handle_ssa_defs (stmt, data); - } - } + t = gimple_call_lhs (stmt); + if (t && !disqualify_ops_if_throwing_stmt (stmt, t, NULL)) + ret |= build_access_from_expr (t, stmt, true); break; case GIMPLE_ASM: - if (analysis_stage) - { - walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL, - asm_visit_addr); - if (final_bbs) - bitmap_set_bit (final_bbs, bb->index); - } + walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL, + asm_visit_addr); + if (final_bbs) + bitmap_set_bit (final_bbs, bb->index); + for (i = 0; i < gimple_asm_ninputs (stmt); i++) { - tree *op = &TREE_VALUE (gimple_asm_input_op (stmt, i)); - any |= scan_expr (op, &gsi, false, data); + t = TREE_VALUE (gimple_asm_input_op (stmt, i)); + ret |= build_access_from_expr (t, stmt, false); } for (i = 0; i < gimple_asm_noutputs (stmt); i++) { - tree *op = &TREE_VALUE (gimple_asm_output_op (stmt, i)); - any |= scan_expr (op, &gsi, true, data); + t = TREE_VALUE (gimple_asm_output_op (stmt, i)); + ret |= build_access_from_expr (t, stmt, true); } break; default: break; } - - if (any) - { - ret = true; - - if (!analysis_stage) - { - bb_changed = true; - update_stmt (stmt); - maybe_clean_eh_stmt (stmt); - } - } - if (deleted) - bb_changed = true; - else - { - gsi_next (&gsi); - ret = true; - } } - if (!analysis_stage && bb_changed && sra_mode == SRA_MODE_EARLY_IPA) - gimple_purge_dead_eh_edges (bb); } return ret; @@ -2300,15 +2225,14 @@ get_access_for_expr (tree expr) return get_var_base_offset_size_access (base, offset, max_size); } -/* Callback for scan_function. Replace the expression EXPR with a scalar - replacement if there is one and generate other statements to do type - conversion or subtree copying if necessary. GSI is used to place newly - created statements, WRITE is true if the expression is being written to (it - is on a LHS of a statement or output in an assembly statement). */ +/* Replace the expression EXPR with a scalar replacement if there is one and + generate other statements to do type conversion or subtree copying if + necessary. GSI is used to place newly created statements, WRITE is true if + the expression is being written to (it is on a LHS of a statement or output + in an assembly statement). */ static bool -sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write, - void *data ATTRIBUTE_UNUSED) +sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) { struct access *access; tree type, bfr; @@ -2510,11 +2434,17 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc, while (lacc); } +/* Result code for SRA assignment modification. */ +enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */ + SRA_AM_MODIFIED, /* stmt changed but not + removed */ + SRA_AM_REMOVED }; /* stmt eliminated */ + /* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer to the assignment and GSI is the statement iterator pointing at it. Returns the same values as sra_modify_assign. */ -static enum scan_assign_result +static enum assignment_mod_result sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi) { tree lhs = gimple_assign_lhs (*stmt); @@ -2522,7 +2452,7 @@ sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi) acc = get_access_for_expr (lhs); if (!acc) - return SRA_SA_NONE; + return SRA_AM_NONE; if (VEC_length (constructor_elt, CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0) @@ -2532,7 +2462,7 @@ sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi) if (access_has_children_p (acc)) generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi, true, true); - return SRA_SA_PROCESSED; + return SRA_AM_MODIFIED; } if (acc->grp_covered) @@ -2540,12 +2470,12 @@ sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi) init_subtree_with_zero (acc, gsi, false); unlink_stmt_vdef (*stmt); gsi_remove (gsi, true); - return SRA_SA_REMOVED; + return SRA_AM_REMOVED; } else { init_subtree_with_zero (acc, gsi, true); - return SRA_SA_PROCESSED; + return SRA_AM_MODIFIED; } } @@ -2578,16 +2508,14 @@ replace_uses_with_default_def_ssa_name (tree ssa) replace_uses_by (ssa, repl); } -/* Callback of scan_function to process assign statements. It examines both - sides of the statement, replaces them with a scalare replacement if there is - one and generating copying of replacements if scalarized aggregates have been - used in the assignment. STMT is a pointer to the assign statement, GSI is - used to hold generated statements for type conversions and subtree +/* Examine both sides of the assignment statement pointed to by STMT, replace + them with a scalare replacement if there is one and generate copying of + replacements if scalarized aggregates have been used in the assignment. GSI + is used to hold generated statements for type conversions and subtree copying. */ -static enum scan_assign_result -sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, - void *data ATTRIBUTE_UNUSED) +static enum assignment_mod_result +sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) { struct access *lacc, *racc; tree lhs, rhs; @@ -2597,7 +2525,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, gimple_stmt_iterator orig_gsi = *gsi; if (!gimple_assign_single_p (*stmt)) - return SRA_SA_NONE; + return SRA_AM_NONE; lhs = gimple_assign_lhs (*stmt); rhs = gimple_assign_rhs1 (*stmt); @@ -2609,16 +2537,16 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF) { modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt), - gsi, false, data); + gsi, false); modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt), - gsi, true, data); - return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE; + gsi, true); + return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE; } lacc = get_access_for_expr (lhs); racc = get_access_for_expr (rhs); if (!lacc && !racc) - return SRA_SA_NONE; + return SRA_AM_NONE; if (lacc && lacc->grp_to_be_replaced) { @@ -2747,7 +2675,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, unlink_stmt_vdef (*stmt); gsi_remove (&orig_gsi, true); sra_stats.deleted++; - return SRA_SA_REMOVED; + return SRA_AM_REMOVED; } } else @@ -2767,7 +2695,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, unlink_stmt_vdef (*stmt); gsi_remove (gsi, true); sra_stats.deleted++; - return SRA_SA_REMOVED; + return SRA_AM_REMOVED; } else if (racc->first_child) generate_subtree_copies (racc->first_child, lhs, @@ -2790,7 +2718,83 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, gcc_assert (*stmt == gsi_stmt (orig_gsi)); } - return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE; + return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE; +} + +/* Traverse the function body and all modifications as decided in + analyze_all_variable_accesses. */ + +static void +sra_modify_function_body (void) +{ + basic_block bb; + + FOR_EACH_BB (bb) + { + gimple_stmt_iterator gsi = gsi_start_bb (bb); + while (!gsi_end_p (gsi)) + { + gimple stmt = gsi_stmt (gsi); + enum assignment_mod_result assign_result; + bool modified = false, deleted = false; + tree *t; + unsigned i; + + switch (gimple_code (stmt)) + { + case GIMPLE_RETURN: + t = gimple_return_retval_ptr (stmt); + if (*t != NULL_TREE) + modified |= sra_modify_expr (t, &gsi, false); + break; + + case GIMPLE_ASSIGN: + assign_result = sra_modify_assign (&stmt, &gsi); + modified |= assign_result == SRA_AM_MODIFIED; + deleted = assign_result == SRA_AM_REMOVED; + break; + + case GIMPLE_CALL: + /* Operands must be processed before the lhs. */ + for (i = 0; i < gimple_call_num_args (stmt); i++) + { + t = gimple_call_arg_ptr (stmt, i); + modified |= sra_modify_expr (t, &gsi, false); + } + + if (gimple_call_lhs (stmt)) + { + t = gimple_call_lhs_ptr (stmt); + modified |= sra_modify_expr (t, &gsi, true); + } + break; + + case GIMPLE_ASM: + for (i = 0; i < gimple_asm_ninputs (stmt); i++) + { + t = &TREE_VALUE (gimple_asm_input_op (stmt, i)); + modified |= sra_modify_expr (t, &gsi, false); + } + for (i = 0; i < gimple_asm_noutputs (stmt); i++) + { + t = &TREE_VALUE (gimple_asm_output_op (stmt, i)); + modified |= sra_modify_expr (t, &gsi, true); + } + break; + + default: + break; + } + + if (modified) + { + update_stmt (stmt); + maybe_clean_eh_stmt (stmt); + } + if (!deleted) + gsi_next (&gsi); + } + } } /* Generate statements initializing scalar replacements of parts of function @@ -2844,14 +2848,13 @@ perform_intra_sra (void) if (!find_var_candidates ()) goto out; - if (!scan_function (build_access_from_expr, build_accesses_from_assign, NULL, - true, NULL)) + if (!scan_function ()) goto out; if (!analyze_all_variable_accesses ()) goto out; - scan_function (sra_modify_expr, sra_modify_assign, NULL, false, NULL); + sra_modify_function_body (); initialize_parameter_reductions (); statistics_counter_event (cfun, "Scalar replacements created", @@ -3786,20 +3789,18 @@ get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base) return NULL; } -/* Callback for scan_function. If the statement STMT defines an SSA_NAME of a - parameter which is to be removed because its value is not used, replace the - SSA_NAME with a one relating to a created VAR_DECL and replace all of its - uses too and return true (update_stmt is then issued for the statement by - the caller). DATA is a pointer to an adjustments vector. */ +/* If the statement STMT defines an SSA_NAME of a parameter which is to be + removed because its value is not used, replace the SSA_NAME with a one + relating to a created VAR_DECL together all of its uses and return true. + ADJUSTMENTS is a pointer to an adjustments vector. */ static bool -replace_removed_params_ssa_names (gimple stmt, void *data) +replace_removed_params_ssa_names (gimple stmt, + ipa_parm_adjustment_vec adjustments) { - VEC (ipa_parm_adjustment_t, heap) *adjustments; struct ipa_parm_adjustment *adj; tree lhs, decl, repl, name; - adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data; if (gimple_code (stmt) == GIMPLE_PHI) lhs = gimple_phi_result (stmt); else if (is_gimple_assign (stmt)) @@ -3842,27 +3843,22 @@ replace_removed_params_ssa_names (gimple stmt, void *data) return true; } -/* Callback for scan_function and helper to sra_ipa_modify_assign. If the - expression *EXPR should be replaced by a reduction of a parameter, do so. - DATA is a pointer to a vector of adjustments. DONT_CONVERT specifies - whether the function should care about type incompatibility the current and - new expressions. If it is true, the function will leave incompatibility - issues to the caller. - - When called directly by scan_function, DONT_CONVERT is true when the EXPR is - a write (LHS) expression. */ +/* If the expression *EXPR should be replaced by a reduction of a parameter, do + so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT + specifies whether the function should care about type incompatibility the + current and new expressions. If it is false, the function will leave + incompatibility issues to the caller. Return true iff the expression + was modified. */ static bool -sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, - bool dont_convert, void *data) +sra_ipa_modify_expr (tree *expr, bool convert, + ipa_parm_adjustment_vec adjustments) { - ipa_parm_adjustment_vec adjustments; int i, len; struct ipa_parm_adjustment *adj, *cand = NULL; HOST_WIDE_INT offset, size, max_size; tree base, src; - adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data; len = VEC_length (ipa_parm_adjustment_t, adjustments); if (TREE_CODE (*expr) == BIT_FIELD_REF @@ -3870,7 +3866,7 @@ sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, || TREE_CODE (*expr) == REALPART_EXPR) { expr = &TREE_OPERAND (*expr, 0); - dont_convert = false; + convert = true; } base = get_ref_base_and_extent (*expr, &offset, &size, &max_size); @@ -3919,8 +3915,7 @@ sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, fprintf (dump_file, "\n"); } - if (!dont_convert - && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type)) + if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type)) { tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src); *expr = vce; @@ -3930,24 +3925,28 @@ sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, return true; } -/* Callback for scan_function to process assign statements. Performs - essentially the same function like sra_ipa_modify_expr. */ +/* If the statement pointed to by STMT_PTR contains any expressions that need + to replaced with a different one as noted by ADJUSTMENTS, do so. Handle any + potential type incompatibilities (GSI is used to accommodate conversion + statements and must point to the statement). Return true iff the statement + was modified. */ -static enum scan_assign_result -sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, void *data) +static bool +sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, + ipa_parm_adjustment_vec adjustments) { gimple stmt = *stmt_ptr; tree *lhs_p, *rhs_p; bool any; if (!gimple_assign_single_p (stmt)) - return SRA_SA_NONE; + return false; rhs_p = gimple_assign_rhs1_ptr (stmt); lhs_p = gimple_assign_lhs_ptr (stmt); - any = sra_ipa_modify_expr (rhs_p, gsi, true, data); - any |= sra_ipa_modify_expr (lhs_p, gsi, true, data); + any = sra_ipa_modify_expr (rhs_p, false, adjustments); + any |= sra_ipa_modify_expr (lhs_p, false, adjustments); if (any) { tree new_rhs = NULL_TREE; @@ -3983,10 +3982,94 @@ sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, void *data) gimple_assign_set_rhs_from_tree (gsi, tmp); } - return SRA_SA_PROCESSED; + return true; } - return SRA_SA_NONE; + return false; +} + +/* Traverse the function body and all modifications as described in + ADJUSTMENTS. */ + +static void +ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) +{ + basic_block bb; + + FOR_EACH_BB (bb) + { + gimple_stmt_iterator gsi; + bool bb_changed = false; + + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments); + + gsi = gsi_start_bb (bb); + while (!gsi_end_p (gsi)) + { + gimple stmt = gsi_stmt (gsi); + bool modified = false; + tree *t; + unsigned i; + + switch (gimple_code (stmt)) + { + case GIMPLE_RETURN: + t = gimple_return_retval_ptr (stmt); + if (*t != NULL_TREE) + modified |= sra_ipa_modify_expr (t, true, adjustments); + break; + + case GIMPLE_ASSIGN: + modified |= sra_ipa_modify_assign (&stmt, &gsi, adjustments); + modified |= replace_removed_params_ssa_names (stmt, adjustments); + break; + + case GIMPLE_CALL: + /* Operands must be processed before the lhs. */ + for (i = 0; i < gimple_call_num_args (stmt); i++) + { + t = gimple_call_arg_ptr (stmt, i); + modified |= sra_ipa_modify_expr (t, true, adjustments); + } + + if (gimple_call_lhs (stmt)) + { + t = gimple_call_lhs_ptr (stmt); + modified |= sra_ipa_modify_expr (t, false, adjustments); + modified |= replace_removed_params_ssa_names (stmt, + adjustments); + } + break; + + case GIMPLE_ASM: + for (i = 0; i < gimple_asm_ninputs (stmt); i++) + { + t = &TREE_VALUE (gimple_asm_input_op (stmt, i)); + modified |= sra_ipa_modify_expr (t, true, adjustments); + } + for (i = 0; i < gimple_asm_noutputs (stmt); i++) + { + t = &TREE_VALUE (gimple_asm_output_op (stmt, i)); + modified |= sra_ipa_modify_expr (t, false, adjustments); + } + break; + + default: + break; + } + + if (modified) + { + bb_changed = true; + update_stmt (stmt); + maybe_clean_eh_stmt (stmt); + } + gsi_next (&gsi); + } + if (bb_changed) + gimple_purge_dead_eh_edges (bb); + } } /* Call gimple_debug_bind_reset_value on all debug statements describing @@ -4013,7 +4096,8 @@ sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments) continue; FOR_EACH_IMM_USE_STMT (stmt, ui, name) { - /* All other users must have been removed by scan_function. */ + /* All other users must have been removed by + ipa_sra_modify_function_body. */ gcc_assert (is_gimple_debug (stmt)); gimple_debug_bind_reset_value (stmt); update_stmt (stmt); @@ -4131,8 +4215,7 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments) as following functions will use what it computed. */ create_abstract_origin (current_function_decl); ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA"); - scan_function (sra_ipa_modify_expr, sra_ipa_modify_assign, - replace_removed_params_ssa_names, false, adjustments); + ipa_sra_modify_function_body (adjustments); sra_ipa_reset_debug_stmts (adjustments); convert_callers (node, adjustments); cgraph_make_node_local (node); @@ -4224,8 +4307,7 @@ ipa_early_sra (void) * last_basic_block_for_function (cfun)); final_bbs = BITMAP_ALLOC (NULL); - scan_function (build_access_from_expr, build_accesses_from_assign, - NULL, true, NULL); + scan_function (); if (encountered_apply_args) { if (dump_file) |