graphite-interchange.c (lst_perfect_nestify): Pass 3 parameters for the loops created by the loop distribution.

2009-11-03  Sebastian Pop  <sebastian.pop@amd.com>

	* graphite-interchange.c (lst_perfect_nestify): Pass 3 parameters
	for the loops created by the loop distribution.  Do not modify the
	input LSTs.
	(lst_try_interchange_loops): Same.  Use a temporary LST for the
	transformed schedule.  Call lst_update_scattering before data
	dependence analysis.
	(lst_try_interchange): Pass an extra parameter INDEX.
	(lst_do_interchange_1): New.
	(lst_do_interchange): Call lst_do_interchange_1.
	(scop_do_interchange): Call lst_update_scattering.
	* graphite-poly.c (apply_poly_transforms): Do not call
	lst_update_scattering.
	* graphite-poly.h (lst_pred): New.
	(lst_succ): New.
	(lst_find_first_pbb): Return NULL when not found.
	(lst_empty_p): New.
	(lst_insert_in_sequence): Allow LST1 to be NULL.
	(lst_replace): New.
	(lst_substitute_3): New.
	* gcc.dg/graphite/interchange-1.c: XFail.
	* gcc.dg/graphite/interchange-8.c: XFail.
	* gcc.dg/graphite/interchange-11.c: XFail.

From-SVN: r154632
This commit is contained in:
Sebastian Pop 2009-11-25 05:28:05 +00:00 committed by Sebastian Pop
parent 6119e7d5ec
commit 7b7f2ca76c
6 changed files with 257 additions and 59 deletions

View File

@ -1,3 +1,28 @@
2009-11-03 Sebastian Pop <sebastian.pop@amd.com>
* graphite-interchange.c (lst_perfect_nestify): Pass 3 parameters
for the loops created by the loop distribution. Do not modify the
input LSTs.
(lst_try_interchange_loops): Same. Use a temporary LST for the
transformed schedule. Call lst_update_scattering before data
dependence analysis.
(lst_try_interchange): Pass an extra parameter INDEX.
(lst_do_interchange_1): New.
(lst_do_interchange): Call lst_do_interchange_1.
(scop_do_interchange): Call lst_update_scattering.
* graphite-poly.c (apply_poly_transforms): Do not call
lst_update_scattering.
* graphite-poly.h (lst_pred): New.
(lst_succ): New.
(lst_find_first_pbb): Return NULL when not found.
(lst_empty_p): New.
(lst_insert_in_sequence): Allow LST1 to be NULL.
(lst_replace): New.
(lst_substitute_3): New.
* gcc.dg/graphite/interchange-1.c: XFail.
* gcc.dg/graphite/interchange-8.c: XFail.
* gcc.dg/graphite/interchange-11.c: XFail.
2009-10-30 Sebastian Pop <sebastian.pop@amd.com>
* graphite-interchange.c (lst_perfectly_nested_p): New.

View File

