Handle double reduction in parloops

2015-07-28  Tom de Vries  <tom@codesourcery.com>

	* tree-parloops.c (reduc_stmt_res): New function.
	(initialize_reductions, add_field_for_reduction)
	(create_phi_for_local_result, create_loads_for_reductions)
	(create_stores_for_reduction, build_new_reduction): Handle case that
	reduc_stmt is a phi.
	(gather_scalar_reductions): Allow double_reduc reductions.

	* gcc.dg/autopar/uns-outer-4.c: Remove xfail on scan for parallelizing
	outer loop.

	* testsuite/libgomp.c/uns-outer-4.c: New test.

From-SVN: r226300
This commit is contained in:
Tom de Vries 2015-07-28 07:54:04 +00:00 committed by Tom de Vries
parent 70b47b6199
commit 12efb1d75f
6 changed files with 120 additions and 13 deletions

View File

@ -1,3 +1,12 @@
2015-07-28 Tom de Vries <tom@codesourcery.com>
* tree-parloops.c (reduc_stmt_res): New function.
(initialize_reductions, add_field_for_reduction)
(create_phi_for_local_result, create_loads_for_reductions)
(create_stores_for_reduction, build_new_reduction): Handle case that
reduc_stmt is a phi.
(gather_scalar_reductions): Allow double_reduc reductions.
2015-07-28 Richard Biener <rguenther@suse.de> 2015-07-28 Richard Biener <rguenther@suse.de>
* fold-const.c (fold_comparison): Remove equality folding * fold-const.c (fold_comparison): Remove equality folding

View File

@ -1,3 +1,8 @@
2015-07-28 Tom de Vries <tom@codesourcery.com>
* gcc.dg/autopar/uns-outer-4.c: Remove xfail on scan for parallelizing
outer loop.
2015-07-28 Luis Felipe Strano Moraes <luis.strano@gmail.com> 2015-07-28 Luis Felipe Strano Moraes <luis.strano@gmail.com>
Manuel López-Ibáñez <manu@gcc.gnu.org> Manuel López-Ibáñez <manu@gcc.gnu.org>

View File

@ -12,9 +12,7 @@ parloop (int N)
int i, j; int i, j;
unsigned int sum; unsigned int sum;
/* Double reduction is currently not supported, outer loop is not /* Double reduction is detected, outer loop is parallelized. */
parallelized. Inner reduction is detected, inner loop is
parallelized. */
sum = 0; sum = 0;
for (i = 0; i < N; i++) for (i = 0; i < N; i++)
for (j = 0; j < N; j++) for (j = 0; j < N; j++)
@ -23,5 +21,5 @@ parloop (int N)
g_sum = sum; g_sum = sum;
} }
/* { dg-final { scan-tree-dump-times "parallelizing outer loop" 1 "parloops" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-times "parallelizing outer loop" 1 "parloops" } } */
/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */ /* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */

View File

