Commit 826a536d by Richard Biener Committed by Richard Biener

tree-loop-distribution.c: Include tree-vectorizer.h for find_loop_location.

2013-10-02  Richard Biener  <rguenther@suse.de>

	* tree-loop-distribution.c: Include tree-vectorizer.h for
	find_loop_location.
	(enum partition_kind): Remove PKIND_REDUCTION.
	(struct partition_s): Remove has_writes member, add reduction_p
	member.
	(partition_alloc): Adjust.
	(partition_builtin_p): Likewise.
	(partition_has_writes): Remove.
	(partition_reduction_p): New function.
	(partition_merge_into): Likewise.
	(generate_code_for_partition): Commonize builtin partition
	handling tail.
	(rdg_cannot_recompute_vertex_p): Remove.
	(already_processed_vertex_p): Likewise.
	(rdg_flag_vertex): Do not set has_writes.
	(classify_partition): Adjust.
	(rdg_build_partitions): Do not set has_writes, treat all
	partitions as useful.
	(distribute_loop): Record number of library calls generated.
	Adjust.
	(tree_loop_distribution): Report number of loops and library
	calls generated as opt-info.

	* gcc.dg/tree-ssa/ldist-11.c: Adjust.
	* gcc.dg/tree-ssa/ldist-17.c: Likewise.
	* gcc.dg/tree-ssa/ldist-23.c: Likewise.
	* gcc.dg/tree-ssa/ldist-pr45948.c: Likewise.
	* gfortran.dg/ldist-pr45199.f: Likewise.