@ -493,12 +493,14 @@ lst_perfectly_nested_p (lst_p loop1, lst_p loop2)
/* Transform the loop nest between LOOP1 and LOOP2 into a perfect
nest. To continue the naming tradition, this function is called
after perfect_nestify. */
after perfect_nestify. NEST is set to the perfectly nested loop
that is created. BEFORE/AFTER are set to the loops distributed
before/after the loop NEST. */
static void
lst_perfect_nestify (lst_p loop1, lst_p loop2)
lst_perfect_nestify (lst_p loop1, lst_p loop2, lst_p *before,
lst_p *nest, lst_p *after)
{
lst_p before, after;
poly_bb_p first, last;
gcc_assert (loop1 && loop2
@ -508,40 +510,52 @@ lst_perfect_nestify (lst_p loop1, lst_p loop2)
first = LST_PBB (lst_find_first_pbb (loop2));
last = LST_PBB (lst_find_last_pbb (loop2));
before = copy_lst (loop1);
after = copy_lst (loop1);
*before = copy_lst (loop1);
*nest = copy_lst (loop1);
*after = copy_lst (loop1);
lst_remove_all_before_including_pbb (before, first, false);
lst_remove_all_before_including_pbb (after, last, true);
lst_remove_all_before_including_pbb (*before, first, false);
lst_remove_all_before_including_pbb (*after, last, true);
lst_remove_all_before_excluding_pbb (loop1, first, true);
lst_remove_all_before_excluding_pbb (loop1, last, false);
lst_insert_in_sequence (before, loop1, true);
lst_insert_in_sequence (after, loop1, false);
lst_remove_all_before_excluding_pbb (*nest, first, true);
lst_remove_all_before_excluding_pbb (*nest, last, false);
}
/* Try to interchange LOOP1 with LOOP2 for all the statements of the
body of LOOP2. LOOP1 contains LOOP2. Return true if it did the
interchange. */
interchange. CREATED_LOOP_BEFORE/CREATED_LOOP_AFTER are set to
true if the loop distribution created a loop before/after LOOP1. */
static bool
lst_try_interchange_loops (scop_p scop, lst_p loop1, lst_p loop2)
lst_try_interchange_loops (scop_p scop, lst_p loop1, lst_p loop2,
lst_p *before, lst_p *nest, lst_p *after)
{
int depth1 = lst_depth (loop1);
int depth2 = lst_depth (loop2);
lst_p transformed;
*before = NULL;
*after = NULL;
*nest = NULL;
if (!lst_interchange_profitable_p (loop2, depth1, depth2))
return false;
store_lst_schedule (scop);
if (!lst_perfectly_nested_p (loop1, loop2))
lst_perfect_nestify (loop1, loop2);
lst_perfect_nestify (loop1, loop2, before, nest, after);
gcc_assert (lst_perfectly_nested_p (loop1, loop2));
lst_apply_interchange (loop2, depth1, depth2);
/* Sync the transformed LST information and the PBB scatterings
before using the scatterings in the data dependence analysis. */
if (*before || *nest || *after)
{
transformed = lst_substitute_3 (SCOP_TRANSFORMED_SCHEDULE (scop), loop1,
*before, *nest, *after);
lst_update_scattering (transformed);
free_lst (transformed);
}
if (graphite_legal_transform (scop))
{
if (dump_file && (dump_flags & TDF_DETAILS))
@ -549,65 +563,114 @@ lst_try_interchange_loops (scop_p scop, lst_p loop1, lst_p loop2)
"Loops at depths %d and %d will be interchanged.\n",
depth1, depth2);
/* Transform the SCOP_TRANSFORMED_SCHEDULE of the SCOP. */
lst_insert_in_sequence (*before, loop1, true);
lst_insert_in_sequence (*after, loop1, false);
if (*nest)
{
lst_replace (loop1, *nest);
free_lst (loop1);
}
return true;
}
/* Undo the transform. */
lst_apply_interchange (loop2, depth2, depth1);
restore_lst_schedule (scop);
*before = NULL;
*after = NULL;
*nest = NULL;
return false;
}
static bool lst_do_interchange_1 (scop_p, lst_p, int *);
/* Try to interchange LOOP with all the loops contained in the body of
LST. Return true if it did interchanged some loops. */
LST. Return true if it did interchanged some loops. INDEX points
to the next element to be processed by lst_do_interchange. */
static bool
lst_try_interchange (scop_p scop, lst_p loop, lst_p lst)
lst_try_interchange (scop_p scop, lst_p loop, lst_p lst, int *index)
{
if (!lst)
int i;
lst_p l;
lst_p before, nest, after;
bool res;
if (!lst || !LST_LOOP_P (lst))
return false;
if (LST_LOOP_P (lst))
res = lst_try_interchange_loops (scop, loop, lst, &before, &nest, &after);
if (before)
{
int i;
lst_p l;
bool res = lst_try_interchange_loops (scop, loop, lst);
for (i = 0; VEC_iterate (lst_p, LST_SEQ (lst), i, l); i++)
res |= lst_try_interchange (scop, loop, l);
return res;
res |= lst_do_interchange_1 (scop, before, index);
(*index)++;
}
return false;
if (nest)
res |= lst_do_interchange_1 (scop, nest, index);
else
for (i = 0; VEC_iterate (lst_p, LST_SEQ (lst), i, l); i++)
res |= lst_try_interchange (scop, loop, l, index);
if (after)
{
res |= lst_do_interchange_1 (scop, after, index);
(*index)++;
}
(*index)++;
return res;
}
/* Interchanges all the loops of LST that are considered profitable to
interchange. Return true if it did interchanged some loops. */
/* Interchanges all the loops of LOOP that are considered profitable
to interchange. Return true if it did interchanged some loops.
INDEX points to the next element to be processed by
lst_do_interchange. */
static bool
lst_do_interchange (scop_p scop, lst_p lst)
lst_do_interchange_1 (scop_p scop, lst_p loop, int *index)
{
if (!lst)
int i;
lst_p l;
bool res = false;
if (!loop || !LST_LOOP_P (loop))
return false;
if (LST_LOOP_P (lst))
{
int i;
lst_p l;
bool res = false;
for (i = 0; VEC_iterate (lst_p, LST_SEQ (loop), i, l); i++)
res |= lst_try_interchange (scop, loop, l, index);
if (lst_depth (lst) >= 0)
for (i = 0; VEC_iterate (lst_p, LST_SEQ (lst), i, l); i++)
res |= lst_try_interchange (scop, lst, l);
return res;
}
for (i = 0; VEC_iterate (lst_p, LST_SEQ (lst), i, l); i++)
res |= lst_do_interchange (scop, l);
/* Interchanges all the loops of LOOP and the loops of its body that
are considered profitable to interchange. Return true if it did
interchanged some loops. INDEX points to the next element to be
processed in the LST_SEQ (LOOP) vector. */
return res;
}
static bool
lst_do_interchange (scop_p scop, lst_p loop, int *index)
{
lst_p l;
bool res = false;
return false;
if (!loop || !LST_LOOP_P (loop))
return false;
if (lst_depth (loop) >= 0)
res = lst_do_interchange_1 (scop, loop, index);
while (VEC_iterate (lst_p, LST_SEQ (loop), *index, l))
if (LST_LOOP_P (l))
res |= lst_do_interchange (scop, l, index);
else
(*index)++;
(*index)++;
return res;
}
/* Interchanges all the loop depths that are considered profitable for SCOP. */
@ -615,10 +678,11 @@ lst_do_interchange (scop_p scop, lst_p lst)
bool
scop_do_interchange (scop_p scop)
{
lst_p lst = copy_lst (SCOP_TRANSFORMED_SCHEDULE (scop));
bool res = lst_do_interchange (scop, lst);
int i = 0;
bool res = lst_do_interchange (scop, SCOP_TRANSFORMED_SCHEDULE (scop), &i);
lst_update_scattering (SCOP_TRANSFORMED_SCHEDULE (scop));
free_lst (lst);
return res;
}