@ -549,6 +549,14 @@ take_address_of (tree obj, tree type, edge entry,
return name; return name;
} }
static tree
reduc_stmt_res (gimple stmt)
{
return (gimple_code (stmt) == GIMPLE_PHI
? gimple_phi_result (stmt)
: gimple_assign_lhs (stmt));
}
/* Callback for htab_traverse. Create the initialization statement /* Callback for htab_traverse. Create the initialization statement
for reduction described in SLOT, and place it at the preheader of for reduction described in SLOT, and place it at the preheader of
the loop described in DATA. */ the loop described in DATA. */
@ -575,7 +583,7 @@ initialize_reductions (reduction_info **slot, struct loop *loop)
c = build_omp_clause (gimple_location (reduc->reduc_stmt), c = build_omp_clause (gimple_location (reduc->reduc_stmt),
OMP_CLAUSE_REDUCTION); OMP_CLAUSE_REDUCTION);
OMP_CLAUSE_REDUCTION_CODE (c) = reduc->reduction_code; OMP_CLAUSE_REDUCTION_CODE (c) = reduc->reduction_code;
OMP_CLAUSE_DECL (c) = SSA_NAME_VAR (gimple_assign_lhs (reduc->reduc_stmt)); OMP_CLAUSE_DECL (c) = SSA_NAME_VAR (reduc_stmt_res (reduc->reduc_stmt));
init = omp_reduction_init (c, TREE_TYPE (bvar)); init = omp_reduction_init (c, TREE_TYPE (bvar));
reduc->init = init; reduc->init = init;
@ -982,7 +990,7 @@ add_field_for_reduction (reduction_info **slot, tree type)
{ {
struct reduction_info *const red = *slot; struct reduction_info *const red = *slot;
tree var = gimple_assign_lhs (red->reduc_stmt); tree var = reduc_stmt_res (red->reduc_stmt);
tree field = build_decl (gimple_location (red->reduc_stmt), FIELD_DECL, tree field = build_decl (gimple_location (red->reduc_stmt), FIELD_DECL,
SSA_NAME_IDENTIFIER (var), TREE_TYPE (var)); SSA_NAME_IDENTIFIER (var), TREE_TYPE (var));
@ -1042,12 +1050,12 @@ create_phi_for_local_result (reduction_info **slot, struct loop *loop)
e = EDGE_PRED (store_bb, 1); e = EDGE_PRED (store_bb, 1);
else else
e = EDGE_PRED (store_bb, 0); e = EDGE_PRED (store_bb, 0);
local_res = copy_ssa_name (gimple_assign_lhs (reduc->reduc_stmt)); tree lhs = reduc_stmt_res (reduc->reduc_stmt);
local_res = copy_ssa_name (lhs);
locus = gimple_location (reduc->reduc_stmt); locus = gimple_location (reduc->reduc_stmt);
new_phi = create_phi_node (local_res, store_bb); new_phi = create_phi_node (local_res, store_bb);
add_phi_arg (new_phi, reduc->init, e, locus); add_phi_arg (new_phi, reduc->init, e, locus);
add_phi_arg (new_phi, gimple_assign_lhs (reduc->reduc_stmt), add_phi_arg (new_phi, lhs, FALLTHRU_EDGE (loop->latch), locus);
FALLTHRU_EDGE (loop->latch), locus);
reduc->new_phi = new_phi; reduc->new_phi = new_phi;
return 1; return 1;
@ -1140,7 +1148,7 @@ create_loads_for_reductions (reduction_info **slot, struct clsn_data *clsn_data)
struct reduction_info *const red = *slot; struct reduction_info *const red = *slot;
gimple stmt; gimple stmt;
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
tree type = TREE_TYPE (gimple_assign_lhs (red->reduc_stmt)); tree type = TREE_TYPE (reduc_stmt_res (red->reduc_stmt));
tree load_struct; tree load_struct;
tree name; tree name;
tree x; tree x;
@ -1205,7 +1213,7 @@ create_stores_for_reduction (reduction_info **slot, struct clsn_data *clsn_data)
tree t; tree t;
gimple stmt; gimple stmt;
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
tree type = TREE_TYPE (gimple_assign_lhs (red->reduc_stmt)); tree type = TREE_TYPE (reduc_stmt_res (red->reduc_stmt));
gsi = gsi_last_bb (clsn_data->store_bb); gsi = gsi_last_bb (clsn_data->store_bb);
t = build3 (COMPONENT_REF, type, clsn_data->store, red->field, NULL_TREE); t = build3 (COMPONENT_REF, type, clsn_data->store, red->field, NULL_TREE);
@ -2330,6 +2338,7 @@ build_new_reduction (reduction_info_table_type *reduction_list,
{ {
reduction_info **slot; reduction_info **slot;
struct reduction_info *new_reduction; struct reduction_info *new_reduction;
enum tree_code reduction_code;
gcc_assert (reduc_stmt); gcc_assert (reduc_stmt);
@ -2341,12 +2350,22 @@ build_new_reduction (reduction_info_table_type *reduction_list,
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
if (gimple_code (reduc_stmt) == GIMPLE_PHI)
{
tree op1 = PHI_ARG_DEF (reduc_stmt, 0);
gimple def1 = SSA_NAME_DEF_STMT (op1);
reduction_code = gimple_assign_rhs_code (def1);
}
else
reduction_code = gimple_assign_rhs_code (reduc_stmt);
new_reduction = XCNEW (struct reduction_info); new_reduction = XCNEW (struct reduction_info);
new_reduction->reduc_stmt = reduc_stmt; new_reduction->reduc_stmt = reduc_stmt;
new_reduction->reduc_phi = phi; new_reduction->reduc_phi = phi;
new_reduction->reduc_version = SSA_NAME_VERSION (gimple_phi_result (phi)); new_reduction->reduc_version = SSA_NAME_VERSION (gimple_phi_result (phi));
new_reduction->reduction_code = gimple_assign_rhs_code (reduc_stmt); new_reduction->reduction_code = reduction_code;
slot = reduction_list->find_slot (new_reduction, INSERT); slot = reduction_list->find_slot (new_reduction, INSERT);
*slot = new_reduction; *slot = new_reduction;
} }
@ -2368,6 +2387,8 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list
{ {
gphi_iterator gsi; gphi_iterator gsi;
loop_vec_info simple_loop_info; loop_vec_info simple_loop_info;
loop_vec_info simple_inner_loop_info = NULL;
bool allow_double_reduc = true;
simple_loop_info = vect_analyze_loop_form (loop); simple_loop_info = vect_analyze_loop_form (loop);
if (simple_loop_info == NULL) if (simple_loop_info == NULL)
@ -2389,12 +2410,46 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list
gimple reduc_stmt gimple reduc_stmt
= vect_force_simple_reduction (simple_loop_info, phi, true, = vect_force_simple_reduction (simple_loop_info, phi, true,
&double_reduc, true); &double_reduc, true);
if (!reduc_stmt || double_reduc) if (!reduc_stmt)
continue; continue;
if (double_reduc)
{
if (!allow_double_reduc
|| loop->inner->inner != NULL)
continue;
if (!simple_inner_loop_info)
{
simple_inner_loop_info = vect_analyze_loop_form (loop->inner);
if (!simple_inner_loop_info)
{
allow_double_reduc = false;
continue;
}
}
use_operand_p use_p;
gimple inner_stmt;
bool single_use_p = single_imm_use (res, &use_p, &inner_stmt);
gcc_assert (single_use_p);
gphi *inner_phi = as_a <gphi *> (inner_stmt);
if (simple_iv (loop->inner, loop->inner, PHI_RESULT (inner_phi),
&iv, true))
continue;
gimple inner_reduc_stmt
= vect_force_simple_reduction (simple_inner_loop_info, inner_phi,
true, &double_reduc, true);
gcc_assert (!double_reduc);
if (inner_reduc_stmt == NULL)
continue;
}
build_new_reduction (reduction_list, reduc_stmt, phi); build_new_reduction (reduction_list, reduc_stmt, phi);
} }
destroy_loop_vec_info (simple_loop_info, true); destroy_loop_vec_info (simple_loop_info, true);
destroy_loop_vec_info (simple_inner_loop_info, true);
/* As gimple_uid is used by the vectorizer in between vect_analyze_loop_form /* As gimple_uid is used by the vectorizer in between vect_analyze_loop_form
and destroy_loop_vec_info, we can set gimple_uid of reduc_phi stmts and destroy_loop_vec_info, we can set gimple_uid of reduc_phi stmts

View File

@ -1,3 +1,7 @@
2015-07-28 Tom de Vries <tom@codesourcery.com>
* testsuite/libgomp.c/uns-outer-4.c: New test.
2015-07-24 Cesar Philippidis <cesar@codesourcery.com> 2015-07-24 Cesar Philippidis <cesar@codesourcery.com>
* testsuite/libgomp.c/pr66714.c: New test. * testsuite/libgomp.c/pr66714.c: New test.

View File

@ -0,0 +1,36 @@
/* { dg-do run } */
/* { dg-additional-options "-ftree-parallelize-loops=2" } */
void abort (void);
unsigned int g_sum = 1;
unsigned int x[500][500];
void __attribute__((noinline,noclone))
parloop (int N)
{
int i, j;
unsigned int sum;
/* Double reduction is detected, outer loop is parallelized. */
sum = 0;
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
sum += x[i][j];
g_sum = sum;
}
int
main (void)
{
x[234][432] = 2;
parloop (500);
if (g_sum != 2)
abort ();
return 0;
}