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
This commit is contained in:
Martin Jambor 2014-04-17 15:53:59 +02:00 committed by Martin Jambor
parent b94970bc41
commit 104cb50bd1
7 changed files with 126 additions and 12 deletions

View File

@ -1,3 +1,17 @@
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.
2014-04-17 Richard Biener <rguenther@suse.de>
PR middle-end/60849

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,8 @@
2014-04-17 Martin Jambor <mjambor@suse.cz>
* gnat.dg/opt34.adb: New.
* gnat.dg/opt34_pkg.ads: Likewise.
2014-04-17 Trevor Saunders <tsaunders@mozilla.com>
* g++.dg/plugin/dumb_plugin.c, g++.dg/plugin/selfasign.c,

View File

@ -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" } }

View File

@ -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;

View File

@ -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;
}