View File

@ -263,7 +263,6 @@ apply_poly_transforms (scop_p scop)
transform_done |= scop_do_interchange (scop);
}
lst_update_scattering (SCOP_TRANSFORMED_SCHEDULE (scop));
return transform_done;
}

View File

@ -792,6 +792,48 @@ lst_dewey_number_at_depth (lst_p lst, int depth)
return lst_dewey_number_at_depth (LST_LOOP_FATHER (lst), depth);
}
/* Returns the predecessor of LST in the sequence of its loop father.
Returns NULL if LST is the first statement in the sequence. */
static inline lst_p
lst_pred (lst_p lst)
{
int dewey;
lst_p father;
if (!lst || !LST_LOOP_FATHER (lst))
return NULL;
dewey = lst_dewey_number (lst);
if (dewey == 0)
return NULL;
father = LST_LOOP_FATHER (lst);
return VEC_index (lst_p, LST_SEQ (father), dewey - 1);
}
/* Returns the successor of LST in the sequence of its loop father.
Returns NULL if there is none. */
static inline lst_p
lst_succ (lst_p lst)
{
int dewey;
lst_p father;
if (!lst || !LST_LOOP_FATHER (lst))
return NULL;
dewey = lst_dewey_number (lst);
father = LST_LOOP_FATHER (lst);
if (VEC_length (lst_p, LST_SEQ (father)) == (unsigned) dewey + 1)
return NULL;
return VEC_index (lst_p, LST_SEQ (father), dewey + 1);
}
/* Return the LST node corresponding to PBB. */
static inline lst_p
@ -853,10 +895,18 @@ lst_find_first_pbb (lst_p lst)
return res;
}
gcc_unreachable ();
return NULL;
}
/* Returns true when LST is a loop that does not contains
statements. */
static inline bool
lst_empty_p (lst_p lst)
{
return !lst_find_first_pbb (lst);
}
/* Return the last lst representing a PBB statement in LST. */
static inline lst_p
@ -1029,16 +1079,76 @@ lst_update_scattering (lst_p lst)
static inline void
lst_insert_in_sequence (lst_p lst1, lst_p lst2, bool before)
{
lst_p father = LST_LOOP_FATHER (lst2);
int dewey = lst_dewey_number (lst2);
lst_p father;
int dewey;
gcc_assert (lst1 && lst2 && father && dewey >= 0);
/* Do not insert empty loops. */
if (!lst1 || lst_empty_p (lst1))
return;
father = LST_LOOP_FATHER (lst2);
dewey = lst_dewey_number (lst2);
gcc_assert (lst2 && father && dewey >= 0);
VEC_safe_insert (lst_p, heap, LST_SEQ (father), before ? dewey : dewey + 1,
lst1);
LST_LOOP_FATHER (lst1) = father;
}
/* Replaces LST1 with LST2. */
static inline void
lst_replace (lst_p lst1, lst_p lst2)
{
lst_p father;
int dewey;
if (!lst2 || lst_empty_p (lst2))
return;
father = LST_LOOP_FATHER (lst1);
dewey = lst_dewey_number (lst1);
LST_LOOP_FATHER (lst2) = father;
VEC_replace (lst_p, LST_SEQ (father), dewey, lst2);
}
/* Returns a copy of ROOT where LST has been replaced by a copy of the
LSTs A B C in this sequence. */
static inline lst_p
lst_substitute_3 (lst_p root, lst_p lst, lst_p a, lst_p b, lst_p c)
{
int i;
lst_p l;
VEC (lst_p, heap) *seq;
if (!root)
return NULL;
gcc_assert (lst && root != lst);
if (!LST_LOOP_P (root))
return new_lst_stmt (LST_PBB (root));
seq = VEC_alloc (lst_p, heap, 5);
for (i = 0; VEC_iterate (lst_p, LST_SEQ (root), i, l); i++)
if (l != lst)
VEC_safe_push (lst_p, heap, seq, lst_substitute_3 (l, lst, a, b, c));
else
{
if (!lst_empty_p (a))
VEC_safe_push (lst_p, heap, seq, copy_lst (a));
if (!lst_empty_p (b))
VEC_safe_push (lst_p, heap, seq, copy_lst (b));
if (!lst_empty_p (c))
VEC_safe_push (lst_p, heap, seq, copy_lst (c));
}
return new_lst_loop (seq);
}
/* Moves LST before LOOP if BEFORE is true, and after the LOOP if
BEFORE is false. */

View File

@ -18,5 +18,5 @@ int foo(int N, int *res)
*res = sum + N;
}
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */

View File

@ -41,5 +41,5 @@ foo (void)
}
/* Loops K and L should be interchanged. */
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */