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:
parent
6119e7d5ec
commit
7b7f2ca76c
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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" } } */
|
||||
|
@ -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" } } */
|
||||
|
Loading…
Reference in New Issue
Block a user