From-SVN: r203115
parent 4b403ece
2013-10-02 Richard Biener <rguenther@suse.de>
* tree-loop-distribution.c: Include tree-vectorizer.h for
find_loop_location.
(enum partition_kind): Remove PKIND_REDUCTION.
(struct partition_s): Remove has_writes member, add reduction_p
member.
(partition_alloc): Adjust.
(partition_builtin_p): Likewise.
(partition_has_writes): Remove.
(partition_reduction_p): New function.
(partition_merge_into): Likewise.
(generate_code_for_partition): Commonize builtin partition
handling tail.
(rdg_cannot_recompute_vertex_p): Remove.
(already_processed_vertex_p): Likewise.
(rdg_flag_vertex): Do not set has_writes.
(classify_partition): Adjust.
(rdg_build_partitions): Do not set has_writes, treat all
partitions as useful.
(distribute_loop): Record number of library calls generated.
Adjust.
(tree_loop_distribution): Report number of loops and library
calls generated as opt-info.
2013-10-02 Andrew MacLeod <amacleod@redhat.com> 2013-10-02 Andrew MacLeod <amacleod@redhat.com>
* tree-flow.h: Include new .h files. Move prototypes. * tree-flow.h: Include new .h files. Move prototypes.
......
2013-10-02 Richard Biener <rguenther@suse.de>
* gcc.dg/tree-ssa/ldist-11.c: Adjust.
* gcc.dg/tree-ssa/ldist-17.c: Likewise.
* gcc.dg/tree-ssa/ldist-23.c: Likewise.
* gcc.dg/tree-ssa/ldist-pr45948.c: Likewise.
* gfortran.dg/ldist-pr45199.f: Likewise.
2013-10-02 Paolo Carlini <paolo.carlini@oracle.com> 2013-10-02 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/58565 PR c++/58565
......
...@@ -28,6 +28,6 @@ void foo (int * __restrict__ ia, ...@@ -28,6 +28,6 @@ void foo (int * __restrict__ ia,
*/ */
} }
/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 1 "ldist" } } */ /* { dg-final { scan-tree-dump-times "distributed: split to 1 loops and 1 library calls" 1 "ldist" } } */
/* { dg-final { scan-tree-dump-times "generated memset zero" 1 "ldist" } } */ /* { dg-final { scan-tree-dump-times "generated memset zero" 1 "ldist" } } */
/* { dg-final { cleanup-tree-dump "ldist" } } */ /* { dg-final { cleanup-tree-dump "ldist" } } */
...@@ -45,6 +45,6 @@ mad_synth_mute (struct mad_synth *synth) ...@@ -45,6 +45,6 @@ mad_synth_mute (struct mad_synth *synth)
return; return;
} }
/* { dg-final { scan-tree-dump "distributed: split to 4" "ldist" } } */ /* { dg-final { scan-tree-dump "distributed: split to 0 loops and 4 library calls" "ldist" } } */
/* { dg-final { scan-tree-dump-times "generated memset zero" 4 "ldist" } } */ /* { dg-final { scan-tree-dump-times "generated memset zero" 4 "ldist" } } */
/* { dg-final { cleanup-tree-dump "ldist" } } */ /* { dg-final { cleanup-tree-dump "ldist" } } */
...@@ -29,6 +29,6 @@ int main() ...@@ -29,6 +29,6 @@ int main()
return 0; return 0;
} }
/* { dg-final { scan-tree-dump "split to 2 loops" "ldist" } } */ /* { dg-final { scan-tree-dump "split to 1 loops and 1 library call" "ldist" } } */
/* { dg-final { scan-tree-dump "generated memcpy" "ldist" } } */ /* { dg-final { scan-tree-dump "generated memcpy" "ldist" } } */
/* { dg-final { cleanup-tree-dump "ldist" } } */ /* { dg-final { cleanup-tree-dump "ldist" } } */
...@@ -18,6 +18,6 @@ foo (int i, int n) ...@@ -18,6 +18,6 @@ foo (int i, int n)
/* We should apply loop distribution and generate 2 memset (0). */ /* We should apply loop distribution and generate 2 memset (0). */
/* { dg-final { scan-tree-dump "distributed: split to 2" "ldist" } } */ /* { dg-final { scan-tree-dump "distributed: split to 0 loops and 2 library calls" "ldist" } } */
/* { dg-final { scan-tree-dump-times "generated memset zero" 2 "ldist" } } */ /* { dg-final { scan-tree-dump-times "generated memset zero" 2 "ldist" } } */
/* { dg-final { cleanup-tree-dump "ldist" } } */ /* { dg-final { cleanup-tree-dump "ldist" } } */
...@@ -22,6 +22,6 @@ ...@@ -22,6 +22,6 @@
! GCC should apply memset zero loop distribution and it should not ICE. ! GCC should apply memset zero loop distribution and it should not ICE.
! { dg-final { scan-tree-dump "distributed: split to 9 loops" "ldist" } } ! { dg-final { scan-tree-dump "distributed: split to 0 loops and 9 library calls" "ldist" } }
! { dg-final { scan-tree-dump-times "generated memset zero" 9 "ldist" } } ! { dg-final { scan-tree-dump-times "generated memset zero" 9 "ldist" } }
! { dg-final { cleanup-tree-dump "ldist" } } ! { dg-final { cleanup-tree-dump "ldist" } }
...@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h" #include "tree-scalar-evolution.h"
#include "tree-pass.h" #include "tree-pass.h"
#include "gimple-pretty-print.h" #include "gimple-pretty-print.h"
#include "tree-vectorizer.h"
/* A Reduced Dependence Graph (RDG) vertex representing a statement. */ /* A Reduced Dependence Graph (RDG) vertex representing a statement. */
...@@ -557,14 +558,14 @@ build_rdg (vec<loop_p> loop_nest, control_dependences *cd) ...@@ -557,14 +558,14 @@ build_rdg (vec<loop_p> loop_nest, control_dependences *cd)
enum partition_kind { enum partition_kind {
PKIND_NORMAL, PKIND_REDUCTION, PKIND_MEMSET, PKIND_MEMCPY PKIND_NORMAL, PKIND_MEMSET, PKIND_MEMCPY
}; };
typedef struct partition_s typedef struct partition_s
{ {
bitmap stmts; bitmap stmts;
bitmap loops; bitmap loops;
bool has_writes; bool reduction_p;
enum partition_kind kind; enum partition_kind kind;
/* data-references a kind != PKIND_NORMAL partition is about. */ /* data-references a kind != PKIND_NORMAL partition is about. */
data_reference_p main_dr; data_reference_p main_dr;
...@@ -581,7 +582,7 @@ partition_alloc (bitmap stmts, bitmap loops) ...@@ -581,7 +582,7 @@ partition_alloc (bitmap stmts, bitmap loops)
partition_t partition = XCNEW (struct partition_s); partition_t partition = XCNEW (struct partition_s);
partition->stmts = stmts ? stmts : BITMAP_ALLOC (NULL); partition->stmts = stmts ? stmts : BITMAP_ALLOC (NULL);
partition->loops = loops ? loops : BITMAP_ALLOC (NULL); partition->loops = loops ? loops : BITMAP_ALLOC (NULL);
partition->has_writes = false; partition->reduction_p = false;
partition->kind = PKIND_NORMAL; partition->kind = PKIND_NORMAL;
return partition; return partition;
} }
...@@ -601,17 +602,29 @@ partition_free (partition_t partition) ...@@ -601,17 +602,29 @@ partition_free (partition_t partition)
static bool static bool
partition_builtin_p (partition_t partition) partition_builtin_p (partition_t partition)
{ {
return partition->kind > PKIND_REDUCTION; return partition->kind != PKIND_NORMAL;
} }
/* Returns true if the partition has an writes. */ /* Returns true if the partition contains a reduction. */
static bool static bool
partition_has_writes (partition_t partition) partition_reduction_p (partition_t partition)
{ {
return partition->has_writes; return partition->reduction_p;
} }
/* Merge PARTITION into the partition DEST. */
static void
partition_merge_into (partition_t dest, partition_t partition)
{
dest->kind = PKIND_NORMAL;
bitmap_ior_into (dest->stmts, partition->stmts);
if (partition_reduction_p (partition))
dest->reduction_p = true;
}
/* Returns true when DEF is an SSA_NAME defined in LOOP and used after /* Returns true when DEF is an SSA_NAME defined in LOOP and used after
the LOOP. */ the LOOP. */
...@@ -998,58 +1011,31 @@ generate_code_for_partition (struct loop *loop, ...@@ -998,58 +1011,31 @@ generate_code_for_partition (struct loop *loop,
{ {
switch (partition->kind) switch (partition->kind)
{ {
case PKIND_NORMAL:
/* Reductions all have to be in the last partition. */
gcc_assert (!partition_reduction_p (partition)
|| !copy_p);
generate_loops_for_partition (loop, partition, copy_p);
return;
case PKIND_MEMSET: case PKIND_MEMSET:
generate_memset_builtin (loop, partition); generate_memset_builtin (loop, partition);
/* If this is the last partition for which we generate code, we have
to destroy the loop. */
if (!copy_p)
destroy_loop (loop);
break; break;
case PKIND_MEMCPY: case PKIND_MEMCPY:
generate_memcpy_builtin (loop, partition); generate_memcpy_builtin (loop, partition);
/* If this is the last partition for which we generate code, we have
to destroy the loop. */
if (!copy_p)
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; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
}
/* Returns true if the node V of RDG cannot be recomputed. */
static bool
rdg_cannot_recompute_vertex_p (struct graph *rdg, int v)
{
if (RDG_MEM_WRITE_STMT (rdg, v))
return true;
return false; /* Common tail for partitions we turn into a call. If this was the last
} partition for which we generate code, we have to destroy the loop. */
if (!copy_p)
/* Returns true when the vertex V has already been generated in the destroy_loop (loop);
current partition (V is in PROCESSED), or when V belongs to another
partition and cannot be recomputed (V is not in REMAINING_STMTS). */
static inline bool
already_processed_vertex_p (bitmap processed, int v)
{
return bitmap_bit_p (processed, v);
} }
static void rdg_flag_vertex_and_dependent (struct graph *, int, partition_t,
bitmap);
/* Flag V from RDG as part of PARTITION, and also flag its loop number /* Flag V from RDG as part of PARTITION, and also flag its loop number
in LOOPS. */ in LOOPS. */
...@@ -1064,9 +1050,6 @@ rdg_flag_vertex (struct graph *rdg, int v, partition_t partition) ...@@ -1064,9 +1050,6 @@ rdg_flag_vertex (struct graph *rdg, int v, partition_t partition)
loop = loop_containing_stmt (RDG_STMT (rdg, v)); loop = loop_containing_stmt (RDG_STMT (rdg, v));
bitmap_set_bit (partition->loops, loop->num); bitmap_set_bit (partition->loops, loop->num);
if (rdg_cannot_recompute_vertex_p (rdg, v))
partition->has_writes = true;
} }
/* Flag in the bitmap PARTITION the vertex V and all its predecessors. /* Flag in the bitmap PARTITION the vertex V and all its predecessors.
...@@ -1127,15 +1110,10 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition) ...@@ -1127,15 +1110,10 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
if (gimple_has_volatile_ops (stmt)) if (gimple_has_volatile_ops (stmt))
volatiles_p = true; volatiles_p = true;
/* If the stmt has uses outside of the loop fail. /* If the stmt has uses outside of the loop mark it as reduction. */
??? If the stmt is generated in another partition that
is not created as builtin we can ignore this. */
if (stmt_has_scalar_dependences_outside_loop (loop, stmt)) if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) partition->reduction_p = true;
fprintf (dump_file, "not generating builtin, partition has "
"scalar uses outside of the loop\n");
partition->kind = PKIND_REDUCTION;
return; return;
} }
} }
...@@ -1356,21 +1334,17 @@ rdg_build_partitions (struct graph *rdg, ...@@ -1356,21 +1334,17 @@ rdg_build_partitions (struct graph *rdg,
np = build_rdg_partition_for_vertex (rdg, v); np = build_rdg_partition_for_vertex (rdg, v);
bitmap_ior_into (partition->stmts, np->stmts); bitmap_ior_into (partition->stmts, np->stmts);
partition->has_writes = partition_has_writes (np);
bitmap_ior_into (processed, np->stmts); bitmap_ior_into (processed, np->stmts);
partition_free (np); partition_free (np);
if (partition_has_writes (partition)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "ldist useful partition:\n");
{ dump_bitmap (dump_file, partition->stmts);
fprintf (dump_file, "ldist useful partition:\n");
dump_bitmap (dump_file, partition->stmts);
}
partitions->safe_push (partition);
partition = partition_alloc (NULL, NULL);
} }
partitions->safe_push (partition);
partition = partition_alloc (NULL, NULL);
} }
/* All vertices should have been assigned to at least one partition now, /* All vertices should have been assigned to at least one partition now,
...@@ -1480,7 +1454,7 @@ partition_contains_all_rw (struct graph *rdg, ...@@ -1480,7 +1454,7 @@ partition_contains_all_rw (struct graph *rdg,
static int static int
distribute_loop (struct loop *loop, vec<gimple> stmts, distribute_loop (struct loop *loop, vec<gimple> stmts,
control_dependences *cd) control_dependences *cd, int *nb_calls)
{ {
struct graph *rdg; struct graph *rdg;
vec<loop_p> loop_nest; vec<loop_p> loop_nest;
...@@ -1489,6 +1463,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, ...@@ -1489,6 +1463,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
bool any_builtin; bool any_builtin;
int i, nbp; int i, nbp;
*nb_calls = 0;
loop_nest.create (3); loop_nest.create (3);
if (!find_loop_nest (loop, &loop_nest)) if (!find_loop_nest (loop, &loop_nest))
{ {
...@@ -1551,9 +1526,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, ...@@ -1551,9 +1526,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
fprintf (dump_file, "because they have similar " fprintf (dump_file, "because they have similar "
"memory accesses\n"); "memory accesses\n");
} }
bitmap_ior_into (into->stmts, partition->stmts); partition_merge_into (into, partition);
if (partition->kind == PKIND_REDUCTION)
into->kind = PKIND_REDUCTION;
partitions.ordered_remove (j); partitions.ordered_remove (j);
partition_free (partition); partition_free (partition);
j--; j--;
...@@ -1577,9 +1550,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, ...@@ -1577,9 +1550,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
for (++i; partitions.iterate (i, &partition); ++i) for (++i; partitions.iterate (i, &partition); ++i)
if (!partition_builtin_p (partition)) if (!partition_builtin_p (partition))
{ {
bitmap_ior_into (into->stmts, partition->stmts); partition_merge_into (into, partition);
if (partition->kind == PKIND_REDUCTION)
into->kind = PKIND_REDUCTION;
partitions.ordered_remove (i); partitions.ordered_remove (i);
partition_free (partition); partition_free (partition);
i--; i--;
...@@ -1597,7 +1568,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, ...@@ -1597,7 +1568,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
for (i = partitions.length () - 2; i >= 0; --i) for (i = partitions.length () - 2; i >= 0; --i)
{ {
partition_t what = partitions[i]; partition_t what = partitions[i];
if (what->kind == PKIND_REDUCTION) if (partition_reduction_p (what))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
...@@ -1606,8 +1577,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, ...@@ -1606,8 +1577,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
dump_bitmap (dump_file, what->stmts); dump_bitmap (dump_file, what->stmts);
fprintf (dump_file, "because the latter has reductions\n"); fprintf (dump_file, "because the latter has reductions\n");
} }
bitmap_ior_into (into->stmts, what->stmts); partition_merge_into (into, what);
into->kind = PKIND_REDUCTION;
partitions.ordered_remove (i); partitions.ordered_remove (i);
partition_free (what); partition_free (what);
} }
...@@ -1627,7 +1597,11 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, ...@@ -1627,7 +1597,11 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
dump_rdg_partitions (dump_file, partitions); dump_rdg_partitions (dump_file, partitions);
FOR_EACH_VEC_ELT (partitions, i, partition) FOR_EACH_VEC_ELT (partitions, i, partition)
generate_code_for_partition (loop, partition, i < nbp - 1); {
if (partition_builtin_p (partition))
(*nb_calls)++;
generate_code_for_partition (loop, partition, i < nbp - 1);
}
ldist_done: ldist_done:
...@@ -1637,7 +1611,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, ...@@ -1637,7 +1611,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
free_rdg (rdg); free_rdg (rdg);
loop_nest.release (); loop_nest.release ();
return nbp; return nbp - *nb_calls;
} }
/* Distribute all loops in the current function. */ /* Distribute all loops in the current function. */
...@@ -1667,7 +1641,6 @@ tree_loop_distribution (void) ...@@ -1667,7 +1641,6 @@ tree_loop_distribution (void)
vec<gimple> work_list = vNULL; vec<gimple> work_list = vNULL;
basic_block *bbs; basic_block *bbs;
int num = loop->num; int num = loop->num;
int nb_generated_loops = 0;
unsigned int i; unsigned int i;
/* If the loop doesn't have a single exit we will fail anyway, /* If the loop doesn't have a single exit we will fail anyway,
...@@ -1722,6 +1695,9 @@ tree_loop_distribution (void) ...@@ -1722,6 +1695,9 @@ tree_loop_distribution (void)
out: out:
free (bbs); free (bbs);
int nb_generated_loops = 0;
int nb_generated_calls = 0;
location_t loc = find_loop_location (loop);
if (work_list.length () > 0) if (work_list.length () > 0)
{ {
if (!cd) if (!cd)
...@@ -1731,20 +1707,20 @@ out: ...@@ -1731,20 +1707,20 @@ out:
cd = new control_dependences (create_edge_list ()); cd = new control_dependences (create_edge_list ());
free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS);
} }
nb_generated_loops = distribute_loop (loop, work_list, cd); nb_generated_loops = distribute_loop (loop, work_list, cd,
&nb_generated_calls);
} }
if (nb_generated_loops > 0) if (nb_generated_loops + nb_generated_calls > 0)
changed = true;
if (dump_file && (dump_flags & TDF_DETAILS))
{ {
if (nb_generated_loops > 1) changed = true;
fprintf (dump_file, "Loop %d distributed: split to %d loops.\n", dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
num, nb_generated_loops); loc, "Loop %d distributed: split to %d loops "
else "and %d library calls.\n",
fprintf (dump_file, "Loop %d is the same.\n", num); num, nb_generated_loops, nb_generated_calls);
} }
else if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Loop %d is the same.\n", num);
work_list.release (); work_list.release ();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment