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:
Sebastian Pop 2011-01-25 21:24:23 +00:00 committed by Sebastian Pop
parent 6bdfdb96ee
commit b305e3dab4
60 changed files with 632 additions and 4815 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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");
}

View File

@ -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));
}

View File

@ -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 */

View File

@ -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"

View File

@ -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. */

View File

@ -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);
{

View File

@ -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

View File

@ -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" } } */

View File

@ -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" } } */

View 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;
}

View File

@ -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" } } */

View File

@ -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" } } */

View File

@ -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" } } */

View File

@ -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" } } */

View File

@ -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" } } */

View File

@ -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" } } */

View File

@ -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" } } */

View File

@ -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" } } */

View File

@ -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" } } */

View 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" } }

View 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" } }

View File

@ -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" } }

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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;
}