diff options
author | Martin Jambor <mjambor@suse.cz> | 2014-04-17 15:53:59 +0200 |
---|---|---|
committer | Martin Jambor <jamborm@gcc.gnu.org> | 2014-04-17 15:53:59 +0200 |
commit | 104cb50bd13ccb8ed1934ef3a8f90ec9e4e1c1de (patch) | |
tree | b255138251190ed1adfba46943629741890a091d /gcc/tree-sra.c | |
parent | b94970bc41f7b2c6ab28d52493f95efcf2fa97de (diff) | |
download | gcc-104cb50bd13ccb8ed1934ef3a8f90ec9e4e1c1de.zip gcc-104cb50bd13ccb8ed1934ef3a8f90ec9e4e1c1de.tar.gz gcc-104cb50bd13ccb8ed1934ef3a8f90ec9e4e1c1de.tar.bz2 |
gimple-iterator.c (gsi_start_edge): New function.
2014-04-17 Martin Jambor <mjambor@suse.cz>
* gimple-iterator.c (gsi_start_edge): New function.
* gimple-iterator.h (gsi_start_edge): Declare.
* tree-sra.c (single_non_eh_succ): New function.
(disqualify_ops_if_throwing_stmt): Renamed to
disqualify_if_bad_bb_terminating_stmt. Allow throwing statements
having one non-EH successor BB.
(sra_modify_expr): If stmt ends bb, use single non-EH successor to
generate loads into replacements.
(sra_modify_assign): Likewise and and also use the simple path for
such statements.
(sra_modify_function_body): Commit statements on edges.
testsuite/
* gnat.dg/opt34.adb: New.
* gnat.dg/opt34_pkg.ads: Likewise.
From-SVN: r209487
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r-- | gcc/tree-sra.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 890234f..49bbee3 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -1142,17 +1142,41 @@ build_access_from_expr (tree expr, gimple stmt, bool write) return false; } -/* Disqualify LHS and RHS for scalarization if STMT must end its basic block in - modes in which it matters, return true iff they have been disqualified. RHS - may be NULL, in that case ignore it. If we scalarize an aggregate in - intra-SRA we may need to add statements after each statement. This is not - possible if a statement unconditionally has to end the basic block. */ +/* Return the single non-EH successor edge of BB or NULL if there is none or + more than one. */ + +static edge +single_non_eh_succ (basic_block bb) +{ + edge e, res = NULL; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bb->succs) + if (!(e->flags & EDGE_EH)) + { + if (res) + return NULL; + res = e; + } + + return res; +} + +/* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and + there is no alternative spot where to put statements SRA might need to + generate after it. The spot we are looking for is an edge leading to a + single non-EH successor, if it exists and is indeed single. RHS may be + NULL, in that case ignore it. */ + static bool -disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs) +disqualify_if_bad_bb_terminating_stmt (gimple stmt, tree lhs, tree rhs) { if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA) - && (stmt_can_throw_internal (stmt) || stmt_ends_bb_p (stmt))) + && stmt_ends_bb_p (stmt)) { + if (single_non_eh_succ (gimple_bb (stmt))) + return false; + disqualify_base_of_expr (lhs, "LHS of a throwing stmt."); if (rhs) disqualify_base_of_expr (rhs, "RHS of a throwing stmt."); @@ -1180,7 +1204,7 @@ build_accesses_from_assign (gimple stmt) lhs = gimple_assign_lhs (stmt); rhs = gimple_assign_rhs1 (stmt); - if (disqualify_ops_if_throwing_stmt (stmt, lhs, rhs)) + if (disqualify_if_bad_bb_terminating_stmt (stmt, lhs, rhs)) return false; racc = build_access_from_expr_1 (rhs, stmt, false); @@ -1319,7 +1343,7 @@ scan_function (void) } t = gimple_call_lhs (stmt); - if (t && !disqualify_ops_if_throwing_stmt (stmt, t, NULL)) + if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL)) ret |= build_access_from_expr (t, stmt, true); break; @@ -2763,6 +2787,13 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) type = TREE_TYPE (*expr); loc = gimple_location (gsi_stmt (*gsi)); + gimple_stmt_iterator alt_gsi = gsi_none (); + if (write && stmt_ends_bb_p (gsi_stmt (*gsi))) + { + alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi))); + gsi = &alt_gsi; + } + if (access->grp_to_be_replaced) { tree repl = get_access_replacement (access); @@ -3226,14 +3257,23 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) if (modify_this_stmt || gimple_has_volatile_ops (*stmt) || contains_vce_or_bfcref_p (rhs) - || contains_vce_or_bfcref_p (lhs)) + || contains_vce_or_bfcref_p (lhs) + || stmt_ends_bb_p (*stmt)) { if (access_has_children_p (racc)) generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0, gsi, false, false, loc); if (access_has_children_p (lacc)) - generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0, - gsi, true, true, loc); + { + gimple_stmt_iterator alt_gsi = gsi_none (); + if (stmt_ends_bb_p (*stmt)) + { + alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi))); + gsi = &alt_gsi; + } + generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0, + gsi, true, true, loc); + } sra_stats.separate_lhs_rhs_handling++; /* This gimplification must be done after generate_subtree_copies, @@ -3397,6 +3437,7 @@ sra_modify_function_body (void) } } + gsi_commit_edge_inserts (); return cfg_changed; } |