From 7b7f2ca76cec6c22c1b0bd1a6bb31baebddaca99 Mon Sep 17 00:00:00 2001 From: Sebastian Pop Date: Wed, 25 Nov 2009 05:28:05 +0000 Subject: [PATCH] graphite-interchange.c (lst_perfect_nestify): Pass 3 parameters for the loops created by the loop distribution. 2009-11-03 Sebastian Pop * 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 --- gcc/ChangeLog.graphite | 25 +++ gcc/graphite-interchange.c | 168 ++++++++++++------ gcc/graphite-poly.c | 1 - gcc/graphite-poly.h | 118 +++++++++++- gcc/testsuite/gcc.dg/graphite/interchange-1.c | 2 +- gcc/testsuite/gcc.dg/graphite/interchange-8.c | 2 +- 6 files changed, 257 insertions(+), 59 deletions(-) diff --git a/gcc/ChangeLog.graphite b/gcc/ChangeLog.graphite index 2662b613d3b..456555538b2 100644 --- a/gcc/ChangeLog.graphite +++ b/gcc/ChangeLog.graphite @@ -1,3 +1,28 @@ +2009-11-03 Sebastian Pop + + * 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 * graphite-interchange.c (lst_perfectly_nested_p): New. diff --git a/gcc/graphite-interchange.c b/gcc/graphite-interchange.c index 6bfa9ab63e4..6ac7fca84df 100644 --- a/gcc/graphite-interchange.c +++ b/gcc/graphite-interchange.c @@ -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; } diff --git a/gcc/graphite-poly.c b/gcc/graphite-poly.c index f628052d928..fa949cc9073 100644 --- a/gcc/graphite-poly.c +++ b/gcc/graphite-poly.c @@ -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; } diff --git a/gcc/graphite-poly.h b/gcc/graphite-poly.h index 6cd46ae0408..8f25a3715a1 100644 --- a/gcc/graphite-poly.h +++ b/gcc/graphite-poly.h @@ -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. */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-1.c b/gcc/testsuite/gcc.dg/graphite/interchange-1.c index 09ce4eafe62..cd9197d4d1a 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-1.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-1.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-8.c b/gcc/testsuite/gcc.dg/graphite/interchange-8.c index f002cc125cc..24b9a15a7ed 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-8.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-8.c @@ -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" } } */