Remove the lambda framework and make -ftree-loop-linear an alias of -floop-interchange.
2011-01-17 Sebastian Pop <sebastian.pop@amd.com> toplev/ * MAINTAINERS (linear loop transforms): Removed. toplev/gcc/ * Makefile.in (LAMBDA_H): Removed. (TREE_DATA_REF_H): Remove dependence on LAMBDA_H. (OBJS-common): Remove dependence on lambda-code.o, lambda-mat.o, lambda-trans.o, and tree-loop-linear.o. (lto-symtab.o): Remove dependence on LAMBDA_H. (tree-loop-linear.o): Remove rule. (lambda-mat.o): Same. (lambda-trans.o): Same. (lambda-code.o): Same. (tree-vect-loop.o): Add missing dependence on TREE_DATA_REF_H. (tree-vect-slp.o): Same. * hwint.h (gcd): Moved here. (least_common_multiple): Same. * lambda-code.c: Removed. * lambda-mat.c: Removed. * lambda-trans.c: Removed. * lambda.h: Removed. * tree-loop-linear.c: Removed. * lto-symtab.c: Do not include lambda.h. * omega.c (gcd): Removed. * passes.c (init_optimization_passes): Remove pass_linear_transform. * tree-data-ref.c (print_lambda_vector): Moved here. (lambda_vector_copy): Same. (lambda_matrix_copy): Same. (lambda_matrix_id): Same. (lambda_vector_first_nz): Same. (lambda_matrix_row_add): Same. (lambda_matrix_row_exchange): Same. (lambda_vector_mult_const): Same. (lambda_vector_negate): Same. (lambda_matrix_row_negate): Same. (lambda_vector_equal): Same. (lambda_matrix_right_hermite): Same. * tree-data-ref.h: Do not include lambda.h. (lambda_vector): Moved here. (lambda_matrix): Same. (dependence_level): Same. (lambda_transform_legal_p): Removed declaration. (lambda_collect_parameters): Same. (lambda_compute_access_matrices): Same. (lambda_vector_gcd): Same. (lambda_vector_new): Same. (lambda_vector_clear): Same. (lambda_vector_lexico_pos): Same. (lambda_vector_zerop): Same. (lambda_matrix_new): Same. * tree-flow.h (least_common_multiple): Removed declaration. * tree-parloops.c (lambda_trans_matrix): Moved here. (LTM_MATRIX): Same. (LTM_ROWSIZE): Same. (LTM_COLSIZE): Same. (LTM_DENOMINATOR): Same. (lambda_trans_matrix_new): Same. (lambda_matrix_vector_mult): Same. (lambda_transform_legal_p): Same. * tree-pass.h (pass_linear_transform): Removed declaration. * tree-ssa-loop.c (tree_linear_transform): Removed. (gate_tree_linear_transform): Removed. (pass_linear_transform): Removed. (gate_graphite_transforms): Make flag_tree_loop_linear an alias of flag_loop_interchange. toplev/gcc/testsuite/ * gfortran.dg/graphite/interchange-4.f: New. * gfortran.dg/graphite/interchange-5.f: New. * gcc.dg/tree-ssa/ltrans-1.c: Removed. * gcc.dg/tree-ssa/ltrans-2.c: Removed. * gcc.dg/tree-ssa/ltrans-3.c: Removed. * gcc.dg/tree-ssa/ltrans-4.c: Removed. * gcc.dg/tree-ssa/ltrans-5.c: Removed. * gcc.dg/tree-ssa/ltrans-6.c: Removed. * gcc.dg/tree-ssa/ltrans-8.c: Removed. * gfortran.dg/ltrans-7.f90: Removed. * gcc.dg/tree-ssa/data-dep-1.c: Removed. * gcc.dg/pr18792.c: -> gcc.dg/graphite/pr18792.c * gcc.dg/pr19910.c: -> gcc.dg/graphite/pr19910.c * gcc.dg/tree-ssa/20041110-1.c: -> gcc.dg/graphite/pr20041110-1.c * gcc.dg/tree-ssa/pr20256.c: -> gcc.dg/graphite/pr20256.c * gcc.dg/pr23625.c: -> gcc.dg/graphite/pr23625.c * gcc.dg/tree-ssa/pr23820.c: -> gcc.dg/graphite/pr23820.c * gcc.dg/tree-ssa/pr24309.c: -> gcc.dg/graphite/pr24309.c * gcc.dg/tree-ssa/pr26435.c: -> gcc.dg/graphite/pr26435.c * gcc.dg/pr29330.c: -> gcc.dg/graphite/pr29330.c * gcc.dg/pr29581-1.c: -> gcc.dg/graphite/pr29581-1.c * gcc.dg/pr29581-2.c: -> gcc.dg/graphite/pr29581-2.c * gcc.dg/pr29581-3.c: -> gcc.dg/graphite/pr29581-3.c * gcc.dg/pr29581-4.c: -> gcc.dg/graphite/pr29581-4.c * gcc.dg/tree-ssa/loop-27.c: -> gcc.dg/graphite/pr30565.c * gcc.dg/tree-ssa/pr31183.c: -> gcc.dg/graphite/pr31183.c * gcc.dg/tree-ssa/pr33576.c: -> gcc.dg/graphite/pr33576.c * gcc.dg/tree-ssa/pr33766.c: -> gcc.dg/graphite/pr33766.c * gcc.dg/pr34016.c: -> gcc.dg/graphite/pr34016.c * gcc.dg/tree-ssa/pr34017.c: -> gcc.dg/graphite/pr34017.c * gcc.dg/tree-ssa/pr34123.c: -> gcc.dg/graphite/pr34123.c * gcc.dg/tree-ssa/pr36287.c: -> gcc.dg/graphite/pr36287.c * gcc.dg/tree-ssa/pr37686.c: -> gcc.dg/graphite/pr37686.c * gcc.dg/pr42917.c: -> gcc.dg/graphite/pr42917.c * gfortran.dg/loop_nest_1.f90: -> gfortran.dg/graphite/pr29290.f90 * gfortran.dg/pr29581.f90: -> gfortran.dg/graphite/pr29581.f90 * gfortran.dg/pr36286.f90: -> gfortran.dg/graphite/pr36286.f90 * gfortran.dg/pr36922.f: -> gfortran.dg/graphite/pr36922.f * gfortran.dg/pr39516.f: -> gfortran.dg/graphite/pr39516.f From-SVN: r169251
This commit is contained in:
parent
6bdfdb96ee
commit
b305e3dab4
@ -1,3 +1,7 @@
|
||||
2011-01-25 Sebastian Pop <sebastian.pop@amd.com>
|
||||
|
||||
* MAINTAINERS (linear loop transforms): Removed.
|
||||
|
||||
2011-01-25 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/cloog.m4 (CLOOG_REQUESTED): Use $2 if --without-cloog.
|
||||
|
@ -221,7 +221,6 @@ mudflap Frank Ch. Eigler fche@redhat.com
|
||||
tree browser/unparser Sebastian Pop sebastian.pop@amd.com
|
||||
scev, data dependence Daniel Berlin dberlin@dberlin.org
|
||||
scev, data dependence Sebastian Pop sebastian.pop@amd.com
|
||||
linear loop transforms Daniel Berlin dberlin@dberlin.org
|
||||
profile feedback Jan Hubicka jh@suse.cz
|
||||
type-safe vectors Nathan Sidwell nathan@codesourcery.com
|
||||
alias analysis Daniel Berlin dberlin@dberlin.org
|
||||
|
@ -1,3 +1,67 @@
|
||||
2011-01-25 Sebastian Pop <sebastian.pop@amd.com>
|
||||
|
||||
* Makefile.in (LAMBDA_H): Removed.
|
||||
(TREE_DATA_REF_H): Remove dependence on LAMBDA_H.
|
||||
(OBJS-common): Remove dependence on lambda-code.o, lambda-mat.o,
|
||||
lambda-trans.o, and tree-loop-linear.o.
|
||||
(lto-symtab.o): Remove dependence on LAMBDA_H.
|
||||
(tree-loop-linear.o): Remove rule.
|
||||
(lambda-mat.o): Same.
|
||||
(lambda-trans.o): Same.
|
||||
(lambda-code.o): Same.
|
||||
(tree-vect-loop.o): Add missing dependence on TREE_DATA_REF_H.
|
||||
(tree-vect-slp.o): Same.
|
||||
* hwint.h (gcd): Moved here.
|
||||
(least_common_multiple): Same.
|
||||
* lambda-code.c: Removed.
|
||||
* lambda-mat.c: Removed.
|
||||
* lambda-trans.c: Removed.
|
||||
* lambda.h: Removed.
|
||||
* tree-loop-linear.c: Removed.
|
||||
* lto-symtab.c: Do not include lambda.h.
|
||||
* omega.c (gcd): Removed.
|
||||
* passes.c (init_optimization_passes): Remove pass_linear_transform.
|
||||
* tree-data-ref.c (print_lambda_vector): Moved here.
|
||||
(lambda_vector_copy): Same.
|
||||
(lambda_matrix_copy): Same.
|
||||
(lambda_matrix_id): Same.
|
||||
(lambda_vector_first_nz): Same.
|
||||
(lambda_matrix_row_add): Same.
|
||||
(lambda_matrix_row_exchange): Same.
|
||||
(lambda_vector_mult_const): Same.
|
||||
(lambda_vector_negate): Same.
|
||||
(lambda_matrix_row_negate): Same.
|
||||
(lambda_vector_equal): Same.
|
||||
(lambda_matrix_right_hermite): Same.
|
||||
* tree-data-ref.h: Do not include lambda.h.
|
||||
(lambda_vector): Moved here.
|
||||
(lambda_matrix): Same.
|
||||
(dependence_level): Same.
|
||||
(lambda_transform_legal_p): Removed declaration.
|
||||
(lambda_collect_parameters): Same.
|
||||
(lambda_compute_access_matrices): Same.
|
||||
(lambda_vector_gcd): Same.
|
||||
(lambda_vector_new): Same.
|
||||
(lambda_vector_clear): Same.
|
||||
(lambda_vector_lexico_pos): Same.
|
||||
(lambda_vector_zerop): Same.
|
||||
(lambda_matrix_new): Same.
|
||||
* tree-flow.h (least_common_multiple): Removed declaration.
|
||||
* tree-parloops.c (lambda_trans_matrix): Moved here.
|
||||
(LTM_MATRIX): Same.
|
||||
(LTM_ROWSIZE): Same.
|
||||
(LTM_COLSIZE): Same.
|
||||
(LTM_DENOMINATOR): Same.
|
||||
(lambda_trans_matrix_new): Same.
|
||||
(lambda_matrix_vector_mult): Same.
|
||||
(lambda_transform_legal_p): Same.
|
||||
* tree-pass.h (pass_linear_transform): Removed declaration.
|
||||
* tree-ssa-loop.c (tree_linear_transform): Removed.
|
||||
(gate_tree_linear_transform): Removed.
|
||||
(pass_linear_transform): Removed.
|
||||
(gate_graphite_transforms): Make flag_tree_loop_linear an alias of
|
||||
flag_loop_interchange.
|
||||
|
||||
2011-01-25 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/47265
|
||||
|
@ -966,8 +966,7 @@ DIAGNOSTIC_H = diagnostic.h $(DIAGNOSTIC_CORE_H) $(PRETTY_PRINT_H)
|
||||
C_PRETTY_PRINT_H = c-family/c-pretty-print.h $(PRETTY_PRINT_H) \
|
||||
$(C_COMMON_H) $(TREE_H)
|
||||
SCEV_H = tree-scalar-evolution.h $(GGC_H) tree-chrec.h $(PARAMS_H)
|
||||
LAMBDA_H = lambda.h $(TREE_H) $(VEC_H) $(GGC_H)
|
||||
TREE_DATA_REF_H = tree-data-ref.h $(LAMBDA_H) omega.h graphds.h $(SCEV_H)
|
||||
TREE_DATA_REF_H = tree-data-ref.h omega.h graphds.h $(SCEV_H)
|
||||
TREE_INLINE_H = tree-inline.h vecir.h
|
||||
REAL_H = real.h $(MACHMODE_H)
|
||||
IRA_INT_H = ira.h ira-int.h $(CFGLOOP_H) alloc-pool.h
|
||||
@ -1279,9 +1278,6 @@ OBJS-common = \
|
||||
ira-emit.o \
|
||||
ira-lives.o \
|
||||
jump.o \
|
||||
lambda-code.o \
|
||||
lambda-mat.o \
|
||||
lambda-trans.o \
|
||||
langhooks.o \
|
||||
lcm.o \
|
||||
lists.o \
|
||||
@ -1379,7 +1375,6 @@ OBJS-common = \
|
||||
tree-into-ssa.o \
|
||||
tree-iterator.o \
|
||||
tree-loop-distribution.o \
|
||||
tree-loop-linear.o \
|
||||
tree-nested.o \
|
||||
tree-nrv.o \
|
||||
tree-object-size.o \
|
||||
@ -2331,7 +2326,7 @@ lto-section-out.o : lto-section-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(EXCEPT_H) pointer-set.h \
|
||||
$(BITMAP_H) langhooks.h $(LTO_STREAMER_H) lto-compress.h
|
||||
lto-symtab.o: lto-symtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(TREE_H) $(GIMPLE_H) $(GGC_H) $(LAMBDA_H) $(HASHTAB_H) \
|
||||
$(TREE_H) $(GIMPLE_H) $(GGC_H) $(HASHTAB_H) \
|
||||
$(LTO_STREAMER_H) $(LINKER_PLUGIN_API_H) gt-lto-symtab.h
|
||||
lto-opts.o: lto-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
|
||||
$(HASHTAB_H) $(GGC_H) $(BITMAP_H) $(FLAGS_H) $(OPTS_H) $(OPTIONS_H) \
|
||||
@ -2711,7 +2706,7 @@ tree-vect-loop.o: tree-vect-loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(TM_H) $(GGC_H) $(TREE_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) \
|
||||
$(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) $(EXPR_H) $(RECOG_H) $(OPTABS_H) \
|
||||
$(DIAGNOSTIC_CORE_H) $(SCEV_H) $(TREE_VECTORIZER_H) tree-pretty-print.h \
|
||||
gimple-pretty-print.h $(TARGET_H)
|
||||
gimple-pretty-print.h $(TARGET_H) $(TREE_DATA_REF_H)
|
||||
tree-vect-loop-manip.o: tree-vect-loop-manip.c $(CONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) \
|
||||
$(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) $(EXPR_H) $(DIAGNOSTIC_CORE_H) \
|
||||
@ -2726,7 +2721,7 @@ tree-vect-slp.o: tree-vect-slp.c $(CONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
|
||||
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \
|
||||
$(EXPR_H) $(RECOG_H) $(OPTABS_H) $(TREE_VECTORIZER_H) tree-pretty-print.h \
|
||||
gimple-pretty-print.h
|
||||
gimple-pretty-print.h $(TREE_DATA_REF_H)
|
||||
tree-vect-stmts.o: tree-vect-stmts.c $(CONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
|
||||
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \
|
||||
@ -2742,8 +2737,6 @@ tree-vectorizer.o: tree-vectorizer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(TM_H) $(GGC_H) $(TREE_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) \
|
||||
$(CFGLOOP_H) $(TREE_PASS_H) $(TREE_VECTORIZER_H) $(TIMEVAR_H) \
|
||||
tree-pretty-print.h
|
||||
tree-loop-linear.o: tree-loop-linear.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(TREE_FLOW_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) $(TREE_PASS_H) $(LAMBDA_H)
|
||||
tree-loop-distribution.o: tree-loop-distribution.c $(CONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h $(TREE_FLOW_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) $(TREE_PASS_H)
|
||||
tree-parloops.o: tree-parloops.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
@ -3462,12 +3455,6 @@ ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h $(EXCEPT_H) $(TM_P_H) \
|
||||
$(OPTABS_H) $(CFGLOOP_H) hard-reg-set.h $(TIMEVAR_H) \
|
||||
$(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
|
||||
lambda-mat.o : lambda-mat.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_FLOW_H) \
|
||||
$(LAMBDA_H)
|
||||
lambda-trans.o : lambda-trans.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(TREE_FLOW_H) $(LAMBDA_H)
|
||||
lambda-code.o : lambda-code.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(TREE_FLOW_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) $(LAMBDA_H) $(TREE_PASS_H)
|
||||
params.o : params.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(PARAMS_H) \
|
||||
$(DIAGNOSTIC_CORE_H)
|
||||
pointer-set.o: pointer-set.c pointer-set.h $(CONFIG_H) $(SYSTEM_H)
|
||||
|
29
gcc/hwint.h
29
gcc/hwint.h
@ -228,4 +228,33 @@ exact_log2 (unsigned HOST_WIDE_INT x)
|
||||
|
||||
#endif /* GCC_VERSION >= 3004 */
|
||||
|
||||
/* Compute the greatest common divisor of two numbers using
|
||||
Euclid's algorithm. */
|
||||
|
||||
static inline int
|
||||
gcd (int a, int b)
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
x = abs (a);
|
||||
y = abs (b);
|
||||
|
||||
while (x > 0)
|
||||
{
|
||||
z = y % x;
|
||||
y = x;
|
||||
x = z;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/* Compute the least common multiple of two numbers A and B . */
|
||||
|
||||
static inline int
|
||||
least_common_multiple (int a, int b)
|
||||
{
|
||||
return (abs (a) * abs (b) / gcd (a, b));
|
||||
}
|
||||
|
||||
#endif /* ! GCC_HWINT_H */
|
||||
|
2855
gcc/lambda-code.c
2855
gcc/lambda-code.c
File diff suppressed because it is too large
Load Diff
608
gcc/lambda-mat.c
608
gcc/lambda-mat.c
@ -1,608 +0,0 @@
|
||||
/* Integer matrix math routines
|
||||
Copyright (C) 2003, 2004, 2005, 2007, 2008, 2010
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Daniel Berlin <dberlin@dberlin.org>.
|
||||
|
||||
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"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tree-flow.h"
|
||||
#include "lambda.h"
|
||||
|
||||
/* Allocate a matrix of M rows x N cols. */
|
||||
|
||||
lambda_matrix
|
||||
lambda_matrix_new (int m, int n, struct obstack * lambda_obstack)
|
||||
{
|
||||
lambda_matrix mat;
|
||||
int i;
|
||||
|
||||
mat = (lambda_matrix) obstack_alloc (lambda_obstack,
|
||||
sizeof (lambda_vector *) * m);
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
mat[i] = lambda_vector_new (n);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
/* Copy the elements of M x N matrix MAT1 to MAT2. */
|
||||
|
||||
void
|
||||
lambda_matrix_copy (lambda_matrix mat1, lambda_matrix mat2,
|
||||
int m, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
lambda_vector_copy (mat1[i], mat2[i], n);
|
||||
}
|
||||
|
||||
/* Store the N x N identity matrix in MAT. */
|
||||
|
||||
void
|
||||
lambda_matrix_id (lambda_matrix mat, int size)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
for (j = 0; j < size; j++)
|
||||
mat[i][j] = (i == j) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Return true if MAT is the identity matrix of SIZE */
|
||||
|
||||
bool
|
||||
lambda_matrix_id_p (lambda_matrix mat, int size)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < size; i++)
|
||||
for (j = 0; j < size; j++)
|
||||
{
|
||||
if (i == j)
|
||||
{
|
||||
if (mat[i][j] != 1)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mat[i][j] != 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Negate the elements of the M x N matrix MAT1 and store it in MAT2. */
|
||||
|
||||
void
|
||||
lambda_matrix_negate (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
lambda_vector_negate (mat1[i], mat2[i], n);
|
||||
}
|
||||
|
||||
/* Take the transpose of matrix MAT1 and store it in MAT2.
|
||||
MAT1 is an M x N matrix, so MAT2 must be N x M. */
|
||||
|
||||
void
|
||||
lambda_matrix_transpose (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
for (j = 0; j < m; j++)
|
||||
mat2[i][j] = mat1[j][i];
|
||||
}
|
||||
|
||||
|
||||
/* Add two M x N matrices together: MAT3 = MAT1+MAT2. */
|
||||
|
||||
void
|
||||
lambda_matrix_add (lambda_matrix mat1, lambda_matrix mat2,
|
||||
lambda_matrix mat3, int m, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
lambda_vector_add (mat1[i], mat2[i], mat3[i], n);
|
||||
}
|
||||
|
||||
/* MAT3 = CONST1 * MAT1 + CONST2 * MAT2. All matrices are M x N. */
|
||||
|
||||
void
|
||||
lambda_matrix_add_mc (lambda_matrix mat1, int const1,
|
||||
lambda_matrix mat2, int const2,
|
||||
lambda_matrix mat3, int m, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
lambda_vector_add_mc (mat1[i], const1, mat2[i], const2, mat3[i], n);
|
||||
}
|
||||
|
||||
/* Multiply two matrices: MAT3 = MAT1 * MAT2.
|
||||
MAT1 is an M x R matrix, and MAT2 is R x N. The resulting MAT2
|
||||
must therefore be M x N. */
|
||||
|
||||
void
|
||||
lambda_matrix_mult (lambda_matrix mat1, lambda_matrix mat2,
|
||||
lambda_matrix mat3, int m, int r, int n)
|
||||
{
|
||||
|
||||
int i, j, k;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
{
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
mat3[i][j] = 0;
|
||||
for (k = 0; k < r; k++)
|
||||
mat3[i][j] += mat1[i][k] * mat2[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete rows r1 to r2 (not including r2). */
|
||||
|
||||
void
|
||||
lambda_matrix_delete_rows (lambda_matrix mat, int rows, int from, int to)
|
||||
{
|
||||
int i;
|
||||
int dist;
|
||||
dist = to - from;
|
||||
|
||||
for (i = to; i < rows; i++)
|
||||
mat[i - dist] = mat[i];
|
||||
|
||||
for (i = rows - dist; i < rows; i++)
|
||||
mat[i] = NULL;
|
||||
}
|
||||
|
||||
/* Swap rows R1 and R2 in matrix MAT. */
|
||||
|
||||
void
|
||||
lambda_matrix_row_exchange (lambda_matrix mat, int r1, int r2)
|
||||
{
|
||||
lambda_vector row;
|
||||
|
||||
row = mat[r1];
|
||||
mat[r1] = mat[r2];
|
||||
mat[r2] = row;
|
||||
}
|
||||
|
||||
/* Add a multiple of row R1 of matrix MAT with N columns to row R2:
|
||||
R2 = R2 + CONST1 * R1. */
|
||||
|
||||
void
|
||||
lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2, int const1)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (const1 == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
mat[r2][i] += const1 * mat[r1][i];
|
||||
}
|
||||
|
||||
/* Negate row R1 of matrix MAT which has N columns. */
|
||||
|
||||
void
|
||||
lambda_matrix_row_negate (lambda_matrix mat, int n, int r1)
|
||||
{
|
||||
lambda_vector_negate (mat[r1], mat[r1], n);
|
||||
}
|
||||
|
||||
/* Multiply row R1 of matrix MAT with N columns by CONST1. */
|
||||
|
||||
void
|
||||
lambda_matrix_row_mc (lambda_matrix mat, int n, int r1, int const1)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
mat[r1][i] *= const1;
|
||||
}
|
||||
|
||||
/* Exchange COL1 and COL2 in matrix MAT. M is the number of rows. */
|
||||
|
||||
void
|
||||
lambda_matrix_col_exchange (lambda_matrix mat, int m, int col1, int col2)
|
||||
{
|
||||
int i;
|
||||
int tmp;
|
||||
for (i = 0; i < m; i++)
|
||||
{
|
||||
tmp = mat[i][col1];
|
||||
mat[i][col1] = mat[i][col2];
|
||||
mat[i][col2] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a multiple of column C1 of matrix MAT with M rows to column C2:
|
||||
C2 = C2 + CONST1 * C1. */
|
||||
|
||||
void
|
||||
lambda_matrix_col_add (lambda_matrix mat, int m, int c1, int c2, int const1)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (const1 == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
mat[i][c2] += const1 * mat[i][c1];
|
||||
}
|
||||
|
||||
/* Negate column C1 of matrix MAT which has M rows. */
|
||||
|
||||
void
|
||||
lambda_matrix_col_negate (lambda_matrix mat, int m, int c1)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
mat[i][c1] *= -1;
|
||||
}
|
||||
|
||||
/* Multiply column C1 of matrix MAT with M rows by CONST1. */
|
||||
|
||||
void
|
||||
lambda_matrix_col_mc (lambda_matrix mat, int m, int c1, int const1)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
mat[i][c1] *= const1;
|
||||
}
|
||||
|
||||
/* Compute the inverse of the N x N matrix MAT and store it in INV.
|
||||
|
||||
We don't _really_ compute the inverse of MAT. Instead we compute
|
||||
det(MAT)*inv(MAT), and we return det(MAT) to the caller as the function
|
||||
result. This is necessary to preserve accuracy, because we are dealing
|
||||
with integer matrices here.
|
||||
|
||||
The algorithm used here is a column based Gauss-Jordan elimination on MAT
|
||||
and the identity matrix in parallel. The inverse is the result of applying
|
||||
the same operations on the identity matrix that reduce MAT to the identity
|
||||
matrix.
|
||||
|
||||
When MAT is a 2 x 2 matrix, we don't go through the whole process, because
|
||||
it is easily inverted by inspection and it is a very common case. */
|
||||
|
||||
static int lambda_matrix_inverse_hard (lambda_matrix, lambda_matrix, int,
|
||||
struct obstack *);
|
||||
|
||||
int
|
||||
lambda_matrix_inverse (lambda_matrix mat, lambda_matrix inv, int n,
|
||||
struct obstack * lambda_obstack)
|
||||
{
|
||||
if (n == 2)
|
||||
{
|
||||
int a, b, c, d, det;
|
||||
a = mat[0][0];
|
||||
b = mat[1][0];
|
||||
c = mat[0][1];
|
||||
d = mat[1][1];
|
||||
inv[0][0] = d;
|
||||
inv[0][1] = -c;
|
||||
inv[1][0] = -b;
|
||||
inv[1][1] = a;
|
||||
det = (a * d - b * c);
|
||||
if (det < 0)
|
||||
{
|
||||
det *= -1;
|
||||
inv[0][0] *= -1;
|
||||
inv[1][0] *= -1;
|
||||
inv[0][1] *= -1;
|
||||
inv[1][1] *= -1;
|
||||
}
|
||||
return det;
|
||||
}
|
||||
else
|
||||
return lambda_matrix_inverse_hard (mat, inv, n, lambda_obstack);
|
||||
}
|
||||
|
||||
/* If MAT is not a special case, invert it the hard way. */
|
||||
|
||||
static int
|
||||
lambda_matrix_inverse_hard (lambda_matrix mat, lambda_matrix inv, int n,
|
||||
struct obstack * lambda_obstack)
|
||||
{
|
||||
lambda_vector row;
|
||||
lambda_matrix temp;
|
||||
int i, j;
|
||||
int determinant;
|
||||
|
||||
temp = lambda_matrix_new (n, n, lambda_obstack);
|
||||
lambda_matrix_copy (mat, temp, n, n);
|
||||
lambda_matrix_id (inv, n);
|
||||
|
||||
/* Reduce TEMP to a lower triangular form, applying the same operations on
|
||||
INV which starts as the identity matrix. N is the number of rows and
|
||||
columns. */
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
row = temp[j];
|
||||
|
||||
/* Make every element in the current row positive. */
|
||||
for (i = j; i < n; i++)
|
||||
if (row[i] < 0)
|
||||
{
|
||||
lambda_matrix_col_negate (temp, n, i);
|
||||
lambda_matrix_col_negate (inv, n, i);
|
||||
}
|
||||
|
||||
/* Sweep the upper triangle. Stop when only the diagonal element in the
|
||||
current row is nonzero. */
|
||||
while (lambda_vector_first_nz (row, n, j + 1) < n)
|
||||
{
|
||||
int min_col = lambda_vector_min_nz (row, n, j);
|
||||
lambda_matrix_col_exchange (temp, n, j, min_col);
|
||||
lambda_matrix_col_exchange (inv, n, j, min_col);
|
||||
|
||||
for (i = j + 1; i < n; i++)
|
||||
{
|
||||
int factor;
|
||||
|
||||
factor = -1 * row[i];
|
||||
if (row[j] != 1)
|
||||
factor /= row[j];
|
||||
|
||||
lambda_matrix_col_add (temp, n, j, i, factor);
|
||||
lambda_matrix_col_add (inv, n, j, i, factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduce TEMP from a lower triangular to the identity matrix. Also compute
|
||||
the determinant, which now is simply the product of the elements on the
|
||||
diagonal of TEMP. If one of these elements is 0, the matrix has 0 as an
|
||||
eigenvalue so it is singular and hence not invertible. */
|
||||
determinant = 1;
|
||||
for (j = n - 1; j >= 0; j--)
|
||||
{
|
||||
int diagonal;
|
||||
|
||||
row = temp[j];
|
||||
diagonal = row[j];
|
||||
|
||||
/* The matrix must not be singular. */
|
||||
gcc_assert (diagonal);
|
||||
|
||||
determinant = determinant * diagonal;
|
||||
|
||||
/* If the diagonal is not 1, then multiply the each row by the
|
||||
diagonal so that the middle number is now 1, rather than a
|
||||
rational. */
|
||||
if (diagonal != 1)
|
||||
{
|
||||
for (i = 0; i < j; i++)
|
||||
lambda_matrix_col_mc (inv, n, i, diagonal);
|
||||
for (i = j + 1; i < n; i++)
|
||||
lambda_matrix_col_mc (inv, n, i, diagonal);
|
||||
|
||||
row[j] = diagonal = 1;
|
||||
}
|
||||
|
||||
/* Sweep the lower triangle column wise. */
|
||||
for (i = j - 1; i >= 0; i--)
|
||||
{
|
||||
if (row[i])
|
||||
{
|
||||
int factor = -row[i];
|
||||
lambda_matrix_col_add (temp, n, j, i, factor);
|
||||
lambda_matrix_col_add (inv, n, j, i, factor);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return determinant;
|
||||
}
|
||||
|
||||
/* Decompose a N x N matrix MAT to a product of a lower triangular H
|
||||
and a unimodular U matrix such that MAT = H.U. N is the size of
|
||||
the rows of MAT. */
|
||||
|
||||
void
|
||||
lambda_matrix_hermite (lambda_matrix mat, int n,
|
||||
lambda_matrix H, lambda_matrix U)
|
||||
{
|
||||
lambda_vector row;
|
||||
int i, j, factor, minimum_col;
|
||||
|
||||
lambda_matrix_copy (mat, H, n, n);
|
||||
lambda_matrix_id (U, n);
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
row = H[j];
|
||||
|
||||
/* Make every element of H[j][j..n] positive. */
|
||||
for (i = j; i < n; i++)
|
||||
{
|
||||
if (row[i] < 0)
|
||||
{
|
||||
lambda_matrix_col_negate (H, n, i);
|
||||
lambda_vector_negate (U[i], U[i], n);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop when only the diagonal element is nonzero. */
|
||||
while (lambda_vector_first_nz (row, n, j + 1) < n)
|
||||
{
|
||||
minimum_col = lambda_vector_min_nz (row, n, j);
|
||||
lambda_matrix_col_exchange (H, n, j, minimum_col);
|
||||
lambda_matrix_row_exchange (U, j, minimum_col);
|
||||
|
||||
for (i = j + 1; i < n; i++)
|
||||
{
|
||||
factor = row[i] / row[j];
|
||||
lambda_matrix_col_add (H, n, j, i, -1 * factor);
|
||||
lambda_matrix_row_add (U, n, i, j, factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Given an M x N integer matrix A, this function determines an M x
|
||||
M unimodular matrix U, and an M x N echelon matrix S such that
|
||||
"U.A = S". This decomposition is also known as "right Hermite".
|
||||
|
||||
Ref: Algorithm 2.1 page 33 in "Loop Transformations for
|
||||
Restructuring Compilers" Utpal Banerjee. */
|
||||
|
||||
void
|
||||
lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
|
||||
lambda_matrix S, lambda_matrix U)
|
||||
{
|
||||
int i, j, i0 = 0;
|
||||
|
||||
lambda_matrix_copy (A, S, m, n);
|
||||
lambda_matrix_id (U, m);
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
if (lambda_vector_first_nz (S[j], m, i0) < m)
|
||||
{
|
||||
++i0;
|
||||
for (i = m - 1; i >= i0; i--)
|
||||
{
|
||||
while (S[i][j] != 0)
|
||||
{
|
||||
int sigma, factor, a, b;
|
||||
|
||||
a = S[i-1][j];
|
||||
b = S[i][j];
|
||||
sigma = (a * b < 0) ? -1: 1;
|
||||
a = abs (a);
|
||||
b = abs (b);
|
||||
factor = sigma * (a / b);
|
||||
|
||||
lambda_matrix_row_add (S, n, i, i-1, -factor);
|
||||
lambda_matrix_row_exchange (S, i, i-1);
|
||||
|
||||
lambda_matrix_row_add (U, m, i, i-1, -factor);
|
||||
lambda_matrix_row_exchange (U, i, i-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Given an M x N integer matrix A, this function determines an M x M
|
||||
unimodular matrix V, and an M x N echelon matrix S such that "A =
|
||||
V.S". This decomposition is also known as "left Hermite".
|
||||
|
||||
Ref: Algorithm 2.2 page 36 in "Loop Transformations for
|
||||
Restructuring Compilers" Utpal Banerjee. */
|
||||
|
||||
void
|
||||
lambda_matrix_left_hermite (lambda_matrix A, int m, int n,
|
||||
lambda_matrix S, lambda_matrix V)
|
||||
{
|
||||
int i, j, i0 = 0;
|
||||
|
||||
lambda_matrix_copy (A, S, m, n);
|
||||
lambda_matrix_id (V, m);
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
if (lambda_vector_first_nz (S[j], m, i0) < m)
|
||||
{
|
||||
++i0;
|
||||
for (i = m - 1; i >= i0; i--)
|
||||
{
|
||||
while (S[i][j] != 0)
|
||||
{
|
||||
int sigma, factor, a, b;
|
||||
|
||||
a = S[i-1][j];
|
||||
b = S[i][j];
|
||||
sigma = (a * b < 0) ? -1: 1;
|
||||
a = abs (a);
|
||||
b = abs (b);
|
||||
factor = sigma * (a / b);
|
||||
|
||||
lambda_matrix_row_add (S, n, i, i-1, -factor);
|
||||
lambda_matrix_row_exchange (S, i, i-1);
|
||||
|
||||
lambda_matrix_col_add (V, m, i-1, i, factor);
|
||||
lambda_matrix_col_exchange (V, m, i, i-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* When it exists, return the first nonzero row in MAT after row
|
||||
STARTROW. Otherwise return rowsize. */
|
||||
|
||||
int
|
||||
lambda_matrix_first_nz_vec (lambda_matrix mat, int rowsize, int colsize,
|
||||
int startrow)
|
||||
{
|
||||
int j;
|
||||
bool found = false;
|
||||
|
||||
for (j = startrow; (j < rowsize) && !found; j++)
|
||||
{
|
||||
if ((mat[j] != NULL)
|
||||
&& (lambda_vector_first_nz (mat[j], colsize, startrow) < colsize))
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (found)
|
||||
return j - 1;
|
||||
return rowsize;
|
||||
}
|
||||
|
||||
/* Multiply a vector VEC by a matrix MAT.
|
||||
MAT is an M*N matrix, and VEC is a vector with length N. The result
|
||||
is stored in DEST which must be a vector of length M. */
|
||||
|
||||
void
|
||||
lambda_matrix_vector_mult (lambda_matrix matrix, int m, int n,
|
||||
lambda_vector vec, lambda_vector dest)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
lambda_vector_clear (dest, m);
|
||||
for (i = 0; i < m; i++)
|
||||
for (j = 0; j < n; j++)
|
||||
dest[i] += matrix[i][j] * vec[j];
|
||||
}
|
||||
|
||||
/* Print out an M x N matrix MAT to OUTFILE. */
|
||||
|
||||
void
|
||||
print_lambda_matrix (FILE * outfile, lambda_matrix matrix, int m, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
print_lambda_vector (outfile, matrix[i], n);
|
||||
fprintf (outfile, "\n");
|
||||
}
|
||||
|
@ -1,80 +0,0 @@
|
||||
/* Lambda matrix transformations.
|
||||
Copyright (C) 2003, 2004, 2007, 2008, 2010 Free Software Foundation, Inc.
|
||||
Contributed by Daniel Berlin <dberlin@dberlin.org>.
|
||||
|
||||
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"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tree-flow.h"
|
||||
#include "lambda.h"
|
||||
|
||||
/* Allocate a new transformation matrix. */
|
||||
|
||||
lambda_trans_matrix
|
||||
lambda_trans_matrix_new (int colsize, int rowsize,
|
||||
struct obstack * lambda_obstack)
|
||||
{
|
||||
lambda_trans_matrix ret;
|
||||
|
||||
ret = (lambda_trans_matrix)
|
||||
obstack_alloc (lambda_obstack, sizeof (struct lambda_trans_matrix_s));
|
||||
LTM_MATRIX (ret) = lambda_matrix_new (rowsize, colsize, lambda_obstack);
|
||||
LTM_ROWSIZE (ret) = rowsize;
|
||||
LTM_COLSIZE (ret) = colsize;
|
||||
LTM_DENOMINATOR (ret) = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return true if MAT is an identity matrix. */
|
||||
|
||||
bool
|
||||
lambda_trans_matrix_id_p (lambda_trans_matrix mat)
|
||||
{
|
||||
if (LTM_ROWSIZE (mat) != LTM_COLSIZE (mat))
|
||||
return false;
|
||||
return lambda_matrix_id_p (LTM_MATRIX (mat), LTM_ROWSIZE (mat));
|
||||
}
|
||||
|
||||
|
||||
/* Compute the inverse of the transformation matrix MAT. */
|
||||
|
||||
lambda_trans_matrix
|
||||
lambda_trans_matrix_inverse (lambda_trans_matrix mat,
|
||||
struct obstack * lambda_obstack)
|
||||
{
|
||||
lambda_trans_matrix inverse;
|
||||
int determinant;
|
||||
|
||||
inverse = lambda_trans_matrix_new (LTM_ROWSIZE (mat), LTM_COLSIZE (mat),
|
||||
lambda_obstack);
|
||||
determinant = lambda_matrix_inverse (LTM_MATRIX (mat), LTM_MATRIX (inverse),
|
||||
LTM_ROWSIZE (mat), lambda_obstack);
|
||||
LTM_DENOMINATOR (inverse) = determinant;
|
||||
return inverse;
|
||||
}
|
||||
|
||||
|
||||
/* Print out a transformation matrix. */
|
||||
|
||||
void
|
||||
print_lambda_trans_matrix (FILE *outfile, lambda_trans_matrix mat)
|
||||
{
|
||||
print_lambda_matrix (outfile, LTM_MATRIX (mat), LTM_ROWSIZE (mat),
|
||||
LTM_COLSIZE (mat));
|
||||
}
|
524
gcc/lambda.h
524
gcc/lambda.h
@ -1,524 +0,0 @@
|
||||
/* Lambda matrix and vector interface.
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Daniel Berlin <dberlin@dberlin.org>
|
||||
|
||||
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/>. */
|
||||
|
||||
#ifndef LAMBDA_H
|
||||
#define LAMBDA_H
|
||||
|
||||
#include "vec.h"
|
||||
|
||||
/* An integer vector. A vector formally consists of an element of a vector
|
||||
space. A vector space is a set that is closed under vector addition
|
||||
and scalar multiplication. In this vector space, an element is a list of
|
||||
integers. */
|
||||
typedef int *lambda_vector;
|
||||
DEF_VEC_P(lambda_vector);
|
||||
DEF_VEC_ALLOC_P(lambda_vector,heap);
|
||||
DEF_VEC_ALLOC_P(lambda_vector,gc);
|
||||
|
||||
typedef VEC(lambda_vector, heap) *lambda_vector_vec_p;
|
||||
DEF_VEC_P (lambda_vector_vec_p);
|
||||
DEF_VEC_ALLOC_P (lambda_vector_vec_p, heap);
|
||||
|
||||
/* An integer matrix. A matrix consists of m vectors of length n (IE
|
||||
all vectors are the same length). */
|
||||
typedef lambda_vector *lambda_matrix;
|
||||
|
||||
DEF_VEC_P (lambda_matrix);
|
||||
DEF_VEC_ALLOC_P (lambda_matrix, heap);
|
||||
|
||||
/* A transformation matrix, which is a self-contained ROWSIZE x COLSIZE
|
||||
matrix. Rather than use floats, we simply keep a single DENOMINATOR that
|
||||
represents the denominator for every element in the matrix. */
|
||||
typedef struct lambda_trans_matrix_s
|
||||
{
|
||||
lambda_matrix matrix;
|
||||
int rowsize;
|
||||
int colsize;
|
||||
int denominator;
|
||||
} *lambda_trans_matrix;
|
||||
#define LTM_MATRIX(T) ((T)->matrix)
|
||||
#define LTM_ROWSIZE(T) ((T)->rowsize)
|
||||
#define LTM_COLSIZE(T) ((T)->colsize)
|
||||
#define LTM_DENOMINATOR(T) ((T)->denominator)
|
||||
|
||||
/* A vector representing a statement in the body of a loop.
|
||||
The COEFFICIENTS vector contains a coefficient for each induction variable
|
||||
in the loop nest containing the statement.
|
||||
The DENOMINATOR represents the denominator for each coefficient in the
|
||||
COEFFICIENT vector.
|
||||
|
||||
This structure is used during code generation in order to rewrite the old
|
||||
induction variable uses in a statement in terms of the newly created
|
||||
induction variables. */
|
||||
typedef struct lambda_body_vector_s
|
||||
{
|
||||
lambda_vector coefficients;
|
||||
int size;
|
||||
int denominator;
|
||||
} *lambda_body_vector;
|
||||
#define LBV_COEFFICIENTS(T) ((T)->coefficients)
|
||||
#define LBV_SIZE(T) ((T)->size)
|
||||
#define LBV_DENOMINATOR(T) ((T)->denominator)
|
||||
|
||||
/* Piecewise linear expression.
|
||||
This structure represents a linear expression with terms for the invariants
|
||||
and induction variables of a loop.
|
||||
COEFFICIENTS is a vector of coefficients for the induction variables, one
|
||||
per loop in the loop nest.
|
||||
CONSTANT is the constant portion of the linear expression
|
||||
INVARIANT_COEFFICIENTS is a vector of coefficients for the loop invariants,
|
||||
one per invariant.
|
||||
DENOMINATOR is the denominator for all of the coefficients and constants in
|
||||
the expression.
|
||||
The linear expressions can be linked together using the NEXT field, in
|
||||
order to represent MAX or MIN of a group of linear expressions. */
|
||||
typedef struct lambda_linear_expression_s
|
||||
{
|
||||
lambda_vector coefficients;
|
||||
int constant;
|
||||
lambda_vector invariant_coefficients;
|
||||
int denominator;
|
||||
struct lambda_linear_expression_s *next;
|
||||
} *lambda_linear_expression;
|
||||
|
||||
#define LLE_COEFFICIENTS(T) ((T)->coefficients)
|
||||
#define LLE_CONSTANT(T) ((T)->constant)
|
||||
#define LLE_INVARIANT_COEFFICIENTS(T) ((T)->invariant_coefficients)
|
||||
#define LLE_DENOMINATOR(T) ((T)->denominator)
|
||||
#define LLE_NEXT(T) ((T)->next)
|
||||
|
||||
struct obstack;
|
||||
|
||||
lambda_linear_expression lambda_linear_expression_new (int, int,
|
||||
struct obstack *);
|
||||
void print_lambda_linear_expression (FILE *, lambda_linear_expression, int,
|
||||
int, char);
|
||||
|
||||
/* Loop structure. Our loop structure consists of a constant representing the
|
||||
STEP of the loop, a set of linear expressions representing the LOWER_BOUND
|
||||
of the loop, a set of linear expressions representing the UPPER_BOUND of
|
||||
the loop, and a set of linear expressions representing the LINEAR_OFFSET of
|
||||
the loop. The linear offset is a set of linear expressions that are
|
||||
applied to *both* the lower bound, and the upper bound. */
|
||||
typedef struct lambda_loop_s
|
||||
{
|
||||
lambda_linear_expression lower_bound;
|
||||
lambda_linear_expression upper_bound;
|
||||
lambda_linear_expression linear_offset;
|
||||
int step;
|
||||
} *lambda_loop;
|
||||
|
||||
#define LL_LOWER_BOUND(T) ((T)->lower_bound)
|
||||
#define LL_UPPER_BOUND(T) ((T)->upper_bound)
|
||||
#define LL_LINEAR_OFFSET(T) ((T)->linear_offset)
|
||||
#define LL_STEP(T) ((T)->step)
|
||||
|
||||
/* Loop nest structure.
|
||||
The loop nest structure consists of a set of loop structures (defined
|
||||
above) in LOOPS, along with an integer representing the DEPTH of the loop,
|
||||
and an integer representing the number of INVARIANTS in the loop. Both of
|
||||
these integers are used to size the associated coefficient vectors in the
|
||||
linear expression structures. */
|
||||
typedef struct lambda_loopnest_s
|
||||
{
|
||||
lambda_loop *loops;
|
||||
int depth;
|
||||
int invariants;
|
||||
} *lambda_loopnest;
|
||||
|
||||
#define LN_LOOPS(T) ((T)->loops)
|
||||
#define LN_DEPTH(T) ((T)->depth)
|
||||
#define LN_INVARIANTS(T) ((T)->invariants)
|
||||
|
||||
lambda_loopnest lambda_loopnest_new (int, int, struct obstack *);
|
||||
lambda_loopnest lambda_loopnest_transform (lambda_loopnest,
|
||||
lambda_trans_matrix,
|
||||
struct obstack *);
|
||||
struct loop;
|
||||
bool perfect_nest_p (struct loop *);
|
||||
void print_lambda_loopnest (FILE *, lambda_loopnest, char);
|
||||
|
||||
void print_lambda_loop (FILE *, lambda_loop, int, int, char);
|
||||
|
||||
lambda_matrix lambda_matrix_new (int, int, struct obstack *);
|
||||
|
||||
void lambda_matrix_id (lambda_matrix, int);
|
||||
bool lambda_matrix_id_p (lambda_matrix, int);
|
||||
void lambda_matrix_copy (lambda_matrix, lambda_matrix, int, int);
|
||||
void lambda_matrix_negate (lambda_matrix, lambda_matrix, int, int);
|
||||
void lambda_matrix_transpose (lambda_matrix, lambda_matrix, int, int);
|
||||
void lambda_matrix_add (lambda_matrix, lambda_matrix, lambda_matrix, int,
|
||||
int);
|
||||
void lambda_matrix_add_mc (lambda_matrix, int, lambda_matrix, int,
|
||||
lambda_matrix, int, int);
|
||||
void lambda_matrix_mult (lambda_matrix, lambda_matrix, lambda_matrix,
|
||||
int, int, int);
|
||||
void lambda_matrix_delete_rows (lambda_matrix, int, int, int);
|
||||
void lambda_matrix_row_exchange (lambda_matrix, int, int);
|
||||
void lambda_matrix_row_add (lambda_matrix, int, int, int, int);
|
||||
void lambda_matrix_row_negate (lambda_matrix mat, int, int);
|
||||
void lambda_matrix_row_mc (lambda_matrix, int, int, int);
|
||||
void lambda_matrix_col_exchange (lambda_matrix, int, int, int);
|
||||
void lambda_matrix_col_add (lambda_matrix, int, int, int, int);
|
||||
void lambda_matrix_col_negate (lambda_matrix, int, int);
|
||||
void lambda_matrix_col_mc (lambda_matrix, int, int, int);
|
||||
int lambda_matrix_inverse (lambda_matrix, lambda_matrix, int, struct obstack *);
|
||||
void lambda_matrix_hermite (lambda_matrix, int, lambda_matrix, lambda_matrix);
|
||||
void lambda_matrix_left_hermite (lambda_matrix, int, int, lambda_matrix, lambda_matrix);
|
||||
void lambda_matrix_right_hermite (lambda_matrix, int, int, lambda_matrix, lambda_matrix);
|
||||
int lambda_matrix_first_nz_vec (lambda_matrix, int, int, int);
|
||||
void lambda_matrix_project_to_null (lambda_matrix, int, int, int,
|
||||
lambda_vector);
|
||||
void print_lambda_matrix (FILE *, lambda_matrix, int, int);
|
||||
|
||||
lambda_trans_matrix lambda_trans_matrix_new (int, int, struct obstack *);
|
||||
bool lambda_trans_matrix_nonsingular_p (lambda_trans_matrix);
|
||||
bool lambda_trans_matrix_fullrank_p (lambda_trans_matrix);
|
||||
int lambda_trans_matrix_rank (lambda_trans_matrix);
|
||||
lambda_trans_matrix lambda_trans_matrix_basis (lambda_trans_matrix);
|
||||
lambda_trans_matrix lambda_trans_matrix_padding (lambda_trans_matrix);
|
||||
lambda_trans_matrix lambda_trans_matrix_inverse (lambda_trans_matrix,
|
||||
struct obstack *);
|
||||
void print_lambda_trans_matrix (FILE *, lambda_trans_matrix);
|
||||
void lambda_matrix_vector_mult (lambda_matrix, int, int, lambda_vector,
|
||||
lambda_vector);
|
||||
bool lambda_trans_matrix_id_p (lambda_trans_matrix);
|
||||
|
||||
lambda_body_vector lambda_body_vector_new (int, struct obstack *);
|
||||
lambda_body_vector lambda_body_vector_compute_new (lambda_trans_matrix,
|
||||
lambda_body_vector,
|
||||
struct obstack *);
|
||||
void print_lambda_body_vector (FILE *, lambda_body_vector);
|
||||
lambda_loopnest gcc_loopnest_to_lambda_loopnest (struct loop *,
|
||||
VEC(tree,heap) **,
|
||||
VEC(tree,heap) **,
|
||||
struct obstack *);
|
||||
void lambda_loopnest_to_gcc_loopnest (struct loop *,
|
||||
VEC(tree,heap) *, VEC(tree,heap) *,
|
||||
VEC(gimple,heap) **,
|
||||
lambda_loopnest, lambda_trans_matrix,
|
||||
struct obstack *);
|
||||
void remove_iv (gimple);
|
||||
tree find_induction_var_from_exit_cond (struct loop *);
|
||||
|
||||
static inline void lambda_vector_negate (lambda_vector, lambda_vector, int);
|
||||
static inline void lambda_vector_mult_const (lambda_vector, lambda_vector, int, int);
|
||||
static inline void lambda_vector_add (lambda_vector, lambda_vector,
|
||||
lambda_vector, int);
|
||||
static inline void lambda_vector_add_mc (lambda_vector, int, lambda_vector, int,
|
||||
lambda_vector, int);
|
||||
static inline void lambda_vector_copy (lambda_vector, lambda_vector, int);
|
||||
static inline bool lambda_vector_zerop (lambda_vector, int);
|
||||
static inline void lambda_vector_clear (lambda_vector, int);
|
||||
static inline bool lambda_vector_equal (lambda_vector, lambda_vector, int);
|
||||
static inline int lambda_vector_min_nz (lambda_vector, int, int);
|
||||
static inline int lambda_vector_first_nz (lambda_vector, int, int);
|
||||
static inline void print_lambda_vector (FILE *, lambda_vector, int);
|
||||
|
||||
/* Allocate a new vector of given SIZE. */
|
||||
|
||||
static inline lambda_vector
|
||||
lambda_vector_new (int size)
|
||||
{
|
||||
return (lambda_vector) ggc_alloc_cleared_atomic (sizeof (int) * size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Multiply vector VEC1 of length SIZE by a constant CONST1,
|
||||
and store the result in VEC2. */
|
||||
|
||||
static inline void
|
||||
lambda_vector_mult_const (lambda_vector vec1, lambda_vector vec2,
|
||||
int size, int const1)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (const1 == 0)
|
||||
lambda_vector_clear (vec2, size);
|
||||
else
|
||||
for (i = 0; i < size; i++)
|
||||
vec2[i] = const1 * vec1[i];
|
||||
}
|
||||
|
||||
/* Negate vector VEC1 with length SIZE and store it in VEC2. */
|
||||
|
||||
static inline void
|
||||
lambda_vector_negate (lambda_vector vec1, lambda_vector vec2,
|
||||
int size)
|
||||
{
|
||||
lambda_vector_mult_const (vec1, vec2, size, -1);
|
||||
}
|
||||
|
||||
/* VEC3 = VEC1+VEC2, where all three the vectors are of length SIZE. */
|
||||
|
||||
static inline void
|
||||
lambda_vector_add (lambda_vector vec1, lambda_vector vec2,
|
||||
lambda_vector vec3, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
vec3[i] = vec1[i] + vec2[i];
|
||||
}
|
||||
|
||||
/* VEC3 = CONSTANT1*VEC1 + CONSTANT2*VEC2. All vectors have length SIZE. */
|
||||
|
||||
static inline void
|
||||
lambda_vector_add_mc (lambda_vector vec1, int const1,
|
||||
lambda_vector vec2, int const2,
|
||||
lambda_vector vec3, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
vec3[i] = const1 * vec1[i] + const2 * vec2[i];
|
||||
}
|
||||
|
||||
/* Copy the elements of vector VEC1 with length SIZE to VEC2. */
|
||||
|
||||
static inline void
|
||||
lambda_vector_copy (lambda_vector vec1, lambda_vector vec2,
|
||||
int size)
|
||||
{
|
||||
memcpy (vec2, vec1, size * sizeof (*vec1));
|
||||
}
|
||||
|
||||
/* Return true if vector VEC1 of length SIZE is the zero vector. */
|
||||
|
||||
static inline bool
|
||||
lambda_vector_zerop (lambda_vector vec1, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
if (vec1[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Clear out vector VEC1 of length SIZE. */
|
||||
|
||||
static inline void
|
||||
lambda_vector_clear (lambda_vector vec1, int size)
|
||||
{
|
||||
memset (vec1, 0, size * sizeof (*vec1));
|
||||
}
|
||||
|
||||
/* Return true if two vectors are equal. */
|
||||
|
||||
static inline bool
|
||||
lambda_vector_equal (lambda_vector vec1, lambda_vector vec2, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
if (vec1[i] != vec2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return the minimum nonzero element in vector VEC1 between START and N.
|
||||
We must have START <= N. */
|
||||
|
||||
static inline int
|
||||
lambda_vector_min_nz (lambda_vector vec1, int n, int start)
|
||||
{
|
||||
int j;
|
||||
int min = -1;
|
||||
|
||||
gcc_assert (start <= n);
|
||||
for (j = start; j < n; j++)
|
||||
{
|
||||
if (vec1[j])
|
||||
if (min < 0 || vec1[j] < vec1[min])
|
||||
min = j;
|
||||
}
|
||||
gcc_assert (min >= 0);
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
/* Return the first nonzero element of vector VEC1 between START and N.
|
||||
We must have START <= N. Returns N if VEC1 is the zero vector. */
|
||||
|
||||
static inline int
|
||||
lambda_vector_first_nz (lambda_vector vec1, int n, int start)
|
||||
{
|
||||
int j = start;
|
||||
while (j < n && vec1[j] == 0)
|
||||
j++;
|
||||
return j;
|
||||
}
|
||||
|
||||
|
||||
/* Multiply a vector by a matrix. */
|
||||
|
||||
static inline void
|
||||
lambda_vector_matrix_mult (lambda_vector vect, int m, lambda_matrix mat,
|
||||
int n, lambda_vector dest)
|
||||
{
|
||||
int i, j;
|
||||
lambda_vector_clear (dest, n);
|
||||
for (i = 0; i < n; i++)
|
||||
for (j = 0; j < m; j++)
|
||||
dest[i] += mat[j][i] * vect[j];
|
||||
}
|
||||
|
||||
/* Compare two vectors returning an integer less than, equal to, or
|
||||
greater than zero if the first argument is considered to be respectively
|
||||
less than, equal to, or greater than the second.
|
||||
We use the lexicographic order. */
|
||||
|
||||
static inline int
|
||||
lambda_vector_compare (lambda_vector vec1, int length1, lambda_vector vec2,
|
||||
int length2)
|
||||
{
|
||||
int min_length;
|
||||
int i;
|
||||
|
||||
if (length1 < length2)
|
||||
min_length = length1;
|
||||
else
|
||||
min_length = length2;
|
||||
|
||||
for (i = 0; i < min_length; i++)
|
||||
if (vec1[i] < vec2[i])
|
||||
return -1;
|
||||
else if (vec1[i] > vec2[i])
|
||||
return 1;
|
||||
else
|
||||
continue;
|
||||
|
||||
return length1 - length2;
|
||||
}
|
||||
|
||||
/* Print out a vector VEC of length N to OUTFILE. */
|
||||
|
||||
static inline void
|
||||
print_lambda_vector (FILE * outfile, lambda_vector vector, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
fprintf (outfile, "%3d ", vector[i]);
|
||||
fprintf (outfile, "\n");
|
||||
}
|
||||
|
||||
/* Compute the greatest common divisor of two numbers using
|
||||
Euclid's algorithm. */
|
||||
|
||||
static inline int
|
||||
gcd (int a, int b)
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
x = abs (a);
|
||||
y = abs (b);
|
||||
|
||||
while (x > 0)
|
||||
{
|
||||
z = y % x;
|
||||
y = x;
|
||||
x = z;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/* Compute the greatest common divisor of a VECTOR of SIZE numbers. */
|
||||
|
||||
static inline int
|
||||
lambda_vector_gcd (lambda_vector vector, int size)
|
||||
{
|
||||
int i;
|
||||
int gcd1 = 0;
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
gcd1 = vector[0];
|
||||
for (i = 1; i < size; i++)
|
||||
gcd1 = gcd (gcd1, vector[i]);
|
||||
}
|
||||
return gcd1;
|
||||
}
|
||||
|
||||
/* Returns true when the vector V is lexicographically positive, in
|
||||
other words, when the first nonzero element is positive. */
|
||||
|
||||
static inline bool
|
||||
lambda_vector_lexico_pos (lambda_vector v,
|
||||
unsigned n)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (v[i] == 0)
|
||||
continue;
|
||||
if (v[i] < 0)
|
||||
return false;
|
||||
if (v[i] > 0)
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Given a vector of induction variables IVS, and a vector of
|
||||
coefficients COEFS, build a tree that is a linear combination of
|
||||
the induction variables. */
|
||||
|
||||
static inline tree
|
||||
build_linear_expr (tree type, lambda_vector coefs, VEC (tree, heap) *ivs)
|
||||
{
|
||||
unsigned i;
|
||||
tree iv;
|
||||
tree expr = build_zero_cst (type);
|
||||
|
||||
for (i = 0; VEC_iterate (tree, ivs, i, iv); i++)
|
||||
{
|
||||
int k = coefs[i];
|
||||
|
||||
if (k == 1)
|
||||
expr = fold_build2 (PLUS_EXPR, type, expr, iv);
|
||||
|
||||
else if (k != 0)
|
||||
expr = fold_build2 (PLUS_EXPR, type, expr,
|
||||
fold_build2 (MULT_EXPR, type, iv,
|
||||
build_int_cst (type, k)));
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
/* Returns the dependence level for a vector DIST of size LENGTH.
|
||||
LEVEL = 0 means a lexicographic dependence, i.e. a dependence due
|
||||
to the sequence of statements, not carried by any loop. */
|
||||
|
||||
|
||||
static inline unsigned
|
||||
dependence_level (lambda_vector dist_vect, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
if (dist_vect[i] != 0)
|
||||
return i + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* LAMBDA_H */
|
@ -25,7 +25,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "tree.h"
|
||||
#include "gimple.h"
|
||||
#include "ggc.h"
|
||||
#include "lambda.h" /* gcd */
|
||||
#include "hashtab.h"
|
||||
#include "plugin-api.h"
|
||||
#include "lto-streamer.h"
|
||||
|
18
gcc/omega.c
18
gcc/omega.c
@ -181,24 +181,6 @@ omega_no_procedure (omega_pb pb ATTRIBUTE_UNUSED)
|
||||
|
||||
void (*omega_when_reduced) (omega_pb) = omega_no_procedure;
|
||||
|
||||
/* Compute the greatest common divisor of A and B. */
|
||||
|
||||
static inline int
|
||||
gcd (int b, int a)
|
||||
{
|
||||
if (b == 1)
|
||||
return 1;
|
||||
|
||||
while (b != 0)
|
||||
{
|
||||
int t = b;
|
||||
b = a % b;
|
||||
a = t;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Print to FILE from PB equation E with all its coefficients
|
||||
multiplied by C. */
|
||||
|
||||
|
@ -887,7 +887,6 @@ init_optimization_passes (void)
|
||||
NEXT_PASS (pass_record_bounds);
|
||||
NEXT_PASS (pass_check_data_deps);
|
||||
NEXT_PASS (pass_loop_distribution);
|
||||
NEXT_PASS (pass_linear_transform);
|
||||
NEXT_PASS (pass_copy_prop);
|
||||
NEXT_PASS (pass_graphite);
|
||||
{
|
||||
|
@ -1,3 +1,48 @@
|
||||
2011-01-25 Sebastian Pop <sebastian.pop@amd.com>
|
||||
|
||||
* gfortran.dg/graphite/interchange-4.f: New.
|
||||
* gfortran.dg/graphite/interchange-5.f: New.
|
||||
|
||||
* gcc.dg/tree-ssa/ltrans-1.c: Removed.
|
||||
* gcc.dg/tree-ssa/ltrans-2.c: Removed.
|
||||
* gcc.dg/tree-ssa/ltrans-3.c: Removed.
|
||||
* gcc.dg/tree-ssa/ltrans-4.c: Removed.
|
||||
* gcc.dg/tree-ssa/ltrans-5.c: Removed.
|
||||
* gcc.dg/tree-ssa/ltrans-6.c: Removed.
|
||||
* gcc.dg/tree-ssa/ltrans-8.c: Removed.
|
||||
* gfortran.dg/ltrans-7.f90: Removed.
|
||||
* gcc.dg/tree-ssa/data-dep-1.c: Removed.
|
||||
|
||||
* gcc.dg/pr18792.c: -> gcc.dg/graphite/pr18792.c
|
||||
* gcc.dg/pr19910.c: -> gcc.dg/graphite/pr19910.c
|
||||
* gcc.dg/tree-ssa/20041110-1.c: -> gcc.dg/graphite/pr20041110-1.c
|
||||
* gcc.dg/tree-ssa/pr20256.c: -> gcc.dg/graphite/pr20256.c
|
||||
* gcc.dg/pr23625.c: -> gcc.dg/graphite/pr23625.c
|
||||
* gcc.dg/tree-ssa/pr23820.c: -> gcc.dg/graphite/pr23820.c
|
||||
* gcc.dg/tree-ssa/pr24309.c: -> gcc.dg/graphite/pr24309.c
|
||||
* gcc.dg/tree-ssa/pr26435.c: -> gcc.dg/graphite/pr26435.c
|
||||
* gcc.dg/pr29330.c: -> gcc.dg/graphite/pr29330.c
|
||||
* gcc.dg/pr29581-1.c: -> gcc.dg/graphite/pr29581-1.c
|
||||
* gcc.dg/pr29581-2.c: -> gcc.dg/graphite/pr29581-2.c
|
||||
* gcc.dg/pr29581-3.c: -> gcc.dg/graphite/pr29581-3.c
|
||||
* gcc.dg/pr29581-4.c: -> gcc.dg/graphite/pr29581-4.c
|
||||
* gcc.dg/tree-ssa/loop-27.c: -> gcc.dg/graphite/pr30565.c
|
||||
* gcc.dg/tree-ssa/pr31183.c: -> gcc.dg/graphite/pr31183.c
|
||||
* gcc.dg/tree-ssa/pr33576.c: -> gcc.dg/graphite/pr33576.c
|
||||
* gcc.dg/tree-ssa/pr33766.c: -> gcc.dg/graphite/pr33766.c
|
||||
* gcc.dg/pr34016.c: -> gcc.dg/graphite/pr34016.c
|
||||
* gcc.dg/tree-ssa/pr34017.c: -> gcc.dg/graphite/pr34017.c
|
||||
* gcc.dg/tree-ssa/pr34123.c: -> gcc.dg/graphite/pr34123.c
|
||||
* gcc.dg/tree-ssa/pr36287.c: -> gcc.dg/graphite/pr36287.c
|
||||
* gcc.dg/tree-ssa/pr37686.c: -> gcc.dg/graphite/pr37686.c
|
||||
* gcc.dg/pr42917.c: -> gcc.dg/graphite/pr42917.c
|
||||
* gcc.dg/tree-ssa/data-dep-1.c
|
||||
* gfortran.dg/loop_nest_1.f90: -> gfortran.dg/graphite/pr29290.f90
|
||||
* gfortran.dg/pr29581.f90: -> gfortran.dg/graphite/pr29581.f90
|
||||
* gfortran.dg/pr36286.f90: -> gfortran.dg/graphite/pr36286.f90
|
||||
* gfortran.dg/pr36922.f: -> gfortran.dg/graphite/pr36922.f
|
||||
* gfortran.dg/pr39516.f: -> gfortran.dg/graphite/pr39516.f
|
||||
|
||||
2011-01-25 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/47265
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear" } */
|
||||
/* { dg-require-effective-target size32plus } */
|
||||
|
||||
int foo()
|
||||
@ -20,6 +20,3 @@ int foo()
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "converted loop nest to perfect loop nest" 0 "ltrans"} } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear" } */
|
||||
/* { dg-require-effective-target size32plus } */
|
||||
|
||||
int foo(int *p, int n)
|
||||
@ -15,6 +15,3 @@ int foo(int *p, int n)
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "converted loop nest to perfect loop nest" 0 "ltrans"} } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
13
gcc/testsuite/gcc.dg/graphite/pr42917.c
Normal file
13
gcc/testsuite/gcc.dg/graphite/pr42917.c
Normal file
@ -0,0 +1,13 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -ftree-loop-linear -fcompare-debug" } */
|
||||
|
||||
extern int A[];
|
||||
|
||||
void
|
||||
foo ()
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 255; j >= 0; j--)
|
||||
A[j] = 0;
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -ftree-loop-linear -fcompare-debug -fdump-tree-ltrans" } */
|
||||
|
||||
extern int A[];
|
||||
|
||||
void
|
||||
foo ()
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 255; j >= 0; j--)
|
||||
A[j] = 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Successfully transformed loop" "ltrans" } } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
@ -1,28 +0,0 @@
|
||||
/* { dg-do compile { target int32plus } } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
|
||||
int foo (int n, int m)
|
||||
{
|
||||
int a[10000][10000];
|
||||
int i, j, k;
|
||||
|
||||
for(k = 0; k < 1234; k++)
|
||||
for(j = 0; j < 5; j++)
|
||||
for(i = 0; i < 67; i++)
|
||||
{
|
||||
a[j+i-(-m+n+3)][i-k+4] = a[k+j][i];
|
||||
}
|
||||
|
||||
return a[0][0];
|
||||
}
|
||||
|
||||
|
||||
/* For the data dependence analysis of the outermost loop, the
|
||||
evolution of "k+j" should be instantiated in the outermost loop "k"
|
||||
and the evolution should be taken in the innermost loop "i". The
|
||||
pattern below ensures that the evolution is not computed in the
|
||||
outermost "k" loop: the 4 comes from the instantiation of the
|
||||
number of iterations of loop "j". */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "4, \\+, 1" 0 "ltrans" } } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
@ -1,24 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all -march=i486" { target { i?86-*-* && ilp32} } } */
|
||||
/* { dg-require-effective-target size32plus } */
|
||||
|
||||
double u[1782225];
|
||||
int foo(int N, int *res)
|
||||
{
|
||||
int i, j;
|
||||
double sum = 0.0;
|
||||
/* This loop should be converted to a perfect nest and
|
||||
interchanged. */
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
for (j = 0; j < N; j++)
|
||||
sum = sum + u[i + 1335 * j];
|
||||
|
||||
u[1336 * i] *= 2;
|
||||
}
|
||||
*res = sum + N;
|
||||
}
|
||||
/* { dg-final { scan-tree-dump-times "converted loop nest to perfect loop nest" 1 "ltrans"} } */
|
||||
/* { dg-final { scan-tree-dump-times "transformed loop" 1 "ltrans"} } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
@ -1,26 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
/* { dg-require-effective-target size32plus } */
|
||||
|
||||
double u[1782225];
|
||||
int foo(int N, int *res)
|
||||
{
|
||||
unsigned int i, j;
|
||||
double sum = 0;
|
||||
|
||||
/* This loop should be converted to a perfect nest and
|
||||
interchanged. */
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
for (j = 0; j < N; j++)
|
||||
{
|
||||
sum = sum + u[i + 1335 * j];
|
||||
if (j == N - 1)
|
||||
u[1336 * i] *= 2;
|
||||
}
|
||||
}
|
||||
*res = sum + N;
|
||||
}
|
||||
/* { dg-final { scan-tree-dump-times "transformed loop" 1 "ltrans"} {
|
||||
xfail *-*-*} } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
@ -1,22 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all -march=i486" { target { i?86-*-* && ilp32} } } */
|
||||
/* { dg-require-effective-target size32plus } */
|
||||
|
||||
double u[1782225];
|
||||
int foo(int N, int *res)
|
||||
{
|
||||
unsigned int i, j;
|
||||
double sum = 0;
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
for (j = 0; j < N; j++)
|
||||
{
|
||||
sum = sum + u[i + 1335 * j];
|
||||
}
|
||||
}
|
||||
*res = sum + N;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "transformed loop" 1 "ltrans" } } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
@ -1,21 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all -march=i486" { target { i?86-*-* && ilp32} } } */
|
||||
/* { dg-require-effective-target size32plus } */
|
||||
|
||||
double u[1782225];
|
||||
int foo(int N, int *res)
|
||||
{
|
||||
int i, j;
|
||||
double sum = 0;
|
||||
for (i = 0; i < N; i++)
|
||||
for (j = 0; j < N; j++)
|
||||
sum = sum + u[i + 1335 * j];
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
u[1336 * i] *= 2;
|
||||
*res = sum + N;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "transformed loop" 1 "ltrans"} } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
@ -1,18 +0,0 @@
|
||||
/* { dg-do compile { target { size32plus } } } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all -march=i486" { target { i?86-*-* && ilp32} } } */
|
||||
|
||||
int foo ()
|
||||
{
|
||||
int A[100][1111];
|
||||
int i, j;
|
||||
|
||||
for( i = 0; i < 1111; i++)
|
||||
for( j = 0; j < 100; j++)
|
||||
A[j][i] = 5 * A[j][i];
|
||||
|
||||
return A[10][10];
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "transformed loop" 1 "ltrans"} } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
@ -1,22 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all -march=i486" { target { i?86-*-* && ilp32} } } */
|
||||
/* { dg-require-effective-target size32plus } */
|
||||
|
||||
|
||||
|
||||
int medium_loop_interchange(int A[100][200])
|
||||
{
|
||||
int i,j;
|
||||
|
||||
/* This loop should be interchanged. */
|
||||
|
||||
for(j = 0; j < 200; j++)
|
||||
for(i = 0; i < 100; i++)
|
||||
A[i][j] = A[i][j] + A[i][j];
|
||||
|
||||
return A[1][1];
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "transformed loop" 1 "ltrans"} } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
@ -1,15 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
|
||||
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all -march=i486" { target { i?86-*-* && ilp32} } } */
|
||||
double foo(double *a)
|
||||
{
|
||||
int i,j;
|
||||
double r = 0.0;
|
||||
for (i=0; i<100; ++i)
|
||||
for (j=0; j<1000; ++j)
|
||||
r += a[j*100+i];
|
||||
return r;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "transformed loop" 1 "ltrans"} } */
|
||||
/* { dg-final { cleanup-tree-dump "ltrans" } } */
|
29
gcc/testsuite/gfortran.dg/graphite/interchange-4.f
Normal file
29
gcc/testsuite/gfortran.dg/graphite/interchange-4.f
Normal file
@ -0,0 +1,29 @@
|
||||
subroutine s231 (ntimes,ld,n,ctime,dtime,a,b,c,d,e,aa,bb,cc)
|
||||
c
|
||||
c loop interchange
|
||||
c loop with multiple dimension recursion
|
||||
c
|
||||
integer ntimes, ld, n, i, nl, j
|
||||
double precision a(n), b(n), c(n), d(n), e(n), aa(ld,n),
|
||||
+ bb(ld,n), cc(ld,n)
|
||||
double precision chksum, cs2d
|
||||
real t1, t2, second, ctime, dtime
|
||||
|
||||
call init(ld,n,a,b,c,d,e,aa,bb,cc,'s231 ')
|
||||
t1 = second()
|
||||
do 1 nl = 1,ntimes/n
|
||||
do 10 i=1,n
|
||||
do 20 j=2,n
|
||||
aa(i,j) = aa(i,j-1) + bb(i,j)
|
||||
20 continue
|
||||
10 continue
|
||||
call dummy(ld,n,a,b,c,d,e,aa,bb,cc,1.d0)
|
||||
1 continue
|
||||
t2 = second() - t1 - ctime - ( dtime * float(ntimes/n) )
|
||||
chksum = cs2d(n,aa)
|
||||
call check (chksum,(ntimes/n)*n*(n-1),n,t2,'s231 ')
|
||||
return
|
||||
end
|
||||
|
||||
! { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } }
|
||||
! { dg-final { cleanup-tree-dump "graphite" } }
|
30
gcc/testsuite/gfortran.dg/graphite/interchange-5.f
Normal file
30
gcc/testsuite/gfortran.dg/graphite/interchange-5.f
Normal file
@ -0,0 +1,30 @@
|
||||
subroutine s235 (ntimes,ld,n,ctime,dtime,a,b,c,d,e,aa,bb,cc)
|
||||
c
|
||||
c loop interchanging
|
||||
c imperfectly nested loops
|
||||
c
|
||||
integer ntimes, ld, n, i, nl, j
|
||||
double precision a(n), b(n), c(n), d(n), e(n), aa(ld,n),
|
||||
+ bb(ld,n), cc(ld,n)
|
||||
double precision chksum, cs1d, cs2d
|
||||
real t1, t2, second, ctime, dtime
|
||||
|
||||
call init(ld,n,a,b,c,d,e,aa,bb,cc,'s235 ')
|
||||
t1 = second()
|
||||
do 1 nl = 1,ntimes/n
|
||||
do 10 i = 1,n
|
||||
a(i) = a(i) + b(i) * c(i)
|
||||
do 20 j = 2,n
|
||||
aa(i,j) = aa(i,j-1) + bb(i,j) * a(i)
|
||||
20 continue
|
||||
10 continue
|
||||
call dummy(ld,n,a,b,c,d,e,aa,bb,cc,1.d0)
|
||||
1 continue
|
||||
t2 = second() - t1 - ctime - ( dtime * float(ntimes/n) )
|
||||
chksum = cs2d(n,aa) + cs1d(n,a)
|
||||
call check (chksum,(ntimes/n)*n*(n-1),n,t2,'s235 ')
|
||||
return
|
||||
end
|
||||
|
||||
! { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } }
|
||||
! { dg-final { cleanup-tree-dump "graphite" } }
|
@ -1,31 +0,0 @@
|
||||
! { dg-do compile }
|
||||
! { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" }
|
||||
! { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all -march=i486" { target { i?86-*-* && ilp32 } } }
|
||||
|
||||
Program FOO
|
||||
IMPLICIT INTEGER (I-N)
|
||||
IMPLICIT REAL*8 (A-H, O-Z)
|
||||
PARAMETER (N1=1335, N2=1335)
|
||||
COMMON U(N1,N2), V(N1,N2), P(N1,N2)
|
||||
|
||||
PC = 0.0D0
|
||||
UC = 0.0D0
|
||||
VC = 0.0D0
|
||||
|
||||
do I = 1, M
|
||||
do J = 1, M
|
||||
PC = PC + abs(P(I,J))
|
||||
UC = UC + abs(U(I,J))
|
||||
VC = VC + abs(V(I,J))
|
||||
end do
|
||||
U(I,I) = U(I,I) * ( mod (I, 100) /100.)
|
||||
end do
|
||||
|
||||
write(6,366) PC, UC, VC
|
||||
366 format(/, ' PC = ',E12.4,/,' UC = ',E12.4,/,' VC = ',E12.4,/)
|
||||
|
||||
end Program FOO
|
||||
|
||||
! Please do not XFAIL.
|
||||
! { dg-final { scan-tree-dump-times "transformed loop" 1 "ltrans" } }
|
||||
! { dg-final { cleanup-tree-dump "ltrans" } }
|
@ -340,6 +340,18 @@ print_dir_vectors (FILE *outf, VEC (lambda_vector, heap) *dir_vects,
|
||||
print_direction_vector (outf, v, length);
|
||||
}
|
||||
|
||||
/* Print out a vector VEC of length N to OUTFILE. */
|
||||
|
||||
static inline void
|
||||
print_lambda_vector (FILE * outfile, lambda_vector vector, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
fprintf (outfile, "%3d ", vector[i]);
|
||||
fprintf (outfile, "\n");
|
||||
}
|
||||
|
||||
/* Print a vector of distance vectors. */
|
||||
|
||||
void
|
||||
@ -2064,6 +2076,168 @@ compute_overlap_steps_for_affine_1_2 (tree chrec_a, tree chrec_b,
|
||||
affine_fn_free (overlaps_b_xyz);
|
||||
}
|
||||
|
||||
/* Copy the elements of vector VEC1 with length SIZE to VEC2. */
|
||||
|
||||
static void
|
||||
lambda_vector_copy (lambda_vector vec1, lambda_vector vec2,
|
||||
int size)
|
||||
{
|
||||
memcpy (vec2, vec1, size * sizeof (*vec1));
|
||||
}
|
||||
|
||||
/* Copy the elements of M x N matrix MAT1 to MAT2. */
|
||||
|
||||
static void
|
||||
lambda_matrix_copy (lambda_matrix mat1, lambda_matrix mat2,
|
||||
int m, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
lambda_vector_copy (mat1[i], mat2[i], n);
|
||||
}
|
||||
|
||||
/* Store the N x N identity matrix in MAT. */
|
||||
|
||||
static void
|
||||
lambda_matrix_id (lambda_matrix mat, int size)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
for (j = 0; j < size; j++)
|
||||
mat[i][j] = (i == j) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Return the first nonzero element of vector VEC1 between START and N.
|
||||
We must have START <= N. Returns N if VEC1 is the zero vector. */
|
||||
|
||||
static int
|
||||
lambda_vector_first_nz (lambda_vector vec1, int n, int start)
|
||||
{
|
||||
int j = start;
|
||||
while (j < n && vec1[j] == 0)
|
||||
j++;
|
||||
return j;
|
||||
}
|
||||
|
||||
/* Add a multiple of row R1 of matrix MAT with N columns to row R2:
|
||||
R2 = R2 + CONST1 * R1. */
|
||||
|
||||
static void
|
||||
lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2, int const1)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (const1 == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
mat[r2][i] += const1 * mat[r1][i];
|
||||
}
|
||||
|
||||
/* Swap rows R1 and R2 in matrix MAT. */
|
||||
|
||||
static void
|
||||
lambda_matrix_row_exchange (lambda_matrix mat, int r1, int r2)
|
||||
{
|
||||
lambda_vector row;
|
||||
|
||||
row = mat[r1];
|
||||
mat[r1] = mat[r2];
|
||||
mat[r2] = row;
|
||||
}
|
||||
|
||||
/* Multiply vector VEC1 of length SIZE by a constant CONST1,
|
||||
and store the result in VEC2. */
|
||||
|
||||
static void
|
||||
lambda_vector_mult_const (lambda_vector vec1, lambda_vector vec2,
|
||||
int size, int const1)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (const1 == 0)
|
||||
lambda_vector_clear (vec2, size);
|
||||
else
|
||||
for (i = 0; i < size; i++)
|
||||
vec2[i] = const1 * vec1[i];
|
||||
}
|
||||
|
||||
/* Negate vector VEC1 with length SIZE and store it in VEC2. */
|
||||
|
||||
static void
|
||||
lambda_vector_negate (lambda_vector vec1, lambda_vector vec2,
|
||||
int size)
|
||||
{
|
||||
lambda_vector_mult_const (vec1, vec2, size, -1);
|
||||
}
|
||||
|
||||
/* Negate row R1 of matrix MAT which has N columns. */
|
||||
|
||||
static void
|
||||
lambda_matrix_row_negate (lambda_matrix mat, int n, int r1)
|
||||
{
|
||||
lambda_vector_negate (mat[r1], mat[r1], n);
|
||||
}
|
||||
|
||||
/* Return true if two vectors are equal. */
|
||||
|
||||
static bool
|
||||
lambda_vector_equal (lambda_vector vec1, lambda_vector vec2, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
if (vec1[i] != vec2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Given an M x N integer matrix A, this function determines an M x
|
||||
M unimodular matrix U, and an M x N echelon matrix S such that
|
||||
"U.A = S". This decomposition is also known as "right Hermite".
|
||||
|
||||
Ref: Algorithm 2.1 page 33 in "Loop Transformations for
|
||||
Restructuring Compilers" Utpal Banerjee. */
|
||||
|
||||
static void
|
||||
lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
|
||||
lambda_matrix S, lambda_matrix U)
|
||||
{
|
||||
int i, j, i0 = 0;
|
||||
|
||||
lambda_matrix_copy (A, S, m, n);
|
||||
lambda_matrix_id (U, m);
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
if (lambda_vector_first_nz (S[j], m, i0) < m)
|
||||
{
|
||||
++i0;
|
||||
for (i = m - 1; i >= i0; i--)
|
||||
{
|
||||
while (S[i][j] != 0)
|
||||
{
|
||||
int sigma, factor, a, b;
|
||||
|
||||
a = S[i-1][j];
|
||||
b = S[i][j];
|
||||
sigma = (a * b < 0) ? -1: 1;
|
||||
a = abs (a);
|
||||
b = abs (b);
|
||||
factor = sigma * (a / b);
|
||||
|
||||
lambda_matrix_row_add (S, n, i, i-1, -factor);
|
||||
lambda_matrix_row_exchange (S, i, i-1);
|
||||
|
||||
lambda_matrix_row_add (U, m, i, i-1, -factor);
|
||||
lambda_matrix_row_exchange (U, i, i-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determines the overlapping elements due to accesses CHREC_A and
|
||||
CHREC_B, that are affine functions. This function cannot handle
|
||||
symbolic evolution functions, ie. when initial conditions are
|
||||
|
@ -23,7 +23,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
#define GCC_TREE_DATA_REF_H
|
||||
|
||||
#include "graphds.h"
|
||||
#include "lambda.h"
|
||||
#include "omega.h"
|
||||
#include "tree-chrec.h"
|
||||
|
||||
@ -96,6 +95,19 @@ struct dr_alias
|
||||
bitmap vops;
|
||||
};
|
||||
|
||||
/* An integer vector. A vector formally consists of an element of a vector
|
||||
space. A vector space is a set that is closed under vector addition
|
||||
and scalar multiplication. In this vector space, an element is a list of
|
||||
integers. */
|
||||
typedef int *lambda_vector;
|
||||
DEF_VEC_P(lambda_vector);
|
||||
DEF_VEC_ALLOC_P(lambda_vector,heap);
|
||||
DEF_VEC_ALLOC_P(lambda_vector,gc);
|
||||
|
||||
/* An integer matrix. A matrix consists of m vectors of length n (IE
|
||||
all vectors are the same length). */
|
||||
typedef lambda_vector *lambda_matrix;
|
||||
|
||||
/* Each vector of the access matrix represents a linear access
|
||||
function for a subscript. First elements correspond to the
|
||||
leftmost indices, ie. for a[i][j] the first vector corresponds to
|
||||
@ -494,6 +506,22 @@ ddrs_have_anti_deps (VEC (ddr_p, heap) *dependence_relations)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Returns the dependence level for a vector DIST of size LENGTH.
|
||||
LEVEL = 0 means a lexicographic dependence, i.e. a dependence due
|
||||
to the sequence of statements, not carried by any loop. */
|
||||
|
||||
static inline unsigned
|
||||
dependence_level (lambda_vector dist_vect, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
if (dist_vect[i] != 0)
|
||||
return i + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the dependence level for the DDR relation. */
|
||||
|
||||
static inline unsigned
|
||||
@ -629,16 +657,6 @@ rdg_has_similar_memory_accesses (struct graph *rdg, int v1, int v2)
|
||||
RDG_STMT (rdg, v2));
|
||||
}
|
||||
|
||||
/* In lambda-code.c */
|
||||
bool lambda_transform_legal_p (lambda_trans_matrix, int,
|
||||
VEC (ddr_p, heap) *);
|
||||
void lambda_collect_parameters (VEC (data_reference_p, heap) *,
|
||||
VEC (tree, heap) **);
|
||||
bool lambda_compute_access_matrices (VEC (data_reference_p, heap) *,
|
||||
VEC (tree, heap) *,
|
||||
VEC (loop_p, heap) *,
|
||||
struct obstack *);
|
||||
|
||||
/* In tree-data-ref.c */
|
||||
void split_constant_offset (tree , tree *, tree *);
|
||||
|
||||
@ -656,4 +674,86 @@ DEF_VEC_ALLOC_P (rdgc, heap);
|
||||
DEF_VEC_P (bitmap);
|
||||
DEF_VEC_ALLOC_P (bitmap, heap);
|
||||
|
||||
/* Compute the greatest common divisor of a VECTOR of SIZE numbers. */
|
||||
|
||||
static inline int
|
||||
lambda_vector_gcd (lambda_vector vector, int size)
|
||||
{
|
||||
int i;
|
||||
int gcd1 = 0;
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
gcd1 = vector[0];
|
||||
for (i = 1; i < size; i++)
|
||||
gcd1 = gcd (gcd1, vector[i]);
|
||||
}
|
||||
return gcd1;
|
||||
}
|
||||
|
||||
/* Allocate a new vector of given SIZE. */
|
||||
|
||||
static inline lambda_vector
|
||||
lambda_vector_new (int size)
|
||||
{
|
||||
return (lambda_vector) ggc_alloc_cleared_atomic (sizeof (int) * size);
|
||||
}
|
||||
|
||||
/* Clear out vector VEC1 of length SIZE. */
|
||||
|
||||
static inline void
|
||||
lambda_vector_clear (lambda_vector vec1, int size)
|
||||
{
|
||||
memset (vec1, 0, size * sizeof (*vec1));
|
||||
}
|
||||
|
||||
/* Returns true when the vector V is lexicographically positive, in
|
||||
other words, when the first nonzero element is positive. */
|
||||
|
||||
static inline bool
|
||||
lambda_vector_lexico_pos (lambda_vector v,
|
||||
unsigned n)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (v[i] == 0)
|
||||
continue;
|
||||
if (v[i] < 0)
|
||||
return false;
|
||||
if (v[i] > 0)
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return true if vector VEC1 of length SIZE is the zero vector. */
|
||||
|
||||
static inline bool
|
||||
lambda_vector_zerop (lambda_vector vec1, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
if (vec1[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Allocate a matrix of M rows x N cols. */
|
||||
|
||||
static inline lambda_matrix
|
||||
lambda_matrix_new (int m, int n, struct obstack *lambda_obstack)
|
||||
{
|
||||
lambda_matrix mat;
|
||||
int i;
|
||||
|
||||
mat = (lambda_matrix) obstack_alloc (lambda_obstack,
|
||||
sizeof (lambda_vector *) * m);
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
mat[i] = lambda_vector_new (n);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
#endif /* GCC_TREE_DATA_REF_H */
|
||||
|
@ -856,6 +856,4 @@ void warn_function_noreturn (tree);
|
||||
|
||||
void swap_tree_operands (gimple, tree *, tree *);
|
||||
|
||||
int least_common_multiple (int, int);
|
||||
|
||||
#endif /* _TREE_FLOW_H */
|
||||
|
@ -1,423 +0,0 @@
|
||||
/* Linear Loop transforms
|
||||
Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Daniel Berlin <dberlin@dberlin.org>.
|
||||
|
||||
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"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tree-flow.h"
|
||||
#include "cfgloop.h"
|
||||
#include "tree-chrec.h"
|
||||
#include "tree-data-ref.h"
|
||||
#include "tree-scalar-evolution.h"
|
||||
#include "tree-pass.h"
|
||||
#include "lambda.h"
|
||||
|
||||
/* Linear loop transforms include any composition of interchange,
|
||||
scaling, skewing, and reversal. They are used to change the
|
||||
iteration order of loop nests in order to optimize data locality of
|
||||
traversals, or remove dependences that prevent
|
||||
parallelization/vectorization/etc.
|
||||
|
||||
TODO: Determine reuse vectors/matrix and use it to determine optimal
|
||||
transform matrix for locality purposes.
|
||||
TODO: Completion of partial transforms. */
|
||||
|
||||
/* Gather statistics for loop interchange. LOOP is the loop being
|
||||
considered. The first loop in the considered loop nest is
|
||||
FIRST_LOOP, and consequently, the index of the considered loop is
|
||||
obtained by LOOP->DEPTH - FIRST_LOOP->DEPTH
|
||||
|
||||
Initializes:
|
||||
- DEPENDENCE_STEPS the sum of all the data dependence distances
|
||||
carried by loop LOOP,
|
||||
|
||||
- NB_DEPS_NOT_CARRIED_BY_LOOP the number of dependence relations
|
||||
for which the loop LOOP is not carrying any dependence,
|
||||
|
||||
- ACCESS_STRIDES the sum of all the strides in LOOP.
|
||||
|
||||
Example: for the following loop,
|
||||
|
||||
| loop_1 runs 1335 times
|
||||
| loop_2 runs 1335 times
|
||||
| A[{{0, +, 1}_1, +, 1335}_2]
|
||||
| B[{{0, +, 1}_1, +, 1335}_2]
|
||||
| endloop_2
|
||||
| A[{0, +, 1336}_1]
|
||||
| endloop_1
|
||||
|
||||
gather_interchange_stats (in loop_1) will return
|
||||
DEPENDENCE_STEPS = 3002
|
||||
NB_DEPS_NOT_CARRIED_BY_LOOP = 5
|
||||
ACCESS_STRIDES = 10694
|
||||
|
||||
gather_interchange_stats (in loop_2) will return
|
||||
DEPENDENCE_STEPS = 3000
|
||||
NB_DEPS_NOT_CARRIED_BY_LOOP = 7
|
||||
ACCESS_STRIDES = 8010
|
||||
*/
|
||||
|
||||
static void
|
||||
gather_interchange_stats (VEC (ddr_p, heap) *dependence_relations ATTRIBUTE_UNUSED,
|
||||
VEC (data_reference_p, heap) *datarefs ATTRIBUTE_UNUSED,
|
||||
struct loop *loop ATTRIBUTE_UNUSED,
|
||||
struct loop *first_loop ATTRIBUTE_UNUSED,
|
||||
unsigned int *dependence_steps ATTRIBUTE_UNUSED,
|
||||
unsigned int *nb_deps_not_carried_by_loop ATTRIBUTE_UNUSED,
|
||||
double_int *access_strides ATTRIBUTE_UNUSED)
|
||||
{
|
||||
unsigned int i, j;
|
||||
struct data_dependence_relation *ddr;
|
||||
struct data_reference *dr;
|
||||
|
||||
*dependence_steps = 0;
|
||||
*nb_deps_not_carried_by_loop = 0;
|
||||
*access_strides = double_int_zero;
|
||||
|
||||
FOR_EACH_VEC_ELT (ddr_p, dependence_relations, i, ddr)
|
||||
{
|
||||
/* If we don't know anything about this dependence, or the distance
|
||||
vector is NULL, or there is no dependence, then there is no reuse of
|
||||
data. */
|
||||
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know
|
||||
|| DDR_ARE_DEPENDENT (ddr) == chrec_known
|
||||
|| DDR_NUM_DIST_VECTS (ddr) == 0)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < DDR_NUM_DIST_VECTS (ddr); j++)
|
||||
{
|
||||
int dist = DDR_DIST_VECT (ddr, j)[loop_depth (loop) - loop_depth (first_loop)];
|
||||
|
||||
if (dist == 0)
|
||||
(*nb_deps_not_carried_by_loop) += 1;
|
||||
|
||||
else if (dist < 0)
|
||||
(*dependence_steps) += -dist;
|
||||
|
||||
else
|
||||
(*dependence_steps) += dist;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the access strides. */
|
||||
FOR_EACH_VEC_ELT (data_reference_p, datarefs, i, dr)
|
||||
{
|
||||
unsigned int it;
|
||||
tree ref = DR_REF (dr);
|
||||
gimple stmt = DR_STMT (dr);
|
||||
struct loop *stmt_loop = loop_containing_stmt (stmt);
|
||||
struct loop *inner_loop = first_loop->inner;
|
||||
|
||||
if (inner_loop != stmt_loop
|
||||
&& !flow_loop_nested_p (inner_loop, stmt_loop))
|
||||
continue;
|
||||
|
||||
for (it = 0; it < DR_NUM_DIMENSIONS (dr);
|
||||
it++, ref = TREE_OPERAND (ref, 0))
|
||||
{
|
||||
int num = am_vector_index_for_loop (DR_ACCESS_MATRIX (dr), loop->num);
|
||||
int istride = AM_GET_ACCESS_MATRIX_ELEMENT (DR_ACCESS_MATRIX (dr), it, num);
|
||||
tree array_size = TYPE_SIZE (TREE_TYPE (ref));
|
||||
double_int dstride;
|
||||
|
||||
if (array_size == NULL_TREE
|
||||
|| TREE_CODE (array_size) != INTEGER_CST)
|
||||
continue;
|
||||
|
||||
dstride = double_int_mul (tree_to_double_int (array_size),
|
||||
shwi_to_double_int (istride));
|
||||
(*access_strides) = double_int_add (*access_strides, dstride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to apply interchange transformations to TRANS to maximize the
|
||||
spatial and temporal locality of the loop.
|
||||
Returns the new transform matrix. The smaller the reuse vector
|
||||
distances in the inner loops, the fewer the cache misses.
|
||||
FIRST_LOOP is the loop->num of the first loop in the analyzed loop
|
||||
nest. */
|
||||
|
||||
|
||||
static lambda_trans_matrix
|
||||
try_interchange_loops (lambda_trans_matrix trans,
|
||||
unsigned int depth,
|
||||
VEC (ddr_p, heap) *dependence_relations,
|
||||
VEC (data_reference_p, heap) *datarefs,
|
||||
struct loop *first_loop)
|
||||
{
|
||||
bool res;
|
||||
struct loop *loop_i;
|
||||
struct loop *loop_j;
|
||||
unsigned int dependence_steps_i, dependence_steps_j;
|
||||
double_int access_strides_i, access_strides_j;
|
||||
double_int small, large, nb_iter;
|
||||
double_int l1_cache_size, l2_cache_size;
|
||||
int cmp;
|
||||
unsigned int nb_deps_not_carried_by_i, nb_deps_not_carried_by_j;
|
||||
struct data_dependence_relation *ddr;
|
||||
|
||||
if (VEC_length (ddr_p, dependence_relations) == 0)
|
||||
return trans;
|
||||
|
||||
/* When there is an unknown relation in the dependence_relations, we
|
||||
know that it is no worth looking at this loop nest: give up. */
|
||||
ddr = VEC_index (ddr_p, dependence_relations, 0);
|
||||
if (ddr == NULL || DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
|
||||
return trans;
|
||||
|
||||
l1_cache_size = uhwi_to_double_int (L1_CACHE_SIZE * 1024);
|
||||
l2_cache_size = uhwi_to_double_int (L2_CACHE_SIZE * 1024);
|
||||
|
||||
/* LOOP_I is always the outer loop. */
|
||||
for (loop_j = first_loop->inner;
|
||||
loop_j;
|
||||
loop_j = loop_j->inner)
|
||||
for (loop_i = first_loop;
|
||||
loop_depth (loop_i) < loop_depth (loop_j);
|
||||
loop_i = loop_i->inner)
|
||||
{
|
||||
gather_interchange_stats (dependence_relations, datarefs,
|
||||
loop_i, first_loop,
|
||||
&dependence_steps_i,
|
||||
&nb_deps_not_carried_by_i,
|
||||
&access_strides_i);
|
||||
gather_interchange_stats (dependence_relations, datarefs,
|
||||
loop_j, first_loop,
|
||||
&dependence_steps_j,
|
||||
&nb_deps_not_carried_by_j,
|
||||
&access_strides_j);
|
||||
|
||||
/* Heuristics for loop interchange profitability:
|
||||
|
||||
0. Don't transform if the smallest stride is larger than
|
||||
the L2 cache, or if the largest stride multiplied by the
|
||||
number of iterations is smaller than the L1 cache.
|
||||
|
||||
1. (spatial locality) Inner loops should have smallest
|
||||
dependence steps.
|
||||
|
||||
2. (spatial locality) Inner loops should contain more
|
||||
dependence relations not carried by the loop.
|
||||
|
||||
3. (temporal locality) Inner loops should have smallest
|
||||
array access strides.
|
||||
*/
|
||||
|
||||
cmp = double_int_ucmp (access_strides_i, access_strides_j);
|
||||
small = cmp < 0 ? access_strides_i : access_strides_j;
|
||||
large = cmp < 0 ? access_strides_j : access_strides_i;
|
||||
|
||||
if (double_int_ucmp (small, l2_cache_size) > 0)
|
||||
continue;
|
||||
|
||||
res = cmp < 0 ?
|
||||
estimated_loop_iterations (loop_j, false, &nb_iter):
|
||||
estimated_loop_iterations (loop_i, false, &nb_iter);
|
||||
|
||||
if (res
|
||||
&& double_int_ucmp (double_int_mul (large, nb_iter),
|
||||
l1_cache_size) < 0)
|
||||
continue;
|
||||
|
||||
if (dependence_steps_i < dependence_steps_j
|
||||
|| nb_deps_not_carried_by_i > nb_deps_not_carried_by_j
|
||||
|| cmp < 0)
|
||||
{
|
||||
lambda_matrix_row_exchange (LTM_MATRIX (trans),
|
||||
loop_depth (loop_i) - loop_depth (first_loop),
|
||||
loop_depth (loop_j) - loop_depth (first_loop));
|
||||
/* Validate the resulting matrix. When the transformation
|
||||
is not valid, reverse to the previous transformation. */
|
||||
if (!lambda_transform_legal_p (trans, depth, dependence_relations))
|
||||
lambda_matrix_row_exchange (LTM_MATRIX (trans),
|
||||
loop_depth (loop_i) - loop_depth (first_loop),
|
||||
loop_depth (loop_j) - loop_depth (first_loop));
|
||||
}
|
||||
}
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
/* Return the number of nested loops in LOOP_NEST, or 0 if the loops
|
||||
are not perfectly nested. */
|
||||
|
||||
unsigned int
|
||||
perfect_loop_nest_depth (struct loop *loop_nest)
|
||||
{
|
||||
struct loop *temp;
|
||||
unsigned int depth = 1;
|
||||
|
||||
/* If it's not a loop nest, we don't want it. We also don't handle
|
||||
sibling loops properly, which are loops of the following form:
|
||||
|
||||
| for (i = 0; i < 50; i++)
|
||||
| {
|
||||
| for (j = 0; j < 50; j++)
|
||||
| {
|
||||
| ...
|
||||
| }
|
||||
| for (j = 0; j < 50; j++)
|
||||
| {
|
||||
| ...
|
||||
| }
|
||||
| }
|
||||
*/
|
||||
|
||||
if (!loop_nest->inner || !single_exit (loop_nest))
|
||||
return 0;
|
||||
|
||||
for (temp = loop_nest->inner; temp; temp = temp->inner)
|
||||
{
|
||||
/* If we have a sibling loop or multiple exit edges, jump ship. */
|
||||
if (temp->next || !single_exit (temp))
|
||||
return 0;
|
||||
|
||||
depth++;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
/* Perform a set of linear transforms on loops. */
|
||||
|
||||
void
|
||||
linear_transform_loops (void)
|
||||
{
|
||||
bool modified = false;
|
||||
loop_iterator li;
|
||||
VEC(tree,heap) *oldivs = NULL;
|
||||
VEC(tree,heap) *invariants = NULL;
|
||||
VEC(tree,heap) *lambda_parameters = NULL;
|
||||
VEC(gimple,heap) *remove_ivs = VEC_alloc (gimple, heap, 3);
|
||||
struct loop *loop_nest;
|
||||
gimple oldiv_stmt;
|
||||
unsigned i;
|
||||
|
||||
FOR_EACH_LOOP (li, loop_nest, 0)
|
||||
{
|
||||
unsigned int depth = 0;
|
||||
VEC (ddr_p, heap) *dependence_relations;
|
||||
VEC (data_reference_p, heap) *datarefs;
|
||||
|
||||
lambda_loopnest before, after;
|
||||
lambda_trans_matrix trans;
|
||||
struct obstack lambda_obstack;
|
||||
struct loop *loop;
|
||||
VEC (loop_p, heap) *nest;
|
||||
VEC (loop_p, heap) *ln;
|
||||
|
||||
depth = perfect_loop_nest_depth (loop_nest);
|
||||
if (depth == 0)
|
||||
continue;
|
||||
|
||||
nest = VEC_alloc (loop_p, heap, 3);
|
||||
for (loop = loop_nest; loop; loop = loop->inner)
|
||||
VEC_safe_push (loop_p, heap, nest, loop);
|
||||
|
||||
gcc_obstack_init (&lambda_obstack);
|
||||
VEC_truncate (tree, oldivs, 0);
|
||||
VEC_truncate (tree, invariants, 0);
|
||||
VEC_truncate (tree, lambda_parameters, 0);
|
||||
|
||||
datarefs = VEC_alloc (data_reference_p, heap, 10);
|
||||
dependence_relations = VEC_alloc (ddr_p, heap, 10 * 10);
|
||||
ln = VEC_alloc (loop_p, heap, 3);
|
||||
if (!compute_data_dependences_for_loop (loop_nest, true, &ln, &datarefs,
|
||||
&dependence_relations))
|
||||
goto free_and_continue;
|
||||
|
||||
lambda_collect_parameters (datarefs, &lambda_parameters);
|
||||
if (!lambda_compute_access_matrices (datarefs, lambda_parameters,
|
||||
nest, &lambda_obstack))
|
||||
goto free_and_continue;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
dump_ddrs (dump_file, dependence_relations);
|
||||
|
||||
/* Build the transformation matrix. */
|
||||
trans = lambda_trans_matrix_new (depth, depth, &lambda_obstack);
|
||||
lambda_matrix_id (LTM_MATRIX (trans), depth);
|
||||
trans = try_interchange_loops (trans, depth, dependence_relations,
|
||||
datarefs, loop_nest);
|
||||
|
||||
if (lambda_trans_matrix_id_p (trans))
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Won't transform loop. Optimal transform is the identity transform\n");
|
||||
goto free_and_continue;
|
||||
}
|
||||
|
||||
/* Check whether the transformation is legal. */
|
||||
if (!lambda_transform_legal_p (trans, depth, dependence_relations))
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Can't transform loop, transform is illegal:\n");
|
||||
goto free_and_continue;
|
||||
}
|
||||
|
||||
before = gcc_loopnest_to_lambda_loopnest (loop_nest, &oldivs,
|
||||
&invariants, &lambda_obstack);
|
||||
|
||||
if (!before)
|
||||
goto free_and_continue;
|
||||
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (dump_file, "Before:\n");
|
||||
print_lambda_loopnest (dump_file, before, 'i');
|
||||
}
|
||||
|
||||
after = lambda_loopnest_transform (before, trans, &lambda_obstack);
|
||||
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (dump_file, "After:\n");
|
||||
print_lambda_loopnest (dump_file, after, 'u');
|
||||
}
|
||||
|
||||
lambda_loopnest_to_gcc_loopnest (loop_nest, oldivs, invariants,
|
||||
&remove_ivs,
|
||||
after, trans, &lambda_obstack);
|
||||
modified = true;
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Successfully transformed loop.\n");
|
||||
|
||||
free_and_continue:
|
||||
obstack_free (&lambda_obstack, NULL);
|
||||
free_dependence_relations (dependence_relations);
|
||||
free_data_refs (datarefs);
|
||||
VEC_free (loop_p, heap, nest);
|
||||
VEC_free (loop_p, heap, ln);
|
||||
}
|
||||
|
||||
FOR_EACH_VEC_ELT (gimple, remove_ivs, i, oldiv_stmt)
|
||||
remove_iv (oldiv_stmt);
|
||||
|
||||
VEC_free (tree, heap, oldivs);
|
||||
VEC_free (tree, heap, invariants);
|
||||
VEC_free (gimple, heap, remove_ivs);
|
||||
scev_reset ();
|
||||
|
||||
if (modified)
|
||||
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa_full_phi);
|
||||
}
|
@ -240,6 +240,125 @@ name_to_copy_elt_hash (const void *aa)
|
||||
return (hashval_t) a->version;
|
||||
}
|
||||
|
||||
/* A transformation matrix, which is a self-contained ROWSIZE x COLSIZE
|
||||
matrix. Rather than use floats, we simply keep a single DENOMINATOR that
|
||||
represents the denominator for every element in the matrix. */
|
||||
typedef struct lambda_trans_matrix_s
|
||||
{
|
||||
lambda_matrix matrix;
|
||||
int rowsize;
|
||||
int colsize;
|
||||
int denominator;
|
||||
} *lambda_trans_matrix;
|
||||
#define LTM_MATRIX(T) ((T)->matrix)
|
||||
#define LTM_ROWSIZE(T) ((T)->rowsize)
|
||||
#define LTM_COLSIZE(T) ((T)->colsize)
|
||||
#define LTM_DENOMINATOR(T) ((T)->denominator)
|
||||
|
||||
/* Allocate a new transformation matrix. */
|
||||
|
||||
static lambda_trans_matrix
|
||||
lambda_trans_matrix_new (int colsize, int rowsize,
|
||||
struct obstack * lambda_obstack)
|
||||
{
|
||||
lambda_trans_matrix ret;
|
||||
|
||||
ret = (lambda_trans_matrix)
|
||||
obstack_alloc (lambda_obstack, sizeof (struct lambda_trans_matrix_s));
|
||||
LTM_MATRIX (ret) = lambda_matrix_new (rowsize, colsize, lambda_obstack);
|
||||
LTM_ROWSIZE (ret) = rowsize;
|
||||
LTM_COLSIZE (ret) = colsize;
|
||||
LTM_DENOMINATOR (ret) = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Multiply a vector VEC by a matrix MAT.
|
||||
MAT is an M*N matrix, and VEC is a vector with length N. The result
|
||||
is stored in DEST which must be a vector of length M. */
|
||||
|
||||
static void
|
||||
lambda_matrix_vector_mult (lambda_matrix matrix, int m, int n,
|
||||
lambda_vector vec, lambda_vector dest)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
lambda_vector_clear (dest, m);
|
||||
for (i = 0; i < m; i++)
|
||||
for (j = 0; j < n; j++)
|
||||
dest[i] += matrix[i][j] * vec[j];
|
||||
}
|
||||
|
||||
/* Return true if TRANS is a legal transformation matrix that respects
|
||||
the dependence vectors in DISTS and DIRS. The conservative answer
|
||||
is false.
|
||||
|
||||
"Wolfe proves that a unimodular transformation represented by the
|
||||
matrix T is legal when applied to a loop nest with a set of
|
||||
lexicographically non-negative distance vectors RDG if and only if
|
||||
for each vector d in RDG, (T.d >= 0) is lexicographically positive.
|
||||
i.e.: if and only if it transforms the lexicographically positive
|
||||
distance vectors to lexicographically positive vectors. Note that
|
||||
a unimodular matrix must transform the zero vector (and only it) to
|
||||
the zero vector." S.Muchnick. */
|
||||
|
||||
static bool
|
||||
lambda_transform_legal_p (lambda_trans_matrix trans,
|
||||
int nb_loops,
|
||||
VEC (ddr_p, heap) *dependence_relations)
|
||||
{
|
||||
unsigned int i, j;
|
||||
lambda_vector distres;
|
||||
struct data_dependence_relation *ddr;
|
||||
|
||||
gcc_assert (LTM_COLSIZE (trans) == nb_loops
|
||||
&& LTM_ROWSIZE (trans) == nb_loops);
|
||||
|
||||
/* When there are no dependences, the transformation is correct. */
|
||||
if (VEC_length (ddr_p, dependence_relations) == 0)
|
||||
return true;
|
||||
|
||||
ddr = VEC_index (ddr_p, dependence_relations, 0);
|
||||
if (ddr == NULL)
|
||||
return true;
|
||||
|
||||
/* When there is an unknown relation in the dependence_relations, we
|
||||
know that it is no worth looking at this loop nest: give up. */
|
||||
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
|
||||
return false;
|
||||
|
||||
distres = lambda_vector_new (nb_loops);
|
||||
|
||||
/* For each distance vector in the dependence graph. */
|
||||
FOR_EACH_VEC_ELT (ddr_p, dependence_relations, i, ddr)
|
||||
{
|
||||
/* Don't care about relations for which we know that there is no
|
||||
dependence, nor about read-read (aka. output-dependences):
|
||||
these data accesses can happen in any order. */
|
||||
if (DDR_ARE_DEPENDENT (ddr) == chrec_known
|
||||
|| (DR_IS_READ (DDR_A (ddr)) && DR_IS_READ (DDR_B (ddr))))
|
||||
continue;
|
||||
|
||||
/* Conservatively answer: "this transformation is not valid". */
|
||||
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
|
||||
return false;
|
||||
|
||||
/* If the dependence could not be captured by a distance vector,
|
||||
conservatively answer that the transform is not valid. */
|
||||
if (DDR_NUM_DIST_VECTS (ddr) == 0)
|
||||
return false;
|
||||
|
||||
/* Compute trans.dist_vect */
|
||||
for (j = 0; j < DDR_NUM_DIST_VECTS (ddr); j++)
|
||||
{
|
||||
lambda_matrix_vector_mult (LTM_MATRIX (trans), nb_loops, nb_loops,
|
||||
DDR_DIST_VECT (ddr, j), distres);
|
||||
|
||||
if (!lambda_vector_lexico_pos (distres, nb_loops))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Data dependency analysis. Returns true if the iterations of LOOP
|
||||
are independent on each other (that is, if we can execute them
|
||||
|
@ -274,7 +274,7 @@ struct dump_file_info
|
||||
/* Insert PHI nodes everywhere they are needed. No pruning of the
|
||||
IDF is done. This is used by passes that need the PHI nodes for
|
||||
O_j even if it means that some arguments will come from the default
|
||||
definition of O_j's symbol (e.g., pass_linear_transform).
|
||||
definition of O_j's symbol.
|
||||
|
||||
WARNING: If you need to use this flag, chances are that your pass
|
||||
may be doing something wrong. Inserting PHI nodes for an old name
|
||||
@ -431,7 +431,6 @@ extern struct gimple_opt_pass pass_rename_ssa_copies;
|
||||
extern struct gimple_opt_pass pass_rest_of_compilation;
|
||||
extern struct gimple_opt_pass pass_sink_code;
|
||||
extern struct gimple_opt_pass pass_fre;
|
||||
extern struct gimple_opt_pass pass_linear_transform;
|
||||
extern struct gimple_opt_pass pass_check_data_deps;
|
||||
extern struct gimple_opt_pass pass_copy_prop;
|
||||
extern struct gimple_opt_pass pass_vrp;
|
||||
|
@ -246,45 +246,6 @@ struct gimple_opt_pass pass_vectorize =
|
||||
}
|
||||
};
|
||||
|
||||
/* Loop nest optimizations. */
|
||||
|
||||
static unsigned int
|
||||
tree_linear_transform (void)
|
||||
{
|
||||
if (number_of_loops () <= 1)
|
||||
return 0;
|
||||
|
||||
linear_transform_loops ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
gate_tree_linear_transform (void)
|
||||
{
|
||||
return flag_tree_loop_linear != 0;
|
||||
}
|
||||
|
||||
struct gimple_opt_pass pass_linear_transform =
|
||||
{
|
||||
{
|
||||
GIMPLE_PASS,
|
||||
"ltrans", /* name */
|
||||
gate_tree_linear_transform, /* gate */
|
||||
tree_linear_transform, /* execute */
|
||||
NULL, /* sub */
|
||||
NULL, /* next */
|
||||
0, /* static_pass_number */
|
||||
TV_TREE_LINEAR_TRANSFORM, /* tv_id */
|
||||
PROP_cfg | PROP_ssa, /* properties_required */
|
||||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
TODO_dump_func
|
||||
| TODO_update_ssa_only_virtuals
|
||||
| TODO_ggc_collect /* todo_flags_finish */
|
||||
}
|
||||
};
|
||||
|
||||
/* GRAPHITE optimizations. */
|
||||
|
||||
static unsigned int
|
||||
@ -305,12 +266,17 @@ gate_graphite_transforms (void)
|
||||
is turned on. */
|
||||
if (flag_loop_block
|
||||
|| flag_loop_interchange
|
||||
|| flag_tree_loop_linear
|
||||
|| flag_loop_strip_mine
|
||||
|| flag_graphite_identity
|
||||
|| flag_loop_parallelize_all
|
||||
|| flag_loop_flatten)
|
||||
flag_graphite = 1;
|
||||
|
||||
/* Make flag_tree_loop_linear an alias of flag_loop_interchange. */
|
||||
if (flag_tree_loop_linear)
|
||||
flag_loop_interchange = flag_tree_loop_linear;
|
||||
|
||||
return flag_graphite != 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user