aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-loop-distribution.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2013-01-28 14:45:46 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2013-01-28 14:45:46 +0000
commitb9fc04974250dfa6e2155fc38dcbca39e162b5c7 (patch)
treec734aa313961c4f7ad6438ad86a0d1f80b7c005d /gcc/tree-loop-distribution.c
parent0bfbca5868fae1912db33ae4ab341d6e08bd68b4 (diff)
downloadgcc-b9fc04974250dfa6e2155fc38dcbca39e162b5c7.zip
gcc-b9fc04974250dfa6e2155fc38dcbca39e162b5c7.tar.gz
gcc-b9fc04974250dfa6e2155fc38dcbca39e162b5c7.tar.bz2
re PR tree-optimization/56034 (ICE: verify_gimple failed (invalid PHI argument) with -ftree-loop-distribution)
2013-01-28 Richard Biener <rguenther@suse.de> PR tree-optimization/56034 * tree-loop-distribution.c (enum partition_kind): Add PKIND_REDUCTION. (partition_builtin_p): Adjust. (generate_code_for_partition): Handle PKIND_REDUCTION. Assert it is the last partition. (rdg_flag_uses): Check SSA_NAME_IS_DEFAULT_DEF before looking up the vertex for the definition. (classify_partition): Classify whether a partition is a PKIND_REDUCTION, thus has uses outside of the loop. (ldist_gen): Inherit PKIND_REDUCTION when merging partitions. Merge all PKIND_REDUCTION partitions into the last partition. (tree_loop_distribution): Seed partitions from reductions as well. * gcc.dg/torture/pr56034.c: New testcase. From-SVN: r195508
Diffstat (limited to 'gcc/tree-loop-distribution.c')
-rw-r--r--gcc/tree-loop-distribution.c72
1 files changed, 55 insertions, 17 deletions
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 747b6ac..12fd4c5 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -51,7 +51,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "tree-pass.h"
-enum partition_kind { PKIND_NORMAL, PKIND_MEMSET, PKIND_MEMCPY };
+enum partition_kind {
+ PKIND_NORMAL, PKIND_REDUCTION, PKIND_MEMSET, PKIND_MEMCPY
+};
typedef struct partition_s
{
@@ -90,7 +92,7 @@ partition_free (partition_t partition)
static bool
partition_builtin_p (partition_t partition)
{
- return partition->kind != PKIND_NORMAL;
+ return partition->kind > PKIND_REDUCTION;
}
/* Returns true if the partition has an writes. */
@@ -481,6 +483,9 @@ generate_code_for_partition (struct loop *loop,
destroy_loop (loop);
break;
+ case PKIND_REDUCTION:
+ /* Reductions all have to be in the last partition. */
+ gcc_assert (!copy_p);
case PKIND_NORMAL:
generate_loops_for_partition (loop, partition, copy_p);
break;
@@ -628,7 +633,8 @@ rdg_flag_uses (struct graph *rdg, int u, partition_t partition, bitmap loops,
{
tree use = USE_FROM_PTR (use_p);
- if (TREE_CODE (use) == SSA_NAME)
+ if (TREE_CODE (use) == SSA_NAME
+ && !SSA_NAME_IS_DEFAULT_DEF (use))
{
gimple def_stmt = SSA_NAME_DEF_STMT (use);
int v = rdg_vertex_for_stmt (rdg, def_stmt);
@@ -858,25 +864,18 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
unsigned i;
tree nb_iter;
data_reference_p single_load, single_store;
+ bool volatiles_p = false;
partition->kind = PKIND_NORMAL;
partition->main_dr = NULL;
partition->secondary_dr = NULL;
- if (!flag_tree_loop_distribute_patterns)
- return;
-
- /* Perform general partition disqualification for builtins. */
- nb_iter = number_of_exit_cond_executions (loop);
- if (!nb_iter || nb_iter == chrec_dont_know)
- return;
-
EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
{
gimple stmt = RDG_STMT (rdg, i);
if (gimple_has_volatile_ops (stmt))
- return;
+ volatiles_p = true;
/* If the stmt has uses outside of the loop fail.
??? If the stmt is generated in another partition that
@@ -886,10 +885,20 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "not generating builtin, partition has "
"scalar uses outside of the loop\n");
+ partition->kind = PKIND_REDUCTION;
return;
}
}
+ /* Perform general partition disqualification for builtins. */
+ if (volatiles_p
+ || !flag_tree_loop_distribute_patterns)
+ return;
+
+ nb_iter = number_of_exit_cond_executions (loop);
+ if (!nb_iter || nb_iter == chrec_dont_know)
+ return;
+
/* Detect memset and memcpy. */
single_load = NULL;
single_store = NULL;
@@ -1294,6 +1303,8 @@ ldist_gen (struct loop *loop, struct graph *rdg,
if (!partition_builtin_p (partition))
{
bitmap_ior_into (into->stmts, partition->stmts);
+ if (partition->kind == PKIND_REDUCTION)
+ into->kind = PKIND_REDUCTION;
partitions.ordered_remove (i);
i--;
}
@@ -1328,6 +1339,8 @@ ldist_gen (struct loop *loop, struct graph *rdg,
"memory accesses\n");
}
bitmap_ior_into (into->stmts, partition->stmts);
+ if (partition->kind == PKIND_REDUCTION)
+ into->kind = PKIND_REDUCTION;
partitions.ordered_remove (j);
j--;
}
@@ -1335,6 +1348,29 @@ ldist_gen (struct loop *loop, struct graph *rdg,
}
}
+ /* Fuse all reduction partitions into the last. */
+ if (partitions.length () > 1)
+ {
+ partition_t into = partitions.last ();
+ for (i = partitions.length () - 2; i >= 0; --i)
+ {
+ partition_t what = partitions[i];
+ if (what->kind == PKIND_REDUCTION)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "fusing partitions\n");
+ dump_bitmap (dump_file, into->stmts);
+ dump_bitmap (dump_file, what->stmts);
+ fprintf (dump_file, "because the latter has reductions\n");
+ }
+ bitmap_ior_into (into->stmts, what->stmts);
+ into->kind = PKIND_REDUCTION;
+ partitions.ordered_remove (i);
+ }
+ }
+ }
+
nbp = partitions.length ();
if (nbp == 0
|| (nbp == 1 && !partition_builtin_p (partitions[0]))
@@ -1478,11 +1514,13 @@ tree_loop_distribution (void)
for (gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
- /* Only distribute stores for now.
- ??? We should also try to distribute scalar reductions,
- thus SSA defs that have scalar uses outside of the loop. */
- if (!gimple_assign_single_p (stmt)
- || is_gimple_reg (gimple_assign_lhs (stmt)))
+ /* Distribute stmts which have defs that are used outside of
+ the loop. */
+ if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
+ ;
+ /* Otherwise only distribute stores for now. */
+ else if (!gimple_assign_single_p (stmt)
+ || is_gimple_reg (gimple_assign_lhs (stmt)))
continue;
work_list.safe_push (stmt);