remove -floop-* flags
2015-08-27 Sebastian Pop <s.pop@samsung.com> * Makefile.in (OBJS): Remove graphite-blocking.o and graphite-interchange.o. * common.opt (floop-strip-mine, floop-interchange, floop-block): Alias of floop-nest-optimize. * doc/invoke.texi (floop-strip-mine, floop-interchange, floop-block): Document as alias of -floop-nest-optimize. * graphite-blocking.c: Remove. * graphite-interchange.c: Remove. * graphite-optimize-isl.c: Include dumpfile.h. (getScheduleForBand): Add dump for tiled loops. Use PARAM_LOOP_BLOCK_TILE_SIZE instead of hard coded constant. * graphite-poly.c (scop_max_loop_depth): Remove. (print_scattering_function_1): Remove. (print_scattering_function): Remove. (print_scattering_functions): Remove. (debug_scattering_function): Remove. (debug_scattering_functions): Remove. (apply_poly_transforms): Remove use of flag_loop_block, flag_loop_strip_mine, and flag_loop_interchange. (new_poly_bb): Remove use of PBB_TRANSFORMED, PBB_SAVED, and PBB_ORIGINAL. (print_pdr_access_layout): Remove. (print_pdr): Print ISL representation. (new_scop): Remove use of SCOP_ORIGINAL_SCHEDULE, SCOP_TRANSFORMED_SCHEDULE, and SCOP_SAVED_SCHEDULE. (free_scop): Same. (openscop_print_pbb_domain): Remove. (print_pbb): Remove call to print_scattering_function. (openscop_print_scop_context): Remove. (print_scop_context): Do not print matrices anymore. (print_scop): Do not print SCOP_ORIGINAL_SCHEDULE and SCOP_TRANSFORMED_SCHEDULE. (print_isl_set): Add printing of a new line. (print_isl_map): Same. (print_isl_aff): Same. (print_isl_constraint): Same. (loop_to_lst): Remove. (scop_to_lst): Remove. (lst_indent_to): Remove. (print_lst): Remove. (debug_lst): Remove. (dot_lst_1): Remove. (dot_lst): Remove. (reverse_loop_at_level): Remove. (reverse_loop_for_pbbs): Remove. * graphite-poly.h (pdr_dim_iter_domain): Remove. (pdr_nb_params): Remove. (pdr_alias_set_dim): Remove. (pdr_subscript_dim): Remove. (pdr_iterator_dim): Remove. (pdr_parameter_dim): Remove. (same_pdr_p): Remove. (struct poly_scattering): Remove. (struct poly_bb): Remove _original, _transformed, _saved. (PBB_DOMAIN, PBB_ORIGINAL, PBB_ORIGINAL_SCATTERING): Remove. (PBB_TRANSFORMED, PBB_TRANSFORMED_SCATTERING, PBB_SAVED): Remove. (PBB_NB_LOCAL_VARIABLES): Remove. (PBB_NB_SCATTERING_TRANSFORM): Remove. (schedule_to_scattering): Remove. (number_of_write_pdrs): Remove. (pbb_dim_iter_domain): Remove. (pbb_nb_params): Remove. (pbb_nb_scattering_orig): Remove. (pbb_nb_scattering_transform): Remove. (pbb_nb_dynamic_scattering_transform): Remove. (pbb_nb_local_vars): Remove. (pbb_iterator_dim): Remove. (pbb_parameter_dim): Remove. (psco_scattering_dim): Remove. (psct_scattering_dim): Remove. (psct_local_var_dim): Remove. (psco_iterator_dim): Remove. (psct_iterator_dim): Remove. (psco_parameter_dim): Remove. (psct_parameter_dim): Remove. (psct_dynamic_dim): Remove. (psct_static_dim): Remove. (psct_add_local_variable): Remove. (new_lst_loop): Remove. (new_lst_stmt): Remove. (free_lst): Remove. (copy_lst): Remove. (lst_add_loop_under_loop): Remove. (lst_depth): Remove. (lst_dewey_number): Remove. (lst_dewey_number_at_depth): Remove. (lst_pred): Remove. (lst_succ): Remove. (lst_find_pbb): Remove. (find_lst_loop): Remove. (lst_find_first_pbb): Remove. (lst_empty_p): Remove. (lst_find_last_pbb): Remove. (lst_contains_p): Remove. (lst_contains_pbb): Remove. (lst_create_nest): Remove. (lst_remove_from_sequence): Remove. (lst_remove_loop_and_inline_stmts_in_loop_father): Remove. (lst_niter_for_loop): Remove. (pbb_update_scattering): Remove. (lst_update_scattering_under): Remove. (lst_update_scattering): Remove. (lst_insert_in_sequence): Remove. (lst_replace): Remove. (lst_substitute_3): Remove. (lst_distribute_lst): Remove. (lst_remove_all_before_including_pbb): Remove. (lst_remove_all_before_excluding_pbb): Remove. (struct scop): Remove original_schedule, transformed_schedule, and saved_schedule. (SCOP_ORIGINAL_SCHEDULE, SCOP_TRANSFORMED_SCHEDULE): Remove. (SCOP_SAVED_SCHEDULE): Remove. (poly_scattering_new): Remove. (poly_scattering_free): Remove. (poly_scattering_copy): Remove. (store_scattering_pbb): Remove. (store_lst_schedule): Remove. (restore_lst_schedule): Remove. (store_scattering): Remove. (restore_scattering_pbb): Remove. (restore_scattering): Remove. * graphite-sese-to-poly.c (build_pbb_scattering_polyhedrons): Remove scattering_dimensions. Do not use pbb_dim_iter_domain: compute the scattering polyhedron dimension from the dimension of pbb->domain. (build_scop_scattering): Update call to build_pbb_scattering_polyhedrons. (build_poly_scop): Remove call to scop_to_lst. * graphite.c (graphite_transform_loops): Add call to print_scop. (gate_graphite_transforms): Remove use of flag_loop_block, flag_loop_interchange, and flag_loop_strip_mine. testsuite/ * gcc.dg/graphite/graphite.exp (interchange_files, block_files): Replaced by opt_files, compile with -floop-nest-optimize. * g++.dg/graphite/graphite.exp: Same. * gfortran.dg/graphite/graphite.exp: Same. * gcc.dg/graphite/block-0.c: Adjust pattern. * gcc.dg/graphite/block-1.c: Same. * gcc.dg/graphite/block-3.c: Same. * gcc.dg/graphite/block-4.c: Same. * gcc.dg/graphite/block-5.c: Same. * gcc.dg/graphite/block-6.c: Same. * gcc.dg/graphite/block-7.c: Same. * gcc.dg/graphite/block-8.c: Same. * gcc.dg/graphite/block-pr47654.c: Same. * gcc.dg/graphite/interchange-0.c: Same. * gcc.dg/graphite/interchange-1.c: Same. * gcc.dg/graphite/interchange-10.c: Same. * gcc.dg/graphite/interchange-11.c: Same. * gcc.dg/graphite/interchange-12.c: Same. * gcc.dg/graphite/interchange-13.c: Same. * gcc.dg/graphite/interchange-14.c: Same. * gcc.dg/graphite/interchange-15.c: Same. * gcc.dg/graphite/interchange-3.c: Same. * gcc.dg/graphite/interchange-4.c: Same. * gcc.dg/graphite/interchange-5.c: Same. * gcc.dg/graphite/interchange-6.c: Same. * gcc.dg/graphite/interchange-7.c: Same. * gcc.dg/graphite/interchange-8.c: Same. * gcc.dg/graphite/interchange-9.c: Same. * gcc.dg/graphite/interchange-mvt.c: Same. * gcc.dg/graphite/pr37485.c: Same. * gcc.dg/graphite/uns-block-1.c: Same. * gcc.dg/graphite/uns-interchange-12.c: Same. * gcc.dg/graphite/uns-interchange-14.c: Same. * gcc.dg/graphite/uns-interchange-15.c: Same. * gcc.dg/graphite/uns-interchange-9.c: Same. * gcc.dg/graphite/uns-interchange-mvt.c: Same. * gfortran.dg/graphite/interchange-3.f90: Same. From-SVN: r227277
This commit is contained in:
parent
31da952a49
commit
d6bb5ccfeb
134
gcc/ChangeLog
134
gcc/ChangeLog
|
@ -1,3 +1,137 @@
|
|||
2015-08-27 Sebastian Pop <s.pop@samsung.com>
|
||||
|
||||
* Makefile.in (OBJS): Remove graphite-blocking.o and
|
||||
graphite-interchange.o.
|
||||
* common.opt (floop-strip-mine, floop-interchange, floop-block):
|
||||
Alias of floop-nest-optimize.
|
||||
* doc/invoke.texi (floop-strip-mine, floop-interchange, floop-block):
|
||||
Document as alias of -floop-nest-optimize.
|
||||
* graphite-blocking.c: Remove.
|
||||
* graphite-interchange.c: Remove.
|
||||
* graphite-optimize-isl.c: Include dumpfile.h.
|
||||
(getScheduleForBand): Add dump for tiled loops. Use
|
||||
PARAM_LOOP_BLOCK_TILE_SIZE instead of hard coded constant.
|
||||
* graphite-poly.c (scop_max_loop_depth): Remove.
|
||||
(print_scattering_function_1): Remove.
|
||||
(print_scattering_function): Remove.
|
||||
(print_scattering_functions): Remove.
|
||||
(debug_scattering_function): Remove.
|
||||
(debug_scattering_functions): Remove.
|
||||
(apply_poly_transforms): Remove use of flag_loop_block,
|
||||
flag_loop_strip_mine, and flag_loop_interchange.
|
||||
(new_poly_bb): Remove use of PBB_TRANSFORMED, PBB_SAVED, and
|
||||
PBB_ORIGINAL.
|
||||
(print_pdr_access_layout): Remove.
|
||||
(print_pdr): Print ISL representation.
|
||||
(new_scop): Remove use of SCOP_ORIGINAL_SCHEDULE,
|
||||
SCOP_TRANSFORMED_SCHEDULE, and SCOP_SAVED_SCHEDULE.
|
||||
(free_scop): Same.
|
||||
(openscop_print_pbb_domain): Remove.
|
||||
(print_pbb): Remove call to print_scattering_function.
|
||||
(openscop_print_scop_context): Remove.
|
||||
(print_scop_context): Do not print matrices anymore.
|
||||
(print_scop): Do not print SCOP_ORIGINAL_SCHEDULE and
|
||||
SCOP_TRANSFORMED_SCHEDULE.
|
||||
(print_isl_set): Add printing of a new line.
|
||||
(print_isl_map): Same.
|
||||
(print_isl_aff): Same.
|
||||
(print_isl_constraint): Same.
|
||||
(loop_to_lst): Remove.
|
||||
(scop_to_lst): Remove.
|
||||
(lst_indent_to): Remove.
|
||||
(print_lst): Remove.
|
||||
(debug_lst): Remove.
|
||||
(dot_lst_1): Remove.
|
||||
(dot_lst): Remove.
|
||||
(reverse_loop_at_level): Remove.
|
||||
(reverse_loop_for_pbbs): Remove.
|
||||
* graphite-poly.h (pdr_dim_iter_domain): Remove.
|
||||
(pdr_nb_params): Remove.
|
||||
(pdr_alias_set_dim): Remove.
|
||||
(pdr_subscript_dim): Remove.
|
||||
(pdr_iterator_dim): Remove.
|
||||
(pdr_parameter_dim): Remove.
|
||||
(same_pdr_p): Remove.
|
||||
(struct poly_scattering): Remove.
|
||||
(struct poly_bb): Remove _original, _transformed, _saved.
|
||||
(PBB_DOMAIN, PBB_ORIGINAL, PBB_ORIGINAL_SCATTERING): Remove.
|
||||
(PBB_TRANSFORMED, PBB_TRANSFORMED_SCATTERING, PBB_SAVED): Remove.
|
||||
(PBB_NB_LOCAL_VARIABLES): Remove.
|
||||
(PBB_NB_SCATTERING_TRANSFORM): Remove.
|
||||
(schedule_to_scattering): Remove.
|
||||
(number_of_write_pdrs): Remove.
|
||||
(pbb_dim_iter_domain): Remove.
|
||||
(pbb_nb_params): Remove.
|
||||
(pbb_nb_scattering_orig): Remove.
|
||||
(pbb_nb_scattering_transform): Remove.
|
||||
(pbb_nb_dynamic_scattering_transform): Remove.
|
||||
(pbb_nb_local_vars): Remove.
|
||||
(pbb_iterator_dim): Remove.
|
||||
(pbb_parameter_dim): Remove.
|
||||
(psco_scattering_dim): Remove.
|
||||
(psct_scattering_dim): Remove.
|
||||
(psct_local_var_dim): Remove.
|
||||
(psco_iterator_dim): Remove.
|
||||
(psct_iterator_dim): Remove.
|
||||
(psco_parameter_dim): Remove.
|
||||
(psct_parameter_dim): Remove.
|
||||
(psct_dynamic_dim): Remove.
|
||||
(psct_static_dim): Remove.
|
||||
(psct_add_local_variable): Remove.
|
||||
(new_lst_loop): Remove.
|
||||
(new_lst_stmt): Remove.
|
||||
(free_lst): Remove.
|
||||
(copy_lst): Remove.
|
||||
(lst_add_loop_under_loop): Remove.
|
||||
(lst_depth): Remove.
|
||||
(lst_dewey_number): Remove.
|
||||
(lst_dewey_number_at_depth): Remove.
|
||||
(lst_pred): Remove.
|
||||
(lst_succ): Remove.
|
||||
(lst_find_pbb): Remove.
|
||||
(find_lst_loop): Remove.
|
||||
(lst_find_first_pbb): Remove.
|
||||
(lst_empty_p): Remove.
|
||||
(lst_find_last_pbb): Remove.
|
||||
(lst_contains_p): Remove.
|
||||
(lst_contains_pbb): Remove.
|
||||
(lst_create_nest): Remove.
|
||||
(lst_remove_from_sequence): Remove.
|
||||
(lst_remove_loop_and_inline_stmts_in_loop_father): Remove.
|
||||
(lst_niter_for_loop): Remove.
|
||||
(pbb_update_scattering): Remove.
|
||||
(lst_update_scattering_under): Remove.
|
||||
(lst_update_scattering): Remove.
|
||||
(lst_insert_in_sequence): Remove.
|
||||
(lst_replace): Remove.
|
||||
(lst_substitute_3): Remove.
|
||||
(lst_distribute_lst): Remove.
|
||||
(lst_remove_all_before_including_pbb): Remove.
|
||||
(lst_remove_all_before_excluding_pbb): Remove.
|
||||
(struct scop): Remove original_schedule, transformed_schedule, and
|
||||
saved_schedule.
|
||||
(SCOP_ORIGINAL_SCHEDULE, SCOP_TRANSFORMED_SCHEDULE): Remove.
|
||||
(SCOP_SAVED_SCHEDULE): Remove.
|
||||
(poly_scattering_new): Remove.
|
||||
(poly_scattering_free): Remove.
|
||||
(poly_scattering_copy): Remove.
|
||||
(store_scattering_pbb): Remove.
|
||||
(store_lst_schedule): Remove.
|
||||
(restore_lst_schedule): Remove.
|
||||
(store_scattering): Remove.
|
||||
(restore_scattering_pbb): Remove.
|
||||
(restore_scattering): Remove.
|
||||
* graphite-sese-to-poly.c (build_pbb_scattering_polyhedrons):
|
||||
Remove scattering_dimensions. Do not use pbb_dim_iter_domain:
|
||||
compute the scattering polyhedron dimension from the dimension of
|
||||
pbb->domain.
|
||||
(build_scop_scattering): Update call to
|
||||
build_pbb_scattering_polyhedrons.
|
||||
(build_poly_scop): Remove call to scop_to_lst.
|
||||
* graphite.c (graphite_transform_loops): Add call to print_scop.
|
||||
(gate_graphite_transforms): Remove use of flag_loop_block,
|
||||
flag_loop_interchange, and flag_loop_strip_mine.
|
||||
|
||||
2015-08-27 Sebastian Pop <s.pop@samsung.com>
|
||||
|
||||
* common.opt (floop-unroll-and-jam): Make alias of floop-nest-optimize.
|
||||
|
|
|
@ -1277,10 +1277,8 @@ OBJS = \
|
|||
graph.o \
|
||||
graphds.o \
|
||||
graphite.o \
|
||||
graphite-blocking.o \
|
||||
graphite-isl-ast-to-gimple.o \
|
||||
graphite-dependences.o \
|
||||
graphite-interchange.o \
|
||||
graphite-optimize-isl.o \
|
||||
graphite-poly.o \
|
||||
graphite-scop-detection.o \
|
||||
|
|
|
@ -1341,16 +1341,16 @@ Common Report Var(flag_loop_parallelize_all) Optimization
|
|||
Mark all loops as parallel
|
||||
|
||||
floop-strip-mine
|
||||
Common Report Var(flag_loop_strip_mine) Optimization
|
||||
Enable Loop Strip Mining transformation
|
||||
Common Alias(floop-nest-optimize)
|
||||
Enable loop nest transforms. Same as -floop-nest-optimize
|
||||
|
||||
floop-interchange
|
||||
Common Report Var(flag_loop_interchange) Optimization
|
||||
Enable Loop Interchange transformation
|
||||
Common Alias(floop-nest-optimize)
|
||||
Enable loop nest transforms. Same as -floop-nest-optimize
|
||||
|
||||
floop-block
|
||||
Common Report Var(flag_loop_block) Optimization
|
||||
Enable Loop Blocking transformation
|
||||
Common Alias(floop-nest-optimize)
|
||||
Enable loop nest transforms. Same as -floop-nest-optimize
|
||||
|
||||
floop-unroll-and-jam
|
||||
Common Alias(floop-nest-optimize)
|
||||
|
@ -2315,8 +2315,8 @@ Common Report Var(flag_tree_loop_im) Init(1) Optimization
|
|||
Enable loop invariant motion on trees
|
||||
|
||||
ftree-loop-linear
|
||||
Common Alias(floop-interchange)
|
||||
Enable loop interchange transforms. Same as -floop-interchange
|
||||
Common Alias(floop-nest-optimize)
|
||||
Enable loop nest transforms. Same as -floop-nest-optimize
|
||||
|
||||
ftree-loop-ivcanon
|
||||
Common Report Var(flag_tree_loop_ivcanon) Init(1) Optimization
|
||||
|
|
|
@ -8734,103 +8734,20 @@ Perform loop optimizations on trees. This flag is enabled by default
|
|||
at @option{-O} and higher.
|
||||
|
||||
@item -ftree-loop-linear
|
||||
@itemx -floop-interchange
|
||||
@itemx -floop-strip-mine
|
||||
@itemx -floop-block
|
||||
@itemx -floop-unroll-and-jam
|
||||
@opindex ftree-loop-linear
|
||||
Perform loop interchange transformations on tree. Same as
|
||||
@option{-floop-interchange}. To use this code transformation, GCC has
|
||||
@opindex floop-interchange
|
||||
@opindex floop-strip-mine
|
||||
@opindex floop-block
|
||||
@opindex floop-unroll-and-jam
|
||||
Perform loop nest optimizations. Same as
|
||||
@option{-floop-nest-optimize}. To use this code transformation, GCC has
|
||||
to be configured with @option{--with-isl} to enable the Graphite loop
|
||||
transformation infrastructure.
|
||||
|
||||
@item -floop-interchange
|
||||
@opindex floop-interchange
|
||||
Perform loop interchange transformations on loops. Interchanging two
|
||||
nested loops switches the inner and outer loops. For example, given a
|
||||
loop like:
|
||||
@smallexample
|
||||
DO J = 1, M
|
||||
DO I = 1, N
|
||||
A(J, I) = A(J, I) * C
|
||||
ENDDO
|
||||
ENDDO
|
||||
@end smallexample
|
||||
@noindent
|
||||
loop interchange transforms the loop as if it were written:
|
||||
@smallexample
|
||||
DO I = 1, N
|
||||
DO J = 1, M
|
||||
A(J, I) = A(J, I) * C
|
||||
ENDDO
|
||||
ENDDO
|
||||
@end smallexample
|
||||
which can be beneficial when @code{N} is larger than the caches,
|
||||
because in Fortran, the elements of an array are stored in memory
|
||||
contiguously by column, and the original loop iterates over rows,
|
||||
potentially creating at each access a cache miss. This optimization
|
||||
applies to all the languages supported by GCC and is not limited to
|
||||
Fortran. To use this code transformation, GCC has to be configured
|
||||
with @option{--with-isl} to enable the Graphite loop transformation
|
||||
infrastructure.
|
||||
|
||||
@item -floop-strip-mine
|
||||
@opindex floop-strip-mine
|
||||
Perform loop strip mining transformations on loops. Strip mining
|
||||
splits a loop into two nested loops. The outer loop has strides
|
||||
equal to the strip size and the inner loop has strides of the
|
||||
original loop within a strip. The strip length can be changed
|
||||
using the @option{loop-block-tile-size} parameter. For example,
|
||||
given a loop like:
|
||||
@smallexample
|
||||
DO I = 1, N
|
||||
A(I) = A(I) + C
|
||||
ENDDO
|
||||
@end smallexample
|
||||
@noindent
|
||||
loop strip mining transforms the loop as if it were written:
|
||||
@smallexample
|
||||
DO II = 1, N, 51
|
||||
DO I = II, min (II + 50, N)
|
||||
A(I) = A(I) + C
|
||||
ENDDO
|
||||
ENDDO
|
||||
@end smallexample
|
||||
This optimization applies to all the languages supported by GCC and is
|
||||
not limited to Fortran. To use this code transformation, GCC has to
|
||||
be configured with @option{--with-isl} to enable the Graphite loop
|
||||
transformation infrastructure.
|
||||
|
||||
@item -floop-block
|
||||
@opindex floop-block
|
||||
Perform loop blocking transformations on loops. Blocking strip mines
|
||||
each loop in the loop nest such that the memory accesses of the
|
||||
element loops fit inside caches. The strip length can be changed
|
||||
using the @option{loop-block-tile-size} parameter. For example, given
|
||||
a loop like:
|
||||
@smallexample
|
||||
DO I = 1, N
|
||||
DO J = 1, M
|
||||
A(J, I) = B(I) + C(J)
|
||||
ENDDO
|
||||
ENDDO
|
||||
@end smallexample
|
||||
@noindent
|
||||
loop blocking transforms the loop as if it were written:
|
||||
@smallexample
|
||||
DO II = 1, N, 51
|
||||
DO JJ = 1, M, 51
|
||||
DO I = II, min (II + 50, N)
|
||||
DO J = JJ, min (JJ + 50, M)
|
||||
A(J, I) = B(I) + C(J)
|
||||
ENDDO
|
||||
ENDDO
|
||||
ENDDO
|
||||
ENDDO
|
||||
@end smallexample
|
||||
which can be beneficial when @code{M} is larger than the caches,
|
||||
because the innermost loop iterates over a smaller amount of data
|
||||
which can be kept in the caches. This optimization applies to all the
|
||||
languages supported by GCC and is not limited to Fortran. To use this
|
||||
code transformation, GCC has to be configured with @option{--with-isl}
|
||||
to enable the Graphite loop transformation infrastructure.
|
||||
|
||||
@item -fgraphite-identity
|
||||
@opindex fgraphite-identity
|
||||
Enable the identity transformation for graphite. For every SCoP we generate
|
||||
|
@ -8847,13 +8764,6 @@ optimizer based on the Pluto optimization algorithms. It calculates a loop
|
|||
structure optimized for data-locality and parallelism. This option
|
||||
is experimental.
|
||||
|
||||
@item -floop-unroll-and-jam
|
||||
@opindex floop-unroll-and-jam
|
||||
Perform loop nest transformations. Same as
|
||||
@option{-floop-nest-optimize}. To use this code transformation, GCC has
|
||||
to be configured with @option{--with-isl} to enable the Graphite loop
|
||||
transformation infrastructure.
|
||||
|
||||
@item -floop-parallelize-all
|
||||
@opindex floop-parallelize-all
|
||||
Use the Graphite data dependence analysis to identify loops that can
|
||||
|
|
|
@ -1,270 +0,0 @@
|
|||
/* Heuristics and transform for loop blocking and strip mining on
|
||||
polyhedral representation.
|
||||
|
||||
Copyright (C) 2009-2015 Free Software Foundation, Inc.
|
||||
Contributed by Sebastian Pop <sebastian.pop@amd.com> and
|
||||
Pranav Garg <pranav.garg2107@gmail.com>.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_isl
|
||||
/* Workaround for GMP 5.1.3 bug, see PR56019. */
|
||||
#include <stddef.h>
|
||||
|
||||
#include <isl/constraint.h>
|
||||
#include <isl/set.h>
|
||||
#include <isl/map.h>
|
||||
#include <isl/union_map.h>
|
||||
#include <isl/constraint.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "backend.h"
|
||||
#include "cfghooks.h"
|
||||
#include "tree.h"
|
||||
#include "gimple.h"
|
||||
#include "params.h"
|
||||
#include "fold-const.h"
|
||||
#include "gimple-iterator.h"
|
||||
#include "tree-ssa-loop.h"
|
||||
#include "dumpfile.h"
|
||||
#include "cfgloop.h"
|
||||
#include "tree-data-ref.h"
|
||||
#include "graphite-poly.h"
|
||||
|
||||
/* Strip mines with a factor STRIDE the scattering (time) dimension
|
||||
around PBB at depth TIME_DEPTH.
|
||||
|
||||
The following example comes from the wiki page:
|
||||
http://gcc.gnu.org/wiki/Graphite/Strip_mine
|
||||
|
||||
The strip mine of a loop with a tile of 64 can be obtained with a
|
||||
scattering function as follows:
|
||||
|
||||
$ cat ./albert_strip_mine.cloog
|
||||
# language: C
|
||||
c
|
||||
|
||||
# parameter {n | n >= 0}
|
||||
1 3
|
||||
# n 1
|
||||
1 1 0
|
||||
1
|
||||
n
|
||||
|
||||
1 # Number of statements:
|
||||
|
||||
1
|
||||
# {i | 0 <= i <= n}
|
||||
2 4
|
||||
# i n 1
|
||||
1 1 0 0
|
||||
1 -1 1 0
|
||||
|
||||
0 0 0
|
||||
1
|
||||
i
|
||||
|
||||
1 # Scattering functions
|
||||
|
||||
3 6
|
||||
# NEW OLD i n 1
|
||||
1 -64 0 1 0 0
|
||||
1 64 0 -1 0 63
|
||||
0 0 1 -1 0 0
|
||||
|
||||
1
|
||||
NEW OLD
|
||||
|
||||
#the output of CLooG is like this:
|
||||
#$ cloog ./albert_strip_mine.cloog
|
||||
# for (NEW=0;NEW<=floord(n,64);NEW++) {
|
||||
# for (OLD=max(64*NEW,0);OLD<=min(64*NEW+63,n);OLD++) {
|
||||
# S1(i = OLD) ;
|
||||
# }
|
||||
# }
|
||||
*/
|
||||
|
||||
static void
|
||||
pbb_strip_mine_time_depth (poly_bb_p pbb, int time_depth, int stride)
|
||||
{
|
||||
isl_space *d;
|
||||
isl_constraint *c;
|
||||
int iter, strip;
|
||||
/* STRIP is the dimension that iterates with stride STRIDE. */
|
||||
/* ITER is the dimension that enumerates single iterations inside
|
||||
one strip that has at most STRIDE iterations. */
|
||||
strip = time_depth;
|
||||
iter = strip + 2;
|
||||
|
||||
pbb->transformed = isl_map_insert_dims (pbb->transformed, isl_dim_out,
|
||||
strip, 2);
|
||||
|
||||
/* Lower bound of the striped loop. */
|
||||
d = isl_map_get_space (pbb->transformed);
|
||||
c = isl_inequality_alloc (isl_local_space_from_space (d));
|
||||
c = isl_constraint_set_coefficient_si (c, isl_dim_out, strip, -stride);
|
||||
c = isl_constraint_set_coefficient_si (c, isl_dim_out, iter, 1);
|
||||
pbb->transformed = isl_map_add_constraint (pbb->transformed, c);
|
||||
|
||||
/* Upper bound of the striped loop. */
|
||||
d = isl_map_get_space (pbb->transformed);
|
||||
c = isl_inequality_alloc (isl_local_space_from_space (d));
|
||||
c = isl_constraint_set_coefficient_si (c, isl_dim_out, strip, stride);
|
||||
c = isl_constraint_set_coefficient_si (c, isl_dim_out, iter, -1);
|
||||
c = isl_constraint_set_constant_si (c, stride - 1);
|
||||
pbb->transformed = isl_map_add_constraint (pbb->transformed, c);
|
||||
|
||||
/* Static scheduling for ITER level.
|
||||
This is mandatory to keep the 2d + 1 canonical scheduling format. */
|
||||
d = isl_map_get_space (pbb->transformed);
|
||||
c = isl_equality_alloc (isl_local_space_from_space (d));
|
||||
c = isl_constraint_set_coefficient_si (c, isl_dim_out, strip + 1, 1);
|
||||
pbb->transformed = isl_map_add_constraint (pbb->transformed, c);
|
||||
}
|
||||
|
||||
/* Returns true when strip mining with STRIDE of the loop LST is
|
||||
profitable. */
|
||||
|
||||
static bool
|
||||
lst_strip_mine_profitable_p (lst_p lst, int stride)
|
||||
{
|
||||
mpz_t niter, strip_stride;
|
||||
bool res;
|
||||
|
||||
gcc_assert (LST_LOOP_P (lst));
|
||||
mpz_init (strip_stride);
|
||||
mpz_init (niter);
|
||||
|
||||
mpz_set_si (strip_stride, stride);
|
||||
lst_niter_for_loop (lst, niter);
|
||||
res = (mpz_cmp (niter, strip_stride) > 0);
|
||||
|
||||
mpz_clear (strip_stride);
|
||||
mpz_clear (niter);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Strip-mines all the loops of LST with STRIDE. Return the number of
|
||||
loops strip-mined. */
|
||||
|
||||
static int
|
||||
lst_do_strip_mine_loop (lst_p lst, int depth, int stride)
|
||||
{
|
||||
int i;
|
||||
lst_p l;
|
||||
poly_bb_p pbb;
|
||||
|
||||
if (!lst)
|
||||
return 0;
|
||||
|
||||
if (LST_LOOP_P (lst))
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l)
|
||||
res += lst_do_strip_mine_loop (l, depth, stride);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
pbb = LST_PBB (lst);
|
||||
pbb_strip_mine_time_depth (pbb, psct_dynamic_dim (pbb, depth), stride);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Strip-mines all the loops of LST with STRIDE. When STRIDE is zero,
|
||||
read the stride from the PARAM_LOOP_BLOCK_TILE_SIZE. Return the
|
||||
number of strip-mined loops.
|
||||
|
||||
Strip mining transforms a loop
|
||||
|
||||
| for (i = 0; i < N; i++)
|
||||
| S (i);
|
||||
|
||||
into the following loop nest:
|
||||
|
||||
| for (k = 0; k < N; k += STRIDE)
|
||||
| for (j = 0; j < STRIDE; j++)
|
||||
| S (i = k + j);
|
||||
*/
|
||||
|
||||
static int
|
||||
lst_do_strip_mine (lst_p lst, int stride)
|
||||
{
|
||||
int i;
|
||||
lst_p l;
|
||||
int res = 0;
|
||||
int depth;
|
||||
|
||||
if (!stride)
|
||||
stride = PARAM_VALUE (PARAM_LOOP_BLOCK_TILE_SIZE);
|
||||
|
||||
if (!lst
|
||||
|| !LST_LOOP_P (lst))
|
||||
return false;
|
||||
|
||||
FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l)
|
||||
res += lst_do_strip_mine (l, stride);
|
||||
|
||||
depth = lst_depth (lst);
|
||||
if (depth >= 0
|
||||
&& lst_strip_mine_profitable_p (lst, stride))
|
||||
{
|
||||
res += lst_do_strip_mine_loop (lst, lst_depth (lst), stride);
|
||||
lst_add_loop_under_loop (lst);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Strip mines all the loops in SCOP. Returns the number of
|
||||
strip-mined loops. */
|
||||
|
||||
int
|
||||
scop_do_strip_mine (scop_p scop, int stride)
|
||||
{
|
||||
return lst_do_strip_mine (SCOP_TRANSFORMED_SCHEDULE (scop), stride);
|
||||
}
|
||||
|
||||
/* Loop blocks all the loops in SCOP. Returns true when we manage to
|
||||
block some loops. */
|
||||
|
||||
bool
|
||||
scop_do_block (scop_p scop)
|
||||
{
|
||||
store_scattering (scop);
|
||||
|
||||
/* If we don't strip mine at least two loops, or not interchange
|
||||
loops, the strip mine alone will not be profitable, and the
|
||||
transform is not a loop blocking: so revert the transform. */
|
||||
if (lst_do_strip_mine (SCOP_TRANSFORMED_SCHEDULE (scop), 0) < 2
|
||||
|| scop_do_interchange (scop) == 0)
|
||||
{
|
||||
restore_scattering (scop);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
fprintf (dump_file, "SCoP will be loop blocked.\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,656 +0,0 @@
|
|||
/* Interchange heuristics and transform for loop interchange on
|
||||
polyhedral representation.
|
||||
|
||||
Copyright (C) 2009-2015 Free Software Foundation, Inc.
|
||||
Contributed by Sebastian Pop <sebastian.pop@amd.com> and
|
||||
Harsha Jagasia <harsha.jagasia@amd.com>.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_isl
|
||||
/* Workaround for GMP 5.1.3 bug, see PR56019. */
|
||||
#include <stddef.h>
|
||||
|
||||
#include <isl/constraint.h>
|
||||
#include <isl/aff.h>
|
||||
#include <isl/set.h>
|
||||
#include <isl/map.h>
|
||||
#include <isl/union_map.h>
|
||||
#include <isl/ilp.h>
|
||||
#include <isl/val.h>
|
||||
|
||||
/* Since ISL-0.13, the extern is in val_gmp.h. */
|
||||
#if !defined(HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE) && defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <isl/val_gmp.h>
|
||||
#if !defined(HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE) && defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "backend.h"
|
||||
#include "cfghooks.h"
|
||||
#include "tree.h"
|
||||
#include "gimple.h"
|
||||
#include "fold-const.h"
|
||||
#include "gimple-iterator.h"
|
||||
#include "tree-ssa-loop.h"
|
||||
#include "dumpfile.h"
|
||||
#include "cfgloop.h"
|
||||
#include "tree-data-ref.h"
|
||||
#include "graphite-poly.h"
|
||||
|
||||
|
||||
/* XXX isl rewrite following comment */
|
||||
/* Builds a linear expression, of dimension DIM, representing PDR's
|
||||
memory access:
|
||||
|
||||
L = r_{n}*r_{n-1}*...*r_{1}*s_{0} + ... + r_{n}*s_{n-1} + s_{n}.
|
||||
|
||||
For an array A[10][20] with two subscript locations s0 and s1, the
|
||||
linear memory access is 20 * s0 + s1: a stride of 1 in subscript s0
|
||||
corresponds to a memory stride of 20.
|
||||
|
||||
OFFSET is a number of dimensions to prepend before the
|
||||
subscript dimensions: s_0, s_1, ..., s_n.
|
||||
|
||||
Thus, the final linear expression has the following format:
|
||||
0 .. 0_{offset} | 0 .. 0_{nit} | 0 .. 0_{gd} | 0 | c_0 c_1 ... c_n
|
||||
where the expression itself is:
|
||||
c_0 * s_0 + c_1 * s_1 + ... c_n * s_n. */
|
||||
|
||||
static isl_constraint *
|
||||
build_linearized_memory_access (isl_map *map, poly_dr_p pdr)
|
||||
{
|
||||
isl_local_space *ls = isl_local_space_from_space (isl_map_get_space (map));
|
||||
isl_constraint *res = isl_equality_alloc (ls);
|
||||
isl_val *size = isl_val_int_from_ui (isl_map_get_ctx (map), 1);
|
||||
|
||||
unsigned nsubs = isl_set_dim (pdr->subscript_sizes, isl_dim_set);
|
||||
/* -1 for the already included L dimension. */
|
||||
unsigned offset = isl_map_dim (map, isl_dim_out) - 1 - nsubs;
|
||||
res = isl_constraint_set_coefficient_si (res, isl_dim_out, offset + nsubs, -1);
|
||||
/* Go through all subscripts from last to first. The dimension "i=0"
|
||||
is the alias set, ignore it. */
|
||||
for (int i = nsubs - 1; i >= 1; i--)
|
||||
{
|
||||
isl_aff *extract_dim;
|
||||
res = isl_constraint_set_coefficient_val (res, isl_dim_out, offset + i,
|
||||
isl_val_copy (size));
|
||||
isl_space *dc = isl_set_get_space (pdr->subscript_sizes);
|
||||
extract_dim = isl_aff_zero_on_domain (isl_local_space_from_space (dc));
|
||||
extract_dim = isl_aff_set_coefficient_si (extract_dim, isl_dim_in, i, 1);
|
||||
isl_val *max = isl_set_max_val (pdr->subscript_sizes, extract_dim);
|
||||
isl_aff_free (extract_dim);
|
||||
|
||||
/* The result is NULL in case of an error, the optimal value in case there
|
||||
is one, negative infinity or infinity if the problem is unbounded and
|
||||
NaN if the problem is empty. */
|
||||
gcc_assert (max);
|
||||
|
||||
/* When one of the dimensions cannot be computed, we cannot build the size
|
||||
of the array for any outer dimensions. */
|
||||
if (!isl_val_is_int (max))
|
||||
{
|
||||
isl_val_free (max);
|
||||
break;
|
||||
}
|
||||
size = isl_val_mul (size, max);
|
||||
}
|
||||
|
||||
isl_val_free (size);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Set STRIDE to the stride of PDR in memory by advancing by one in
|
||||
the loop at DEPTH. */
|
||||
|
||||
static void
|
||||
pdr_stride_in_loop (mpz_t stride, graphite_dim_t depth, poly_dr_p pdr)
|
||||
{
|
||||
poly_bb_p pbb = PDR_PBB (pdr);
|
||||
isl_map *map;
|
||||
isl_set *set;
|
||||
isl_aff *aff;
|
||||
isl_space *dc;
|
||||
isl_constraint *lma, *c;
|
||||
isl_val *islstride;
|
||||
graphite_dim_t time_depth;
|
||||
unsigned offset, nt;
|
||||
unsigned i;
|
||||
/* XXX isl rewrite following comments. */
|
||||
/* Builds a partial difference equations and inserts them
|
||||
into pointset powerset polyhedron P. Polyhedron is assumed
|
||||
to have the format: T|I|T'|I'|G|S|S'|l1|l2.
|
||||
|
||||
TIME_DEPTH is the time dimension w.r.t. which we are
|
||||
differentiating.
|
||||
OFFSET represents the number of dimensions between
|
||||
columns t_{time_depth} and t'_{time_depth}.
|
||||
DIM_SCTR is the number of scattering dimensions. It is
|
||||
essentially the dimensionality of the T vector.
|
||||
|
||||
The following equations are inserted into the polyhedron P:
|
||||
| t_1 = t_1'
|
||||
| ...
|
||||
| t_{time_depth-1} = t'_{time_depth-1}
|
||||
| t_{time_depth} = t'_{time_depth} + 1
|
||||
| t_{time_depth+1} = t'_{time_depth + 1}
|
||||
| ...
|
||||
| t_{dim_sctr} = t'_{dim_sctr}. */
|
||||
|
||||
/* Add the equality: t_{time_depth} = t'_{time_depth} + 1.
|
||||
This is the core part of this alogrithm, since this
|
||||
constraint asks for the memory access stride (difference)
|
||||
between two consecutive points in time dimensions. */
|
||||
|
||||
/* Add equalities:
|
||||
| t1 = t1'
|
||||
| ...
|
||||
| t_{time_depth-1} = t'_{time_depth-1}
|
||||
| t_{time_depth+1} = t'_{time_depth+1}
|
||||
| ...
|
||||
| t_{dim_sctr} = t'_{dim_sctr}
|
||||
|
||||
This means that all the time dimensions are equal except for
|
||||
time_depth, where the constraint is t_{depth} = t'_{depth} + 1
|
||||
step. More to this: we should be careful not to add equalities
|
||||
to the 'coupled' dimensions, which happens when the one dimension
|
||||
is stripmined dimension, and the other dimension corresponds
|
||||
to the point loop inside stripmined dimension. */
|
||||
|
||||
/* pdr->accesses: [P1..nb_param,I1..nb_domain]->[a,S1..nb_subscript]
|
||||
??? [P] not used for PDRs?
|
||||
pdr->subscript_sizes: [a,S1..nb_subscript]
|
||||
pbb->domain: [P1..nb_param,I1..nb_domain]
|
||||
pbb->transformed: [P1..nb_param,I1..nb_domain]->[T1..Tnb_sctr]
|
||||
[T] includes local vars (currently unused)
|
||||
|
||||
First we create [P,I] -> [T,a,S]. */
|
||||
|
||||
map = isl_map_flat_range_product (isl_map_copy (pbb->transformed),
|
||||
isl_map_copy (pdr->accesses));
|
||||
/* Add a dimension for L: [P,I] -> [T,a,S,L].*/
|
||||
map = isl_map_add_dims (map, isl_dim_out, 1);
|
||||
/* Build a constraint for "lma[S] - L == 0", effectively calculating
|
||||
L in terms of subscripts. */
|
||||
lma = build_linearized_memory_access (map, pdr);
|
||||
/* And add it to the map, so we now have:
|
||||
[P,I] -> [T,a,S,L] : lma([S]) == L. */
|
||||
map = isl_map_add_constraint (map, lma);
|
||||
|
||||
/* Then we create [P,I,P',I'] -> [T,a,S,L,T',a',S',L']. */
|
||||
map = isl_map_flat_product (map, isl_map_copy (map));
|
||||
|
||||
/* Now add the equality T[time_depth] == T'[time_depth]+1. This will
|
||||
force L' to be the linear address at T[time_depth] + 1. */
|
||||
time_depth = psct_dynamic_dim (pbb, depth);
|
||||
/* Length of [a,S] plus [L] ... */
|
||||
offset = 1 + isl_map_dim (pdr->accesses, isl_dim_out);
|
||||
/* ... plus [T]. */
|
||||
offset += isl_map_dim (pbb->transformed, isl_dim_out);
|
||||
|
||||
c = isl_equality_alloc (isl_local_space_from_space (isl_map_get_space (map)));
|
||||
c = isl_constraint_set_coefficient_si (c, isl_dim_out, time_depth, 1);
|
||||
c = isl_constraint_set_coefficient_si (c, isl_dim_out,
|
||||
offset + time_depth, -1);
|
||||
c = isl_constraint_set_constant_si (c, 1);
|
||||
map = isl_map_add_constraint (map, c);
|
||||
|
||||
/* Now we equate most of the T/T' elements (making PITaSL nearly
|
||||
the same is (PITaSL)', except for one dimension, namely for 'depth'
|
||||
(an index into [I]), after translating to index into [T]. Take care
|
||||
to not produce an empty map, which indicates we wanted to equate
|
||||
two dimensions that are already coupled via the above time_depth
|
||||
dimension. Happens with strip mining where several scatter dimension
|
||||
are interdependend. */
|
||||
/* Length of [T]. */
|
||||
nt = pbb_nb_scattering_transform (pbb) + pbb_nb_local_vars (pbb);
|
||||
for (i = 0; i < nt; i++)
|
||||
if (i != time_depth)
|
||||
{
|
||||
isl_map *temp = isl_map_equate (isl_map_copy (map),
|
||||
isl_dim_out, i,
|
||||
isl_dim_out, offset + i);
|
||||
if (isl_map_is_empty (temp))
|
||||
isl_map_free (temp);
|
||||
else
|
||||
{
|
||||
isl_map_free (map);
|
||||
map = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now maximize the expression L' - L. */
|
||||
set = isl_map_range (map);
|
||||
dc = isl_set_get_space (set);
|
||||
aff = isl_aff_zero_on_domain (isl_local_space_from_space (dc));
|
||||
aff = isl_aff_set_coefficient_si (aff, isl_dim_in, offset - 1, -1);
|
||||
aff = isl_aff_set_coefficient_si (aff, isl_dim_in, offset + offset - 1, 1);
|
||||
islstride = isl_set_max_val (set, aff);
|
||||
isl_val_get_num_gmp (islstride, stride);
|
||||
isl_val_free (islstride);
|
||||
isl_aff_free (aff);
|
||||
isl_set_free (set);
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
gmp_fprintf (dump_file, "\nStride in BB_%d, DR_%d, depth %d: %Zd ",
|
||||
pbb_index (pbb), PDR_ID (pdr), (int) depth, stride);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets STRIDES to the sum of all the strides of the data references
|
||||
accessed in LOOP at DEPTH. */
|
||||
|
||||
static void
|
||||
memory_strides_in_loop_1 (lst_p loop, graphite_dim_t depth, mpz_t strides)
|
||||
{
|
||||
int i, j;
|
||||
lst_p l;
|
||||
poly_dr_p pdr;
|
||||
mpz_t s, n;
|
||||
|
||||
mpz_init (s);
|
||||
mpz_init (n);
|
||||
|
||||
FOR_EACH_VEC_ELT (LST_SEQ (loop), j, l)
|
||||
if (LST_LOOP_P (l))
|
||||
memory_strides_in_loop_1 (l, depth, strides);
|
||||
else
|
||||
FOR_EACH_VEC_ELT (PBB_DRS (LST_PBB (l)), i, pdr)
|
||||
{
|
||||
pdr_stride_in_loop (s, depth, pdr);
|
||||
mpz_set_si (n, PDR_NB_REFS (pdr));
|
||||
mpz_mul (s, s, n);
|
||||
mpz_add (strides, strides, s);
|
||||
}
|
||||
|
||||
mpz_clear (s);
|
||||
mpz_clear (n);
|
||||
}
|
||||
|
||||
/* Sets STRIDES to the sum of all the strides of the data references
|
||||
accessed in LOOP at DEPTH. */
|
||||
|
||||
static void
|
||||
memory_strides_in_loop (lst_p loop, graphite_dim_t depth, mpz_t strides)
|
||||
{
|
||||
if (mpz_cmp_si (loop->memory_strides, -1) == 0)
|
||||
{
|
||||
mpz_set_si (strides, 0);
|
||||
memory_strides_in_loop_1 (loop, depth, strides);
|
||||
}
|
||||
else
|
||||
mpz_set (strides, loop->memory_strides);
|
||||
}
|
||||
|
||||
/* Return true when the interchange of loops LOOP1 and LOOP2 is
|
||||
profitable.
|
||||
|
||||
Example:
|
||||
|
||||
| int a[100][100];
|
||||
|
|
||||
| int
|
||||
| foo (int N)
|
||||
| {
|
||||
| int j;
|
||||
| int i;
|
||||
|
|
||||
| for (i = 0; i < N; i++)
|
||||
| for (j = 0; j < N; j++)
|
||||
| a[j][2 * i] += 1;
|
||||
|
|
||||
| return a[N][12];
|
||||
| }
|
||||
|
||||
The data access A[j][i] is described like this:
|
||||
|
||||
| i j N a s0 s1 1
|
||||
| 0 0 0 1 0 0 -5 = 0
|
||||
| 0 -1 0 0 1 0 0 = 0
|
||||
|-2 0 0 0 0 1 0 = 0
|
||||
| 0 0 0 0 1 0 0 >= 0
|
||||
| 0 0 0 0 0 1 0 >= 0
|
||||
| 0 0 0 0 -1 0 100 >= 0
|
||||
| 0 0 0 0 0 -1 100 >= 0
|
||||
|
||||
The linearized memory access L to A[100][100] is:
|
||||
|
||||
| i j N a s0 s1 1
|
||||
| 0 0 0 0 100 1 0
|
||||
|
||||
TODO: the shown format is not valid as it does not show the fact
|
||||
that the iteration domain "i j" is transformed using the scattering.
|
||||
|
||||
Next, to measure the impact of iterating once in loop "i", we build
|
||||
a maximization problem: first, we add to DR accesses the dimensions
|
||||
k, s2, s3, L1 = 100 * s0 + s1, L2, and D1: this is the polyhedron P1.
|
||||
L1 and L2 are the linearized memory access functions.
|
||||
|
||||
| i j N a s0 s1 k s2 s3 L1 L2 D1 1
|
||||
| 0 0 0 1 0 0 0 0 0 0 0 0 -5 = 0 alias = 5
|
||||
| 0 -1 0 0 1 0 0 0 0 0 0 0 0 = 0 s0 = j
|
||||
|-2 0 0 0 0 1 0 0 0 0 0 0 0 = 0 s1 = 2 * i
|
||||
| 0 0 0 0 1 0 0 0 0 0 0 0 0 >= 0
|
||||
| 0 0 0 0 0 1 0 0 0 0 0 0 0 >= 0
|
||||
| 0 0 0 0 -1 0 0 0 0 0 0 0 100 >= 0
|
||||
| 0 0 0 0 0 -1 0 0 0 0 0 0 100 >= 0
|
||||
| 0 0 0 0 100 1 0 0 0 -1 0 0 0 = 0 L1 = 100 * s0 + s1
|
||||
|
||||
Then, we generate the polyhedron P2 by interchanging the dimensions
|
||||
(s0, s2), (s1, s3), (L1, L2), (k, i)
|
||||
|
||||
| i j N a s0 s1 k s2 s3 L1 L2 D1 1
|
||||
| 0 0 0 1 0 0 0 0 0 0 0 0 -5 = 0 alias = 5
|
||||
| 0 -1 0 0 0 0 0 1 0 0 0 0 0 = 0 s2 = j
|
||||
| 0 0 0 0 0 0 -2 0 1 0 0 0 0 = 0 s3 = 2 * k
|
||||
| 0 0 0 0 0 0 0 1 0 0 0 0 0 >= 0
|
||||
| 0 0 0 0 0 0 0 0 1 0 0 0 0 >= 0
|
||||
| 0 0 0 0 0 0 0 -1 0 0 0 0 100 >= 0
|
||||
| 0 0 0 0 0 0 0 0 -1 0 0 0 100 >= 0
|
||||
| 0 0 0 0 0 0 0 100 1 0 -1 0 0 = 0 L2 = 100 * s2 + s3
|
||||
|
||||
then we add to P2 the equality k = i + 1:
|
||||
|
||||
|-1 0 0 0 0 0 1 0 0 0 0 0 -1 = 0 k = i + 1
|
||||
|
||||
and finally we maximize the expression "D1 = max (P1 inter P2, L2 - L1)".
|
||||
|
||||
Similarly, to determine the impact of one iteration on loop "j", we
|
||||
interchange (k, j), we add "k = j + 1", and we compute D2 the
|
||||
maximal value of the difference.
|
||||
|
||||
Finally, the profitability test is D1 < D2: if in the outer loop
|
||||
the strides are smaller than in the inner loop, then it is
|
||||
profitable to interchange the loops at DEPTH1 and DEPTH2. */
|
||||
|
||||
static bool
|
||||
lst_interchange_profitable_p (lst_p nest, int depth1, int depth2)
|
||||
{
|
||||
mpz_t d1, d2;
|
||||
bool res;
|
||||
|
||||
gcc_assert (depth1 < depth2);
|
||||
|
||||
mpz_init (d1);
|
||||
mpz_init (d2);
|
||||
|
||||
memory_strides_in_loop (nest, depth1, d1);
|
||||
memory_strides_in_loop (nest, depth2, d2);
|
||||
|
||||
res = mpz_cmp (d1, d2) < 0;
|
||||
|
||||
mpz_clear (d1);
|
||||
mpz_clear (d2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Interchanges the loops at DEPTH1 and DEPTH2 of the original
|
||||
scattering and assigns the resulting polyhedron to the transformed
|
||||
scattering. */
|
||||
|
||||
static void
|
||||
pbb_interchange_loop_depths (graphite_dim_t depth1, graphite_dim_t depth2,
|
||||
poly_bb_p pbb)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned dim1 = psct_dynamic_dim (pbb, depth1);
|
||||
unsigned dim2 = psct_dynamic_dim (pbb, depth2);
|
||||
isl_space *d = isl_map_get_space (pbb->transformed);
|
||||
isl_space *d1 = isl_space_range (d);
|
||||
unsigned n = isl_space_dim (d1, isl_dim_out);
|
||||
isl_space *d2 = isl_space_add_dims (d1, isl_dim_in, n);
|
||||
isl_map *x = isl_map_universe (d2);
|
||||
|
||||
x = isl_map_equate (x, isl_dim_in, dim1, isl_dim_out, dim2);
|
||||
x = isl_map_equate (x, isl_dim_in, dim2, isl_dim_out, dim1);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (i != dim1 && i != dim2)
|
||||
x = isl_map_equate (x, isl_dim_in, i, isl_dim_out, i);
|
||||
|
||||
pbb->transformed = isl_map_apply_range (pbb->transformed, x);
|
||||
}
|
||||
|
||||
/* Apply the interchange of loops at depths DEPTH1 and DEPTH2 to all
|
||||
the statements below LST. */
|
||||
|
||||
static void
|
||||
lst_apply_interchange (lst_p lst, int depth1, int depth2)
|
||||
{
|
||||
if (!lst)
|
||||
return;
|
||||
|
||||
if (LST_LOOP_P (lst))
|
||||
{
|
||||
int i;
|
||||
lst_p l;
|
||||
|
||||
FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l)
|
||||
lst_apply_interchange (l, depth1, depth2);
|
||||
}
|
||||
else
|
||||
pbb_interchange_loop_depths (depth1, depth2, LST_PBB (lst));
|
||||
}
|
||||
|
||||
/* Return true when the nest starting at LOOP1 and ending on LOOP2 is
|
||||
perfect: i.e. there are no sequence of statements. */
|
||||
|
||||
static bool
|
||||
lst_perfectly_nested_p (lst_p loop1, lst_p loop2)
|
||||
{
|
||||
if (loop1 == loop2)
|
||||
return true;
|
||||
|
||||
if (!LST_LOOP_P (loop1))
|
||||
return false;
|
||||
|
||||
return LST_SEQ (loop1).length () == 1
|
||||
&& lst_perfectly_nested_p (LST_SEQ (loop1)[0], 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. 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_p *before,
|
||||
lst_p *nest, lst_p *after)
|
||||
{
|
||||
poly_bb_p first, last;
|
||||
|
||||
gcc_assert (loop1 && loop2
|
||||
&& loop1 != loop2
|
||||
&& LST_LOOP_P (loop1) && LST_LOOP_P (loop2));
|
||||
|
||||
first = LST_PBB (lst_find_first_pbb (loop2));
|
||||
last = LST_PBB (lst_find_last_pbb (loop2));
|
||||
|
||||
*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_excluding_pbb (*nest, first, true);
|
||||
lst_remove_all_before_excluding_pbb (*nest, last, false);
|
||||
|
||||
if (lst_empty_p (*before))
|
||||
{
|
||||
free_lst (*before);
|
||||
*before = NULL;
|
||||
}
|
||||
if (lst_empty_p (*after))
|
||||
{
|
||||
free_lst (*after);
|
||||
*after = NULL;
|
||||
}
|
||||
if (lst_empty_p (*nest))
|
||||
{
|
||||
free_lst (*nest);
|
||||
*nest = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
static bool
|
||||
lst_try_interchange_loops (scop_p scop, lst_p loop1, lst_p loop2)
|
||||
{
|
||||
int depth1 = lst_depth (loop1);
|
||||
int depth2 = lst_depth (loop2);
|
||||
lst_p transformed;
|
||||
|
||||
lst_p before = NULL, nest = NULL, after = NULL;
|
||||
|
||||
if (!lst_perfectly_nested_p (loop1, loop2))
|
||||
lst_perfect_nestify (loop1, loop2, &before, &nest, &after);
|
||||
|
||||
if (!lst_interchange_profitable_p (loop2, depth1, depth2))
|
||||
return false;
|
||||
|
||||
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))
|
||||
fprintf (dump_file,
|
||||
"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. */
|
||||
free_lst (before);
|
||||
free_lst (nest);
|
||||
free_lst (after);
|
||||
lst_apply_interchange (loop2, depth2, depth1);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Selects the inner loop in LST_SEQ (INNER_FATHER) to be interchanged
|
||||
with the loop OUTER in LST_SEQ (OUTER_FATHER). */
|
||||
|
||||
static bool
|
||||
lst_interchange_select_inner (scop_p scop, lst_p outer_father, int outer,
|
||||
lst_p inner_father)
|
||||
{
|
||||
int inner;
|
||||
lst_p loop1, loop2;
|
||||
|
||||
gcc_assert (outer_father
|
||||
&& LST_LOOP_P (outer_father)
|
||||
&& LST_LOOP_P (LST_SEQ (outer_father)[outer])
|
||||
&& inner_father
|
||||
&& LST_LOOP_P (inner_father));
|
||||
|
||||
loop1 = LST_SEQ (outer_father)[outer];
|
||||
|
||||
FOR_EACH_VEC_ELT (LST_SEQ (inner_father), inner, loop2)
|
||||
if (LST_LOOP_P (loop2)
|
||||
&& (lst_try_interchange_loops (scop, loop1, loop2)
|
||||
|| lst_interchange_select_inner (scop, outer_father, outer, loop2)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Interchanges all the loops of LOOP and the loops of its body that
|
||||
are considered profitable to interchange. Return the number of
|
||||
interchanged loops. OUTER is the index in LST_SEQ (LOOP) that
|
||||
points to the next outer loop to be considered for interchange. */
|
||||
|
||||
static int
|
||||
lst_interchange_select_outer (scop_p scop, lst_p loop, int outer)
|
||||
{
|
||||
lst_p l;
|
||||
int res = 0;
|
||||
int i = 0;
|
||||
lst_p father;
|
||||
|
||||
if (!loop || !LST_LOOP_P (loop))
|
||||
return 0;
|
||||
|
||||
father = LST_LOOP_FATHER (loop);
|
||||
if (father)
|
||||
{
|
||||
while (lst_interchange_select_inner (scop, father, outer, loop))
|
||||
{
|
||||
res++;
|
||||
loop = LST_SEQ (father)[outer];
|
||||
}
|
||||
}
|
||||
|
||||
if (LST_LOOP_P (loop))
|
||||
FOR_EACH_VEC_ELT (LST_SEQ (loop), i, l)
|
||||
if (LST_LOOP_P (l))
|
||||
res += lst_interchange_select_outer (scop, l, i);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Interchanges all the loop depths that are considered profitable for
|
||||
SCOP. Return the number of interchanged loops. */
|
||||
|
||||
int
|
||||
scop_do_interchange (scop_p scop)
|
||||
{
|
||||
int res = lst_interchange_select_outer
|
||||
(scop, SCOP_TRANSFORMED_SCHEDULE (scop), 0);
|
||||
|
||||
lst_update_scattering (SCOP_TRANSFORMED_SCHEDULE (scop));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_isl */
|
||||
|
|
@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "tree-data-ref.h"
|
||||
#include "graphite-poly.h"
|
||||
#include "params.h"
|
||||
#include "dumpfile.h"
|
||||
|
||||
static isl_union_set *
|
||||
scop_get_domains (scop_p scop ATTRIBUTE_UNUSED)
|
||||
|
@ -177,12 +178,21 @@ getScheduleForBand (isl_band *Band, int *Dimensions)
|
|||
|
||||
/* It does not make any sense to tile a band with just one dimension. */
|
||||
if (*Dimensions == 1)
|
||||
return PartialSchedule;
|
||||
{
|
||||
if (dump_file && dump_flags)
|
||||
fprintf (dump_file, "not tiled\n");
|
||||
return PartialSchedule;
|
||||
}
|
||||
|
||||
if (dump_file && dump_flags)
|
||||
fprintf (dump_file, "tiled by %d\n",
|
||||
PARAM_VALUE (PARAM_LOOP_BLOCK_TILE_SIZE));
|
||||
|
||||
ctx = isl_union_map_get_ctx (PartialSchedule);
|
||||
Space = isl_union_map_get_space (PartialSchedule);
|
||||
|
||||
TileMap = getTileMap (ctx, *Dimensions, 32);
|
||||
TileMap = getTileMap (ctx, *Dimensions,
|
||||
PARAM_VALUE (PARAM_LOOP_BLOCK_TILE_SIZE));
|
||||
TileUMap = isl_union_map_from_map (isl_map_from_basic_map (TileMap));
|
||||
TileUMap = isl_union_map_align_params (TileUMap, Space);
|
||||
*Dimensions = 2 * *Dimensions;
|
||||
|
|
|
@ -69,94 +69,6 @@ debug_gmp_value (mpz_t val)
|
|||
gmp_fprintf (stderr, "%Zd", val);
|
||||
}
|
||||
|
||||
/* Return the maximal loop depth in SCOP. */
|
||||
|
||||
int
|
||||
scop_max_loop_depth (scop_p scop)
|
||||
{
|
||||
int i;
|
||||
poly_bb_p pbb;
|
||||
int max_nb_loops = 0;
|
||||
|
||||
FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb)
|
||||
{
|
||||
int nb_loops = pbb_dim_iter_domain (pbb);
|
||||
if (max_nb_loops < nb_loops)
|
||||
max_nb_loops = nb_loops;
|
||||
}
|
||||
|
||||
return max_nb_loops;
|
||||
}
|
||||
|
||||
/* Prints to FILE the scattering function of PBB, at some VERBOSITY
|
||||
level. */
|
||||
|
||||
static void
|
||||
print_scattering_function_1 (FILE *file, poly_bb_p pbb, int verbosity)
|
||||
{
|
||||
graphite_dim_t i;
|
||||
|
||||
if (verbosity > 0)
|
||||
{
|
||||
fprintf (file, "# scattering bb_%d (\n", pbb_index (pbb));
|
||||
fprintf (file, "#eq");
|
||||
|
||||
for (i = 0; i < pbb_nb_scattering_transform (pbb); i++)
|
||||
fprintf (file, " s%d", (int) i);
|
||||
|
||||
for (i = 0; i < pbb_nb_local_vars (pbb); i++)
|
||||
fprintf (file, " lv%d", (int) i);
|
||||
|
||||
for (i = 0; i < pbb_dim_iter_domain (pbb); i++)
|
||||
fprintf (file, " i%d", (int) i);
|
||||
|
||||
for (i = 0; i < pbb_nb_params (pbb); i++)
|
||||
fprintf (file, " p%d", (int) i);
|
||||
|
||||
fprintf (file, " cst\n");
|
||||
}
|
||||
|
||||
fprintf (file, "isl\n");
|
||||
print_isl_map (file, pbb->transformed ? pbb->transformed : pbb->schedule);
|
||||
|
||||
if (verbosity > 0)
|
||||
fprintf (file, "#)\n");
|
||||
}
|
||||
|
||||
/* Prints to FILE the scattering function of PBB, at some VERBOSITY
|
||||
level. */
|
||||
|
||||
void
|
||||
print_scattering_function (FILE *file, poly_bb_p pbb, int verbosity)
|
||||
{
|
||||
if (!PBB_TRANSFORMED (pbb))
|
||||
return;
|
||||
|
||||
if (pbb->schedule || pbb->transformed)
|
||||
{
|
||||
if (verbosity > 0)
|
||||
fprintf (file, "# Scattering function is provided\n");
|
||||
|
||||
fprintf (file, "1\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verbosity > 0)
|
||||
fprintf (file, "# Scattering function is not provided\n");
|
||||
|
||||
fprintf (file, "0\n");
|
||||
return;
|
||||
}
|
||||
|
||||
print_scattering_function_1 (file, pbb, verbosity);
|
||||
|
||||
if (verbosity > 0)
|
||||
fprintf (file, "# Scattering names are not provided\n");
|
||||
|
||||
fprintf (file, "0\n");
|
||||
|
||||
}
|
||||
|
||||
/* Prints to FILE the iteration domain of PBB, at some VERBOSITY
|
||||
level. */
|
||||
|
||||
|
@ -166,18 +78,6 @@ print_iteration_domain (FILE *file, poly_bb_p pbb, int verbosity)
|
|||
print_pbb_domain (file, pbb, verbosity);
|
||||
}
|
||||
|
||||
/* Prints to FILE the scattering functions of every PBB of SCOP. */
|
||||
|
||||
void
|
||||
print_scattering_functions (FILE *file, scop_p scop, int verbosity)
|
||||
{
|
||||
int i;
|
||||
poly_bb_p pbb;
|
||||
|
||||
FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb)
|
||||
print_scattering_function (file, pbb, verbosity);
|
||||
}
|
||||
|
||||
/* Prints to FILE the iteration domains of every PBB of SCOP, at some
|
||||
VERBOSITY level. */
|
||||
|
||||
|
@ -191,15 +91,6 @@ print_iteration_domains (FILE *file, scop_p scop, int verbosity)
|
|||
print_iteration_domain (file, pbb, verbosity);
|
||||
}
|
||||
|
||||
/* Prints to STDERR the scattering function of PBB, at some VERBOSITY
|
||||
level. */
|
||||
|
||||
DEBUG_FUNCTION void
|
||||
debug_scattering_function (poly_bb_p pbb, int verbosity)
|
||||
{
|
||||
print_scattering_function (stderr, pbb, verbosity);
|
||||
}
|
||||
|
||||
/* Prints to STDERR the iteration domain of PBB, at some VERBOSITY
|
||||
level. */
|
||||
|
||||
|
@ -209,15 +100,6 @@ debug_iteration_domain (poly_bb_p pbb, int verbosity)
|
|||
print_iteration_domain (stderr, pbb, verbosity);
|
||||
}
|
||||
|
||||
/* Prints to STDERR the scattering functions of every PBB of SCOP, at
|
||||
some VERBOSITY level. */
|
||||
|
||||
DEBUG_FUNCTION void
|
||||
debug_scattering_functions (scop_p scop, int verbosity)
|
||||
{
|
||||
print_scattering_functions (stderr, scop, verbosity);
|
||||
}
|
||||
|
||||
/* Prints to STDERR the iteration domains of every PBB of SCOP, at
|
||||
some VERBOSITY level. */
|
||||
|
||||
|
@ -236,28 +118,13 @@ apply_poly_transforms (scop_p scop)
|
|||
|
||||
/* Generate code even if we did not apply any real transformation.
|
||||
This also allows to check the performance for the identity
|
||||
transformation: GIMPLE -> GRAPHITE -> GIMPLE
|
||||
Keep in mind that CLooG optimizes in control, so the loop structure
|
||||
may change, even if we only use -fgraphite-identity. */
|
||||
transformation: GIMPLE -> GRAPHITE -> GIMPLE. */
|
||||
if (flag_graphite_identity)
|
||||
transform_done = true;
|
||||
|
||||
if (flag_loop_parallelize_all)
|
||||
transform_done = true;
|
||||
|
||||
if (flag_loop_block)
|
||||
transform_done |= scop_do_block (scop);
|
||||
else
|
||||
{
|
||||
if (flag_loop_strip_mine)
|
||||
transform_done |= scop_do_strip_mine (scop, 0);
|
||||
|
||||
if (flag_loop_interchange)
|
||||
transform_done |= scop_do_interchange (scop);
|
||||
}
|
||||
|
||||
/* This pass needs to be run at the final stage, as it does not
|
||||
update the lst. */
|
||||
if (flag_loop_optimize_isl)
|
||||
transform_done |= optimize_isl (scop);
|
||||
|
||||
|
@ -311,9 +178,6 @@ new_poly_bb (scop_p scop, void *black_box)
|
|||
pbb->saved = NULL;
|
||||
PBB_SCOP (pbb) = scop;
|
||||
pbb_set_black_box (pbb, black_box);
|
||||
PBB_TRANSFORMED (pbb) = NULL;
|
||||
PBB_SAVED (pbb) = NULL;
|
||||
PBB_ORIGINAL (pbb) = NULL;
|
||||
PBB_DRS (pbb).create (3);
|
||||
PBB_IS_REDUCTION (pbb) = false;
|
||||
GBB_PBB ((gimple_bb_p) black_box) = pbb;
|
||||
|
@ -342,27 +206,6 @@ free_poly_bb (poly_bb_p pbb)
|
|||
XDELETE (pbb);
|
||||
}
|
||||
|
||||
static void
|
||||
print_pdr_access_layout (FILE *file, poly_bb_p pbb, poly_dr_p pdr)
|
||||
{
|
||||
graphite_dim_t i;
|
||||
|
||||
fprintf (file, "# eq");
|
||||
|
||||
fprintf (file, " alias");
|
||||
|
||||
for (i = 0; i < PDR_NB_SUBSCRIPTS (pdr); i++)
|
||||
fprintf (file, " sub%d", (int) i);
|
||||
|
||||
for (i = 0; i < pbb_dim_iter_domain (pbb); i++)
|
||||
fprintf (file, " i%d", (int) i);
|
||||
|
||||
for (i = 0; i < pbb_nb_params (pbb); i++)
|
||||
fprintf (file, " p%d", (int) i);
|
||||
|
||||
fprintf (file, " cst\n");
|
||||
}
|
||||
|
||||
/* Prints to FILE the polyhedral data reference PDR, at some VERBOSITY
|
||||
level. */
|
||||
|
||||
|
@ -397,14 +240,10 @@ print_pdr (FILE *file, poly_dr_p pdr, int verbosity)
|
|||
if (verbosity > 0)
|
||||
{
|
||||
fprintf (file, "# data accesses (\n");
|
||||
print_pdr_access_layout (file, PDR_PBB (pdr), pdr);
|
||||
print_isl_map (file, pdr->accesses);
|
||||
print_isl_set (file, pdr->subscript_sizes);
|
||||
fprintf (file, "#)\n");
|
||||
}
|
||||
|
||||
/* XXX isl dump accesses/subscripts */
|
||||
|
||||
if (verbosity > 0)
|
||||
fprintf (file, "#)\n");
|
||||
|
||||
if (verbosity > 1)
|
||||
fprintf (file, "#)\n");
|
||||
}
|
||||
|
@ -440,9 +279,6 @@ new_scop (sese region)
|
|||
scop->may_waw_no_source = NULL;
|
||||
scop_set_region (scop, region);
|
||||
SCOP_BBS (scop).create (3);
|
||||
SCOP_ORIGINAL_SCHEDULE (scop) = NULL;
|
||||
SCOP_TRANSFORMED_SCHEDULE (scop) = NULL;
|
||||
SCOP_SAVED_SCHEDULE (scop) = NULL;
|
||||
POLY_SCOP_P (scop) = false;
|
||||
|
||||
return scop;
|
||||
|
@ -474,44 +310,9 @@ free_scop (scop_p scop)
|
|||
isl_union_map_free (scop->may_waw);
|
||||
isl_union_map_free (scop->must_waw_no_source);
|
||||
isl_union_map_free (scop->may_waw_no_source);
|
||||
free_lst (SCOP_ORIGINAL_SCHEDULE (scop));
|
||||
free_lst (SCOP_TRANSFORMED_SCHEDULE (scop));
|
||||
free_lst (SCOP_SAVED_SCHEDULE (scop));
|
||||
XDELETE (scop);
|
||||
}
|
||||
|
||||
/* Print to FILE the domain of PBB in OpenScop format, at some VERBOSITY
|
||||
level. */
|
||||
|
||||
static void
|
||||
openscop_print_pbb_domain (FILE *file, poly_bb_p pbb, int verbosity)
|
||||
{
|
||||
graphite_dim_t i;
|
||||
gimple_bb_p gbb = PBB_BLACK_BOX (pbb);
|
||||
|
||||
if (!pbb->domain)
|
||||
return;
|
||||
|
||||
if (verbosity > 0)
|
||||
{
|
||||
fprintf (file, "\n# Iteration domain of bb_%d (\n", GBB_BB (gbb)->index);
|
||||
fprintf (file, "#eq");
|
||||
|
||||
for (i = 0; i < pbb_dim_iter_domain (pbb); i++)
|
||||
fprintf (file, " i%d", (int) i);
|
||||
|
||||
for (i = 0; i < pbb_nb_params (pbb); i++)
|
||||
fprintf (file, " p%d", (int) i);
|
||||
|
||||
fprintf (file, " cst\n");
|
||||
}
|
||||
|
||||
fprintf (file, "XXX isl\n");
|
||||
|
||||
if (verbosity > 0)
|
||||
fprintf (file, "#)\n");
|
||||
}
|
||||
|
||||
/* Print to FILE the domain of PBB, at some VERBOSITY level. */
|
||||
|
||||
void
|
||||
|
@ -699,8 +500,7 @@ print_pbb (FILE *file, poly_bb_p pbb, int verbosity)
|
|||
dump_gbb_cases (file, PBB_BLACK_BOX (pbb));
|
||||
}
|
||||
|
||||
openscop_print_pbb_domain (file, pbb, verbosity);
|
||||
print_scattering_function (file, pbb, verbosity);
|
||||
print_pbb_domain (file, pbb, verbosity);
|
||||
print_pdrs (file, pbb, verbosity);
|
||||
print_pbb_body (file, pbb, verbosity, false);
|
||||
|
||||
|
@ -748,58 +548,16 @@ print_scop_params (FILE *file, scop_p scop, int verbosity)
|
|||
fprintf (file, "#)\n");
|
||||
}
|
||||
|
||||
/* Print to FILE the context of SCoP in OpenScop format, at some VERBOSITY
|
||||
level. */
|
||||
|
||||
static void
|
||||
openscop_print_scop_context (FILE *file, scop_p scop, int verbosity)
|
||||
{
|
||||
graphite_dim_t i;
|
||||
|
||||
if (verbosity > 0)
|
||||
{
|
||||
fprintf (file, "# Context (\n");
|
||||
fprintf (file, "#eq");
|
||||
|
||||
for (i = 0; i < scop_nb_params (scop); i++)
|
||||
fprintf (file, " p%d", (int) i);
|
||||
|
||||
fprintf (file, " cst\n");
|
||||
}
|
||||
|
||||
if (scop->context)
|
||||
/* XXX isl print context */
|
||||
fprintf (file, "XXX isl\n");
|
||||
else
|
||||
fprintf (file, "0 %d 0 0 0 %d\n", (int) scop_nb_params (scop) + 2,
|
||||
(int) scop_nb_params (scop));
|
||||
|
||||
if (verbosity > 0)
|
||||
fprintf (file, "# )\n");
|
||||
}
|
||||
|
||||
/* Print to FILE the context of SCoP, at some VERBOSITY level. */
|
||||
|
||||
void
|
||||
print_scop_context (FILE *file, scop_p scop, int verbosity)
|
||||
{
|
||||
graphite_dim_t i;
|
||||
|
||||
if (verbosity > 0)
|
||||
{
|
||||
fprintf (file, "# Context (\n");
|
||||
fprintf (file, "#eq");
|
||||
|
||||
for (i = 0; i < scop_nb_params (scop); i++)
|
||||
fprintf (file, " p%d", (int) i);
|
||||
|
||||
fprintf (file, " cst\n");
|
||||
}
|
||||
fprintf (file, "# Context (\n");
|
||||
|
||||
if (scop->context)
|
||||
print_isl_set (file, scop->context);
|
||||
else
|
||||
fprintf (file, "no isl context %d\n", (int) scop_nb_params (scop) + 2);
|
||||
|
||||
if (verbosity > 0)
|
||||
fprintf (file, "# )\n");
|
||||
|
@ -815,7 +573,7 @@ print_scop (FILE *file, scop_p scop, int verbosity)
|
|||
|
||||
fprintf (file, "SCoP 1\n#(\n");
|
||||
fprintf (file, "# Language\nGimple\n");
|
||||
openscop_print_scop_context (file, scop, verbosity);
|
||||
print_scop_context (file, scop, verbosity);
|
||||
print_scop_params (file, scop, verbosity);
|
||||
|
||||
if (verbosity > 0)
|
||||
|
@ -826,17 +584,6 @@ print_scop (FILE *file, scop_p scop, int verbosity)
|
|||
FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb)
|
||||
print_pbb (file, pbb, verbosity);
|
||||
|
||||
if (verbosity > 1)
|
||||
{
|
||||
fprintf (file, "# original_lst (\n");
|
||||
print_lst (file, SCOP_ORIGINAL_SCHEDULE (scop), 0);
|
||||
fprintf (file, "\n#)\n");
|
||||
|
||||
fprintf (file, "# transformed_lst (\n");
|
||||
print_lst (file, SCOP_TRANSFORMED_SCHEDULE (scop), 0);
|
||||
fprintf (file, "\n#)\n");
|
||||
}
|
||||
|
||||
fprintf (file, "#)\n");
|
||||
}
|
||||
|
||||
|
@ -888,6 +635,7 @@ print_isl_set (FILE *f, isl_set *set)
|
|||
{
|
||||
isl_printer *p = isl_printer_to_file (the_isl_ctx, f);
|
||||
p = isl_printer_print_set (p, set);
|
||||
p = isl_printer_print_str (p, "\n");
|
||||
isl_printer_free (p);
|
||||
}
|
||||
|
||||
|
@ -902,6 +650,7 @@ print_isl_map (FILE *f, isl_map *map)
|
|||
{
|
||||
isl_printer *p = isl_printer_to_file (the_isl_ctx, f);
|
||||
p = isl_printer_print_map (p, map);
|
||||
p = isl_printer_print_str (p, "\n");
|
||||
isl_printer_free (p);
|
||||
}
|
||||
|
||||
|
@ -916,6 +665,7 @@ print_isl_aff (FILE *f, isl_aff *aff)
|
|||
{
|
||||
isl_printer *p = isl_printer_to_file (the_isl_ctx, f);
|
||||
p = isl_printer_print_aff (p, aff);
|
||||
p = isl_printer_print_str (p, "\n");
|
||||
isl_printer_free (p);
|
||||
}
|
||||
|
||||
|
@ -930,6 +680,7 @@ print_isl_constraint (FILE *f, isl_constraint *c)
|
|||
{
|
||||
isl_printer *p = isl_printer_to_file (the_isl_ctx, f);
|
||||
p = isl_printer_print_constraint (p, c);
|
||||
p = isl_printer_print_str (p, "\n");
|
||||
isl_printer_free (p);
|
||||
}
|
||||
|
||||
|
@ -976,224 +727,5 @@ pbb_number_of_iterations_at_time (poly_bb_p pbb,
|
|||
isl_set_free (transdomain);
|
||||
}
|
||||
|
||||
/* Translates LOOP to LST. */
|
||||
|
||||
static lst_p
|
||||
loop_to_lst (loop_p loop, vec<poly_bb_p> bbs, int *i)
|
||||
{
|
||||
poly_bb_p pbb;
|
||||
vec<lst_p> seq;
|
||||
seq.create (5);
|
||||
|
||||
for (; bbs.iterate (*i, &pbb); (*i)++)
|
||||
{
|
||||
lst_p stmt;
|
||||
basic_block bb = GBB_BB (PBB_BLACK_BOX (pbb));
|
||||
|
||||
if (bb->loop_father == loop)
|
||||
stmt = new_lst_stmt (pbb);
|
||||
else if (flow_bb_inside_loop_p (loop, bb))
|
||||
{
|
||||
loop_p next = loop->inner;
|
||||
|
||||
while (next && !flow_bb_inside_loop_p (next, bb))
|
||||
next = next->next;
|
||||
|
||||
stmt = loop_to_lst (next, bbs, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*i)--;
|
||||
return new_lst_loop (seq);
|
||||
}
|
||||
|
||||
seq.safe_push (stmt);
|
||||
}
|
||||
|
||||
return new_lst_loop (seq);
|
||||
}
|
||||
|
||||
/* Reads the original scattering of the SCOP and returns an LST
|
||||
representing it. */
|
||||
|
||||
void
|
||||
scop_to_lst (scop_p scop)
|
||||
{
|
||||
lst_p res;
|
||||
int i, n = SCOP_BBS (scop).length ();
|
||||
vec<lst_p> seq;
|
||||
seq.create (5);
|
||||
sese region = SCOP_REGION (scop);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
poly_bb_p pbb = SCOP_BBS (scop)[i];
|
||||
loop_p loop = outermost_loop_in_sese (region, GBB_BB (PBB_BLACK_BOX (pbb)));
|
||||
|
||||
if (loop_in_sese_p (loop, region))
|
||||
res = loop_to_lst (loop, SCOP_BBS (scop), &i);
|
||||
else
|
||||
res = new_lst_stmt (pbb);
|
||||
|
||||
seq.safe_push (res);
|
||||
}
|
||||
|
||||
res = new_lst_loop (seq);
|
||||
SCOP_ORIGINAL_SCHEDULE (scop) = res;
|
||||
SCOP_TRANSFORMED_SCHEDULE (scop) = copy_lst (res);
|
||||
}
|
||||
|
||||
/* Print to FILE on a new line COLUMN white spaces. */
|
||||
|
||||
static void
|
||||
lst_indent_to (FILE *file, int column)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (column > 0)
|
||||
fprintf (file, "\n#");
|
||||
|
||||
for (i = 0; i < column; i++)
|
||||
fprintf (file, " ");
|
||||
}
|
||||
|
||||
/* Print LST to FILE with INDENT spaces of indentation. */
|
||||
|
||||
void
|
||||
print_lst (FILE *file, lst_p lst, int indent)
|
||||
{
|
||||
if (!lst)
|
||||
return;
|
||||
|
||||
lst_indent_to (file, indent);
|
||||
|
||||
if (LST_LOOP_P (lst))
|
||||
{
|
||||
int i;
|
||||
lst_p l;
|
||||
|
||||
if (LST_LOOP_FATHER (lst))
|
||||
fprintf (file, "%d (loop", lst_dewey_number (lst));
|
||||
else
|
||||
fprintf (file, "#(root");
|
||||
|
||||
FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l)
|
||||
print_lst (file, l, indent + 2);
|
||||
|
||||
fprintf (file, ")");
|
||||
}
|
||||
else
|
||||
fprintf (file, "%d stmt_%d", lst_dewey_number (lst), pbb_index (LST_PBB (lst)));
|
||||
}
|
||||
|
||||
/* Print LST to STDERR. */
|
||||
|
||||
DEBUG_FUNCTION void
|
||||
debug_lst (lst_p lst)
|
||||
{
|
||||
print_lst (stderr, lst, 0);
|
||||
}
|
||||
|
||||
/* Pretty print to FILE the loop statement tree LST in DOT format. */
|
||||
|
||||
static void
|
||||
dot_lst_1 (FILE *file, lst_p lst)
|
||||
{
|
||||
if (!lst)
|
||||
return;
|
||||
|
||||
if (LST_LOOP_P (lst))
|
||||
{
|
||||
int i;
|
||||
lst_p l;
|
||||
|
||||
if (!LST_LOOP_FATHER (lst))
|
||||
fprintf (file, "L -> L_%d_%d\n",
|
||||
lst_depth (lst),
|
||||
lst_dewey_number (lst));
|
||||
else
|
||||
fprintf (file, "L_%d_%d -> L_%d_%d\n",
|
||||
lst_depth (LST_LOOP_FATHER (lst)),
|
||||
lst_dewey_number (LST_LOOP_FATHER (lst)),
|
||||
lst_depth (lst),
|
||||
lst_dewey_number (lst));
|
||||
|
||||
FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l)
|
||||
dot_lst_1 (file, l);
|
||||
}
|
||||
|
||||
else
|
||||
fprintf (file, "L_%d_%d -> S_%d\n",
|
||||
lst_depth (LST_LOOP_FATHER (lst)),
|
||||
lst_dewey_number (LST_LOOP_FATHER (lst)),
|
||||
pbb_index (LST_PBB (lst)));
|
||||
|
||||
}
|
||||
|
||||
/* Display the LST using dotty. */
|
||||
|
||||
DEBUG_FUNCTION void
|
||||
dot_lst (lst_p lst)
|
||||
{
|
||||
/* When debugging, enable the following code. This cannot be used
|
||||
in production compilers because it calls "system". */
|
||||
#if 0
|
||||
FILE *stream = fopen ("/tmp/lst.dot", "w");
|
||||
gcc_assert (stream);
|
||||
|
||||
fputs ("digraph all {\n", stream);
|
||||
dot_lst_1 (stream, lst);
|
||||
fputs ("}\n\n", stream);
|
||||
fclose (stream);
|
||||
|
||||
system ("dotty /tmp/lst.dot &");
|
||||
#else
|
||||
fputs ("digraph all {\n", stderr);
|
||||
dot_lst_1 (stderr, lst);
|
||||
fputs ("}\n\n", stderr);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Reverse the loop around PBB at level DEPTH. */
|
||||
|
||||
isl_map *
|
||||
reverse_loop_at_level (poly_bb_p pbb, int depth)
|
||||
{
|
||||
unsigned i, depth_dim = psct_dynamic_dim (pbb, depth);
|
||||
isl_space *d = isl_map_get_space (pbb->transformed);
|
||||
isl_space *d1 = isl_space_range (d);
|
||||
unsigned n = isl_space_dim (d1, isl_dim_out);
|
||||
isl_space *d2 = isl_space_add_dims (d1, isl_dim_in, n);
|
||||
isl_map *x = isl_map_universe (isl_space_copy (d2));
|
||||
isl_constraint *c = isl_equality_alloc (isl_local_space_from_space (d2));
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (i != depth_dim)
|
||||
x = isl_map_equate (x, isl_dim_in, i, isl_dim_out, i);
|
||||
|
||||
c = isl_constraint_set_coefficient_si (c, isl_dim_in, depth_dim, 1);
|
||||
c = isl_constraint_set_coefficient_si (c, isl_dim_out, depth_dim, 1);
|
||||
x = isl_map_add_constraint (x, c);
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Reverse the loop at level DEPTH for all the PBBS. */
|
||||
|
||||
isl_union_map *
|
||||
reverse_loop_for_pbbs (scop_p scop, vec<poly_bb_p> pbbs, int depth)
|
||||
{
|
||||
poly_bb_p pbb;
|
||||
int i;
|
||||
isl_space *space = isl_space_from_domain (isl_set_get_space (scop->context));
|
||||
isl_union_map *res = isl_union_map_empty (space);
|
||||
|
||||
for (i = 0; pbbs.iterate (i, &pbb); i++)
|
||||
res = isl_union_map_add_map (res, reverse_loop_at_level (pbb, depth));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_isl */
|
||||
|
||||
|
|
1082
gcc/graphite-poly.h
1082
gcc/graphite-poly.h
File diff suppressed because it is too large
Load Diff
|
@ -443,18 +443,12 @@ isl_id_for_pbb (scop_p s, poly_bb_p pbb)
|
|||
/* Converts the STATIC_SCHEDULE of PBB into a scattering polyhedron.
|
||||
We generate SCATTERING_DIMENSIONS scattering dimensions.
|
||||
|
||||
CLooG 0.15.0 and previous versions require, that all
|
||||
scattering functions of one CloogProgram have the same number of
|
||||
scattering dimensions, therefore we allow to specify it. This
|
||||
should be removed in future versions of CLooG.
|
||||
|
||||
The scattering polyhedron consists of these dimensions: scattering,
|
||||
loop_iterators, parameters.
|
||||
|
||||
Example:
|
||||
|
||||
| scattering_dimensions = 5
|
||||
| used_scattering_dimensions = 3
|
||||
| nb_iterators = 1
|
||||
| scop_nb_params = 2
|
||||
|
|
||||
|
@ -475,15 +469,13 @@ isl_id_for_pbb (scop_p s, poly_bb_p pbb)
|
|||
|
||||
static void
|
||||
build_pbb_scattering_polyhedrons (isl_aff *static_sched,
|
||||
poly_bb_p pbb, int scattering_dimensions)
|
||||
poly_bb_p pbb)
|
||||
{
|
||||
int i;
|
||||
int nb_iterators = pbb_dim_iter_domain (pbb);
|
||||
int used_scattering_dimensions = nb_iterators * 2 + 1;
|
||||
isl_val *val;
|
||||
isl_space *dc, *dm;
|
||||
|
||||
gcc_assert (scattering_dimensions >= used_scattering_dimensions);
|
||||
int scattering_dimensions = isl_set_dim (pbb->domain, isl_dim_set) * 2 + 1;
|
||||
|
||||
dc = isl_set_get_space (pbb->domain);
|
||||
dm = isl_space_add_dims (isl_space_from_domain (dc),
|
||||
|
@ -577,7 +569,6 @@ build_scop_scattering (scop_p scop)
|
|||
{
|
||||
gimple_bb_p gbb = PBB_BLACK_BOX (pbb);
|
||||
int prefix;
|
||||
int nb_scat_dims = pbb_dim_iter_domain (pbb) * 2 + 1;
|
||||
|
||||
if (previous_gbb)
|
||||
prefix = nb_common_loops (SCOP_REGION (scop), previous_gbb, gbb);
|
||||
|
@ -588,7 +579,7 @@ build_scop_scattering (scop_p scop)
|
|||
|
||||
static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in,
|
||||
prefix, 1);
|
||||
build_pbb_scattering_polyhedrons (static_sched, pbb, nb_scat_dims);
|
||||
build_pbb_scattering_polyhedrons (static_sched, pbb);
|
||||
}
|
||||
|
||||
isl_aff_free (static_sched);
|
||||
|
@ -3103,7 +3094,7 @@ rewrite_commutative_reductions_out_of_ssa (scop_p scop)
|
|||
}
|
||||
|
||||
/* Can all ivs be represented by a signed integer?
|
||||
As CLooG might generate negative values in its expressions, signed loop ivs
|
||||
As ISL might generate negative values in its expressions, signed loop ivs
|
||||
are required in the backend. */
|
||||
|
||||
static bool
|
||||
|
@ -3149,9 +3140,7 @@ build_poly_scop (scop_p scop)
|
|||
|
||||
build_scop_bbs (scop);
|
||||
|
||||
/* FIXME: This restriction is needed to avoid a problem in CLooG.
|
||||
Once CLooG is fixed, remove this guard. Anyways, it makes no
|
||||
sense to optimize a scop containing only PBBs that do not belong
|
||||
/* Do not optimize a scop containing only PBBs that do not belong
|
||||
to any loops. */
|
||||
if (nb_pbbs_in_loops (scop) == 0)
|
||||
return;
|
||||
|
@ -3182,7 +3171,6 @@ build_poly_scop (scop_p scop)
|
|||
rewrite_cross_bb_scalar_deps_out_of_ssa (scop);
|
||||
|
||||
build_scop_drs (scop);
|
||||
scop_to_lst (scop);
|
||||
build_scop_scattering (scop);
|
||||
|
||||
/* This SCoP has been translated to the polyhedral
|
||||
|
|
|
@ -25,12 +25,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
An early description of this pass can be found in the GCC Summit'06
|
||||
paper "GRAPHITE: Polyhedral Analyses and Optimizations for GCC".
|
||||
The wiki page http://gcc.gnu.org/wiki/Graphite contains pointers to
|
||||
the related work.
|
||||
|
||||
One important document to read is CLooG's internal manual:
|
||||
http://repo.or.cz/w/cloog-ppl.git?a=blob_plain;f=doc/cloog.texi;hb=HEAD
|
||||
that describes the data structure of loops used in this file, and
|
||||
the functions that are used for transforming the code. */
|
||||
the related work. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
@ -286,6 +281,9 @@ graphite_transform_loops (void)
|
|||
scop->ctx = ctx;
|
||||
build_poly_scop (scop);
|
||||
|
||||
if (dump_file && dump_flags)
|
||||
print_scop (dump_file, scop, 3);
|
||||
|
||||
if (POLY_SCOP_P (scop)
|
||||
&& apply_poly_transforms (scop)
|
||||
&& graphite_regenerate_ast_isl (scop))
|
||||
|
@ -326,10 +324,7 @@ gate_graphite_transforms (void)
|
|||
{
|
||||
/* Enable -fgraphite pass if any one of the graphite optimization flags
|
||||
is turned on. */
|
||||
if (flag_loop_block
|
||||
|| flag_loop_interchange
|
||||
|| flag_loop_strip_mine
|
||||
|| flag_graphite_identity
|
||||
if (flag_graphite_identity
|
||||
|| flag_loop_parallelize_all
|
||||
|| flag_loop_optimize_isl)
|
||||
flag_graphite = 1;
|
||||
|
|
|
@ -1,3 +1,43 @@
|
|||
2015-08-27 Sebastian Pop <s.pop@samsung.com>
|
||||
|
||||
* gcc.dg/graphite/graphite.exp (interchange_files, block_files):
|
||||
Replaced by opt_files, compile with -floop-nest-optimize.
|
||||
* g++.dg/graphite/graphite.exp: Same.
|
||||
* gfortran.dg/graphite/graphite.exp: Same.
|
||||
* gcc.dg/graphite/block-0.c: Adjust pattern.
|
||||
* gcc.dg/graphite/block-1.c: Same.
|
||||
* gcc.dg/graphite/block-3.c: Same.
|
||||
* gcc.dg/graphite/block-4.c: Same.
|
||||
* gcc.dg/graphite/block-5.c: Same.
|
||||
* gcc.dg/graphite/block-6.c: Same.
|
||||
* gcc.dg/graphite/block-7.c: Same.
|
||||
* gcc.dg/graphite/block-8.c: Same.
|
||||
* gcc.dg/graphite/block-pr47654.c: Same.
|
||||
* gcc.dg/graphite/interchange-0.c: Same.
|
||||
* gcc.dg/graphite/interchange-1.c: Same.
|
||||
* gcc.dg/graphite/interchange-10.c: Same.
|
||||
* gcc.dg/graphite/interchange-11.c: Same.
|
||||
* gcc.dg/graphite/interchange-12.c: Same.
|
||||
* gcc.dg/graphite/interchange-13.c: Same.
|
||||
* gcc.dg/graphite/interchange-14.c: Same.
|
||||
* gcc.dg/graphite/interchange-15.c: Same.
|
||||
* gcc.dg/graphite/interchange-3.c: Same.
|
||||
* gcc.dg/graphite/interchange-4.c: Same.
|
||||
* gcc.dg/graphite/interchange-5.c: Same.
|
||||
* gcc.dg/graphite/interchange-6.c: Same.
|
||||
* gcc.dg/graphite/interchange-7.c: Same.
|
||||
* gcc.dg/graphite/interchange-8.c: Same.
|
||||
* gcc.dg/graphite/interchange-9.c: Same.
|
||||
* gcc.dg/graphite/interchange-mvt.c: Same.
|
||||
* gcc.dg/graphite/pr37485.c: Same.
|
||||
* gcc.dg/graphite/uns-block-1.c: Same.
|
||||
* gcc.dg/graphite/uns-interchange-12.c: Same.
|
||||
* gcc.dg/graphite/uns-interchange-14.c: Same.
|
||||
* gcc.dg/graphite/uns-interchange-15.c: Same.
|
||||
* gcc.dg/graphite/uns-interchange-9.c: Same.
|
||||
* gcc.dg/graphite/uns-interchange-mvt.c: Same.
|
||||
* gfortran.dg/graphite/interchange-3.f90: Same.
|
||||
|
||||
2015-08-27 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/67317
|
||||
|
|
|
@ -41,8 +41,8 @@ set wait_to_run_files [lsort [glob -nocomplain $srcdir/$subdir/*.C ] ]
|
|||
set scop_files [lsort [glob -nocomplain $srcdir/$subdir/scop-*.C ] ]
|
||||
set id_files [lsort [glob -nocomplain $srcdir/$subdir/id-*.C ] ]
|
||||
set run_id_files [lsort [glob -nocomplain $srcdir/$subdir/run-id-*.C ] ]
|
||||
set interchange_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.C ] ]
|
||||
set block_files [lsort [glob -nocomplain $srcdir/$subdir/block-*.C ] ]
|
||||
set opt_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.C \
|
||||
$srcdir/$subdir/block-*.C ] ]
|
||||
|
||||
# Tests to be compiled.
|
||||
set dg-do-what-default compile
|
||||
|
@ -52,16 +52,14 @@ g++-dg-runtest $id_files "" "-O2 -fgraphite-identity -ffast-math"
|
|||
# Tests to be run.
|
||||
set dg-do-what-default run
|
||||
g++-dg-runtest $run_id_files "" "-O2 -fgraphite-identity"
|
||||
g++-dg-runtest $interchange_files "" "-O2 -floop-interchange -fno-loop-block -fno-loop-strip-mine -ffast-math -fdump-tree-graphite-all"
|
||||
g++-dg-runtest $block_files "" "-O2 -floop-block -fno-loop-strip-mine -fno-loop-interchange -ffast-math -fdump-tree-graphite-all"
|
||||
g++-dg-runtest $opt_files "" "-O2 -floop-nest-optimize -ffast-math -fdump-tree-graphite-all"
|
||||
|
||||
# The default action for the rest of the files is 'compile'.
|
||||
set dg-do-what-default compile
|
||||
foreach f $scop_files {lremove wait_to_run_files $f}
|
||||
foreach f $id_files {lremove wait_to_run_files $f}
|
||||
foreach f $run_id_files {lremove wait_to_run_files $f}
|
||||
foreach f $interchange_files {lremove wait_to_run_files $f}
|
||||
foreach f $block_files {lremove wait_to_run_files $f}
|
||||
foreach f $opt_files {lremove wait_to_run_files $f}
|
||||
g++-dg-runtest $wait_to_run_files "" "-pedantic-errors"
|
||||
|
||||
# Clean up.
|
||||
|
|
|
@ -42,4 +42,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "will be loop blocked" "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "not tiled" 3 "graphite" } } */
|
||||
|
|
|
@ -45,4 +45,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be loop blocked" 3 "graphite" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 5 "graphite" } } */
|
||||
|
|
|
@ -17,7 +17,7 @@ foo (void)
|
|||
{
|
||||
int i, j, k;
|
||||
|
||||
/* These loops contain too few iterations to be blocked by 64. */
|
||||
/* These loops contain too few iterations to be blocked. */
|
||||
for (i = 0; i < 24; i++)
|
||||
for (j = 0; j < 24; j++)
|
||||
for (k = 0; k < 24; k++)
|
||||
|
@ -58,4 +58,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */
|
||||
|
|
|
@ -16,7 +16,7 @@ foo (void)
|
|||
{
|
||||
int i, j, k;
|
||||
|
||||
/* This should NOT be blocked: each loop iterates only 24 times. */
|
||||
/* This should NOT be blocked. */
|
||||
for (i = 0; i < 24; i++)
|
||||
for (j = 0; j < 24; j++)
|
||||
for (k = 0; k < 24; k++)
|
||||
|
@ -57,4 +57,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 7 "graphite" } } */
|
||||
|
|
|
@ -53,4 +53,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */
|
||||
|
|
|
@ -48,4 +48,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be loop blocked" 0 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */
|
||||
|
|
|
@ -54,4 +54,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 6 "graphite" } } */
|
||||
|
|
|
@ -55,4 +55,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 7 "graphite" } } */
|
||||
|
|
|
@ -21,4 +21,4 @@ main ()
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "will be loop blocked" "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 1 "graphite" } } */
|
||||
|
|
|
@ -41,10 +41,10 @@ set wait_to_run_files [lsort [glob -nocomplain $srcdir/$subdir/*.c ] ]
|
|||
set scop_files [lsort [glob -nocomplain $srcdir/$subdir/scop-*.c ] ]
|
||||
set id_files [lsort [glob -nocomplain $srcdir/$subdir/id-*.c ] ]
|
||||
set run_id_files [lsort [glob -nocomplain $srcdir/$subdir/run-id-*.c ] ]
|
||||
set interchange_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.c \
|
||||
$srcdir/$subdir/uns-interchange-*.c ] ]
|
||||
set block_files [lsort [glob -nocomplain $srcdir/$subdir/block-*.c \
|
||||
$srcdir/$subdir/uns-block-*.c ] ]
|
||||
set opt_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.c \
|
||||
$srcdir/$subdir/uns-interchange-*.c \
|
||||
$srcdir/$subdir/block-*.c \
|
||||
$srcdir/$subdir/uns-block-*.c ] ]
|
||||
set vect_files [lsort [glob -nocomplain $srcdir/$subdir/vect-*.c ] ]
|
||||
|
||||
# Tests to be compiled.
|
||||
|
@ -55,8 +55,7 @@ dg-runtest $id_files "" "-O2 -fgraphite-identity -ffast-math"
|
|||
# Tests to be run.
|
||||
set dg-do-what-default run
|
||||
dg-runtest $run_id_files "" "-O2 -fgraphite-identity"
|
||||
dg-runtest $interchange_files "" "-O2 -floop-interchange -fno-loop-block -fno-loop-strip-mine -ffast-math -fdump-tree-graphite-all"
|
||||
dg-runtest $block_files "" "-O2 -floop-block -fno-loop-strip-mine -fno-loop-interchange -ffast-math -fdump-tree-graphite-all"
|
||||
dg-runtest $opt_files "" "-O2 -ffast-math -floop-nest-optimize -fdump-tree-graphite-all"
|
||||
|
||||
# Vectorizer tests, to be run or compiled, depending on target capabilities.
|
||||
global DEFAULT_VECTCFLAGS
|
||||
|
@ -71,8 +70,7 @@ set dg-do-what-default compile
|
|||
foreach f $scop_files {lremove wait_to_run_files $f}
|
||||
foreach f $id_files {lremove wait_to_run_files $f}
|
||||
foreach f $run_id_files {lremove wait_to_run_files $f}
|
||||
foreach f $interchange_files {lremove wait_to_run_files $f}
|
||||
foreach f $block_files {lremove wait_to_run_files $f}
|
||||
foreach f $opt_files {lremove wait_to_run_files $f}
|
||||
foreach f $vect_files {lremove wait_to_run_files $f}
|
||||
dg-runtest $wait_to_run_files "" "-ansi -pedantic-errors"
|
||||
|
||||
|
|
|
@ -46,4 +46,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -49,4 +49,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -46,4 +46,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 2 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 4 "graphite" } } */
|
||||
|
|
|
@ -46,4 +46,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -53,4 +53,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 5 "graphite" } } */
|
||||
|
|
|
@ -50,4 +50,4 @@ main (void)
|
|||
}
|
||||
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -54,5 +54,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* PRE destroys the perfect nest and we can't cope with that yet. */
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 7 "graphite" } } */
|
||||
|
|
|
@ -48,6 +48,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* PRE destroys the perfect nest and we can't cope with that yet. */
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 4 "graphite" } } */
|
||||
|
|
|
@ -47,4 +47,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -46,4 +46,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -46,4 +46,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -47,4 +47,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -46,4 +46,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -82,4 +82,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 2 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 5 "graphite" } } */
|
||||
|
|
|
@ -44,4 +44,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */
|
||||
|
|
|
@ -58,6 +58,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* PRE destroys the perfect nest and we can't cope with that yet. */
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 7 "graphite" } } */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* { dg-options "-O2 -floop-block -fno-loop-strip-mine -fno-loop-interchange -ffast-math -fdump-tree-graphite-all" } */
|
||||
/* { dg-options "-O2 -floop-block -ffast-math -fdump-tree-graphite-all" } */
|
||||
|
||||
typedef unsigned char UChar;
|
||||
typedef int Int32;
|
||||
|
@ -30,4 +30,5 @@ void fallbackSort ( UInt32* fmap,
|
|||
}
|
||||
AssertH ( j < 256, 1005 );
|
||||
}
|
||||
/* { dg-final { scan-tree-dump-times "Loop blocked" 1 "graphite" { xfail *-*-* }} } */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 1 "graphite" } } */
|
||||
|
|
|
@ -45,4 +45,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be loop blocked" 3 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 4 "graphite" } } */
|
||||
|
|
|
@ -54,4 +54,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 4 "graphite" } } */
|
||||
|
|
|
@ -55,5 +55,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* PRE destroys the perfect nest and we can't cope with that yet. */
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 6 "graphite" } } */
|
||||
|
|
|
@ -49,6 +49,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* PRE destroys the perfect nest and we can't cope with that yet. */
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -45,4 +45,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */
|
||||
|
|
|
@ -59,6 +59,4 @@ main (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* PRE destroys the perfect nest and we can't cope with that yet. */
|
||||
/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */
|
||||
|
|
|
@ -38,9 +38,9 @@ set save-dg-do-what-default ${dg-do-what-default}
|
|||
dg-init
|
||||
|
||||
set wait_to_run_files [lsort [glob -nocomplain $srcdir/$subdir/*.\[fF\]{,90,95,03,08} ] ]
|
||||
set block_files [lsort [glob -nocomplain $srcdir/$subdir/block-*.\[fF\]{,90,95,03,08} ] ]
|
||||
set id_files [lsort [glob -nocomplain $srcdir/$subdir/id-*.\[fF\]{,90,95,03,08} ] ]
|
||||
set interchange_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.\[fF\]{,90,95,03,08} ] ]
|
||||
set opt_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.\[fF\]{,90,95,03,08} \
|
||||
$srcdir/$subdir/block-*.\[fF\]{,90,95,03,08} ] ]
|
||||
set scop_files [lsort [glob -nocomplain $srcdir/$subdir/scop-*.\[fF\]{,90,95,03,08} ] ]
|
||||
set run_id_files [lsort [glob -nocomplain $srcdir/$subdir/run-id-*.\[fF\]{,90,95,03,08} ] ]
|
||||
set vect_files [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[fF\]{,90,95,03,08} ] ]
|
||||
|
@ -49,8 +49,7 @@ set vect_files [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[fF\]{,90
|
|||
set dg-do-what-default compile
|
||||
gfortran-dg-runtest $scop_files "" "-O2 -fgraphite -fdump-tree-graphite-all"
|
||||
gfortran-dg-runtest $id_files "" "-O2 -fgraphite-identity -ffast-math"
|
||||
gfortran-dg-runtest $interchange_files "" "-O2 -floop-interchange -fno-loop-block -fno-loop-strip-mine -ffast-math -fdump-tree-graphite-all"
|
||||
gfortran-dg-runtest $block_files "" "-O2 -floop-block -fno-loop-strip-mine -fno-loop-interchange -ffast-math -fdump-tree-graphite-all"
|
||||
gfortran-dg-runtest $opt_files "" "-O2 -floop-nest-optimize -ffast-math -fdump-tree-graphite-all"
|
||||
|
||||
# Vectorizer tests, to be run or compiled, depending on target capabilities.
|
||||
if [check_vect_support_and_set_flags] {
|
||||
|
@ -63,9 +62,8 @@ gfortran-dg-runtest $run_id_files "" "-O2 -fgraphite-identity"
|
|||
|
||||
# The default action for the rest of the files is 'compile'.
|
||||
set dg-do-what-default compile
|
||||
foreach f $block_files {lremove wait_to_run_files $f}
|
||||
foreach f $id_files {lremove wait_to_run_files $f}
|
||||
foreach f $interchange_files {lremove wait_to_run_files $f}
|
||||
foreach f $opt_files {lremove wait_to_run_files $f}
|
||||
foreach f $scop_files {lremove wait_to_run_files $f}
|
||||
foreach f $run_id_files {lremove wait_to_run_files $f}
|
||||
foreach f $vect_files {lremove wait_to_run_files $f}
|
||||
|
|
|
@ -24,4 +24,4 @@ Program FOO
|
|||
|
||||
end Program FOO
|
||||
|
||||
! { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } }
|
||||
! { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } }
|
||||
|
|
Loading…
Reference in New Issue