From 104cb50bd13ccb8ed1934ef3a8f90ec9e4e1c1de Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Thu, 17 Apr 2014 15:53:59 +0200 Subject: [PATCH] gimple-iterator.c (gsi_start_edge): New function. 2014-04-17 Martin Jambor * 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 --- gcc/ChangeLog | 14 ++++++++ gcc/gimple-iterator.c | 9 +++++ gcc/gimple-iterator.h | 2 ++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gnat.dg/opt34.adb | 29 +++++++++++++++++ gcc/testsuite/gnat.dg/opt34_pkg.ads | 14 ++++++++ gcc/tree-sra.c | 65 ++++++++++++++++++++++++++++++------- 7 files changed, 126 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/opt34.adb create mode 100644 gcc/testsuite/gnat.dg/opt34_pkg.ads diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1f463e3..a8a95e9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2014-04-17 Martin Jambor + + * 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. + 2014-04-17 Richard Biener PR middle-end/60849 diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c index 1cfeb73..8a1ec53 100644 --- a/gcc/gimple-iterator.c +++ b/gcc/gimple-iterator.c @@ -689,6 +689,15 @@ gsi_insert_seq_on_edge (edge e, gimple_seq seq) gimple_seq_add_seq (&PENDING_STMT (e), seq); } +/* Return a new iterator pointing to the first statement in sequence of + statements on edge E. Such statements need to be subsequently moved into a + basic block by calling gsi_commit_edge_inserts. */ + +gimple_stmt_iterator +gsi_start_edge (edge e) +{ + return gsi_start (PENDING_STMT (e)); +} /* Insert the statement pointed-to by GSI into edge E. Every attempt is made to place the statement in an existing basic block, but diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h index c35dc81..909d58b 100644 --- a/gcc/gimple-iterator.h +++ b/gcc/gimple-iterator.h @@ -123,6 +123,8 @@ gsi_start_bb (basic_block bb) return i; } +gimple_stmt_iterator gsi_start_edge (edge e); + /* Return a new iterator initially pointing to GIMPLE_SEQ's last statement. */ static inline gimple_stmt_iterator diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a3cbef3..eb1ac11 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-04-17 Martin Jambor + + * gnat.dg/opt34.adb: New. + * gnat.dg/opt34_pkg.ads: Likewise. + 2014-04-17 Trevor Saunders * g++.dg/plugin/dumb_plugin.c, g++.dg/plugin/selfasign.c, diff --git a/gcc/testsuite/gnat.dg/opt34.adb b/gcc/testsuite/gnat.dg/opt34.adb new file mode 100644 index 0000000..a5d0ab6 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt34.adb @@ -0,0 +1,29 @@ +-- { dg-do compile } +-- { dg-options "-O -fdump-tree-esra" } + +with Opt34_Pkg; use Opt34_Pkg; + +procedure Opt34 is + + function Local_Fun (Arg : T_Private) return T_Private is + Result : T_Private; + begin + + case Get_Integer (Arg) is + when 1 => + Result := Get_Private (100); + when 2 => + Result := T_Private_Zero; + when others => + null; + end case; + + return Result; + end Local_Fun; + +begin + Assert (Get_Integer (Local_Fun (Get_Private (1))) = 100); +end; + +-- { dg-final { scan-tree-dump "Created a replacement for result" "esra" } } +-- { dg-final { cleanup-tree-dump "esra" } } diff --git a/gcc/testsuite/gnat.dg/opt34_pkg.ads b/gcc/testsuite/gnat.dg/opt34_pkg.ads new file mode 100644 index 0000000..83ecb49 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt34_pkg.ads @@ -0,0 +1,14 @@ +package Opt34_Pkg is + + type T_Private is record + I : Integer := 0; + end record; + + T_Private_Zero : constant T_Private := (I => 0); + + function Get_Private (I : Integer) return T_Private; + function Get_Integer (X : T_Private) return Integer; + + procedure Assert (Cond : Boolean); + +end Opt34_Pkg; 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; } -- 2.7.4