lambda.h (build_linear_expr): New.

* lambda.h (build_linear_expr): New.
	* lambda-code.c (lbv_to_gcc_expression, lle_to_gcc_expression): 
	Use build_linear_expr, call fold and force_gimple_operand.
	(lambda_loopnest_to_gcc_loopnest): Check that there is
	something to insert.
	* testsuite/gcc.dg/tree-ssa/ltrans-6.c: New.


Co-Authored-By: Sebastian Pop <sebpop@gmail.com>

From-SVN: r125355
This commit is contained in:
Jan Sjodin 2007-06-06 06:08:58 +00:00 committed by Sebastian Pop
parent 518a0b7838
commit 69f2880c76
4 changed files with 113 additions and 227 deletions

View File

@ -1,3 +1,13 @@
2007-06-06 Jan Sjodin <jan.sjodin@amd.com>
Sebastian Pop <sebpop@gmail.com>
* lambda.h (build_linear_expr): New.
* lambda-code.c (lbv_to_gcc_expression, lle_to_gcc_expression):
Use build_linear_expr, call fold and force_gimple_operand.
(lambda_loopnest_to_gcc_loopnest): Check that there is
something to insert.
* testsuite/gcc.dg/tree-ssa/ltrans-6.c: New.
2007-06-05 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
PR preprocessor/23479

View File

@ -1528,71 +1528,18 @@ lbv_to_gcc_expression (lambda_body_vector lbv,
tree type, VEC(tree,heap) *induction_vars,
tree *stmts_to_insert)
{
tree stmts, stmt, resvar, name;
tree iv;
size_t i;
tree_stmt_iterator tsi;
int k;
tree resvar;
tree expr = build_linear_expr (type, LBV_COEFFICIENTS (lbv), induction_vars);
k = LBV_DENOMINATOR (lbv);
gcc_assert (k != 0);
if (k != 1)
expr = fold_build2 (CEIL_DIV_EXPR, type, expr, build_int_cst (type, k));
/* Create a statement list and a linear expression temporary. */
stmts = alloc_stmt_list ();
resvar = create_tmp_var (type, "lbvtmp");
add_referenced_var (resvar);
/* Start at 0. */
stmt = build_gimple_modify_stmt (resvar,
fold_convert (type, integer_zero_node));
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
for (i = 0; VEC_iterate (tree, induction_vars, i, iv); i++)
{
if (LBV_COEFFICIENTS (lbv)[i] != 0)
{
tree newname;
tree coeffmult;
/* newname = coefficient * induction_variable */
coeffmult = build_int_cst (type, LBV_COEFFICIENTS (lbv)[i]);
stmt = build_gimple_modify_stmt (resvar,
fold_build2 (MULT_EXPR, type,
iv, coeffmult));
newname = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = newname;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
/* name = name + newname */
stmt = build_gimple_modify_stmt (resvar,
build2 (PLUS_EXPR, type,
name, newname));
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
}
}
/* Handle any denominator that occurs. */
if (LBV_DENOMINATOR (lbv) != 1)
{
tree denominator = build_int_cst (type, LBV_DENOMINATOR (lbv));
stmt = build_gimple_modify_stmt (resvar,
build2 (CEIL_DIV_EXPR, type,
name, denominator));
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
}
*stmts_to_insert = stmts;
return name;
return force_gimple_operand (fold (expr), stmts_to_insert, true, resvar);
}
/* Convert a linear expression from coefficient and constant form to a
@ -1616,182 +1563,57 @@ lle_to_gcc_expression (lambda_linear_expression lle,
VEC(tree,heap) *invariants,
enum tree_code wrap, tree *stmts_to_insert)
{
tree stmts, stmt, resvar, name;
size_t i;
tree_stmt_iterator tsi;
tree iv, invar;
int k;
tree resvar;
tree expr = NULL_TREE;
VEC(tree,heap) *results = NULL;
gcc_assert (wrap == MAX_EXPR || wrap == MIN_EXPR);
name = NULL_TREE;
/* Create a statement list and a linear expression temporary. */
stmts = alloc_stmt_list ();
resvar = create_tmp_var (type, "lletmp");
add_referenced_var (resvar);
/* Build up the linear expressions, and put the variable representing the
result in the results array. */
/* Build up the linear expressions. */
for (; lle != NULL; lle = LLE_NEXT (lle))
{
/* Start at name = 0. */
stmt = build_gimple_modify_stmt (resvar,
fold_convert (type, integer_zero_node));
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
expr = build_linear_expr (type, LLE_COEFFICIENTS (lle), induction_vars);
expr = fold_build2 (PLUS_EXPR, type, expr,
build_linear_expr (type,
LLE_INVARIANT_COEFFICIENTS (lle),
invariants));
/* First do the induction variables.
at the end, name = name + all the induction variables added
together. */
for (i = 0; VEC_iterate (tree, induction_vars, i, iv); i++)
{
if (LLE_COEFFICIENTS (lle)[i] != 0)
{
tree newname;
tree mult;
tree coeff;
k = LLE_CONSTANT (lle);
if (k)
expr = fold_build2 (PLUS_EXPR, type, expr, build_int_cst (type, k));
/* mult = induction variable * coefficient. */
if (LLE_COEFFICIENTS (lle)[i] == 1)
{
mult = VEC_index (tree, induction_vars, i);
}
else
{
coeff = build_int_cst (type,
LLE_COEFFICIENTS (lle)[i]);
mult = fold_build2 (MULT_EXPR, type, iv, coeff);
}
k = LLE_CONSTANT (offset);
if (k)
expr = fold_build2 (PLUS_EXPR, type, expr, build_int_cst (type, k));
/* newname = mult */
stmt = build_gimple_modify_stmt (resvar, mult);
newname = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = newname;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
k = LLE_DENOMINATOR (lle);
if (k != 1)
expr = fold_build2 (wrap == MAX_EXPR ? CEIL_DIV_EXPR : FLOOR_DIV_EXPR,
type, expr, build_int_cst (type, k));
/* name = name + newname */
stmt = build_gimple_modify_stmt (resvar,
build2 (PLUS_EXPR, type,
name, newname));
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
}
}
/* Handle our invariants.
At the end, we have name = name + result of adding all multiplied
invariants. */
for (i = 0; VEC_iterate (tree, invariants, i, invar); i++)
{
if (LLE_INVARIANT_COEFFICIENTS (lle)[i] != 0)
{
tree newname;
tree mult;
tree coeff;
int invcoeff = LLE_INVARIANT_COEFFICIENTS (lle)[i];
/* mult = invariant * coefficient */
if (invcoeff == 1)
{
mult = invar;
}
else
{
coeff = build_int_cst (type, invcoeff);
mult = fold_build2 (MULT_EXPR, type, invar, coeff);
}
/* newname = mult */
stmt = build_gimple_modify_stmt (resvar, mult);
newname = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = newname;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
/* name = name + newname */
stmt = build_gimple_modify_stmt (resvar,
build2 (PLUS_EXPR, type,
name, newname));
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
}
}
/* Now handle the constant.
name = name + constant. */
if (LLE_CONSTANT (lle) != 0)
{
tree incr = build_int_cst (type, LLE_CONSTANT (lle));
stmt = build_gimple_modify_stmt (resvar, build2 (PLUS_EXPR, type,
name, incr));
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
}
/* Now handle the offset.
name = name + linear offset. */
if (LLE_CONSTANT (offset) != 0)
{
tree incr = build_int_cst (type, LLE_CONSTANT (offset));
stmt = build_gimple_modify_stmt (resvar, build2 (PLUS_EXPR, type,
name, incr));
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
}
/* Handle any denominator that occurs. */
if (LLE_DENOMINATOR (lle) != 1)
{
stmt = build_int_cst (type, LLE_DENOMINATOR (lle));
stmt = build2 (wrap == MAX_EXPR ? CEIL_DIV_EXPR : FLOOR_DIV_EXPR,
type, name, stmt);
stmt = build_gimple_modify_stmt (resvar, stmt);
/* name = {ceil, floor}(name/denominator) */
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
}
VEC_safe_push (tree, heap, results, name);
expr = fold (expr);
VEC_safe_push (tree, heap, results, expr);
}
/* Again, out of laziness, we don't handle this case yet. It's not
hard, it just hasn't occurred. */
gcc_assert (VEC_length (tree, results) <= 2);
gcc_assert (expr);
/* We may need to wrap the results in a MAX_EXPR or MIN_EXPR. */
if (VEC_length (tree, results) > 1)
{
tree op1 = VEC_index (tree, results, 0);
tree op2 = VEC_index (tree, results, 1);
stmt = build_gimple_modify_stmt (resvar, build2 (wrap, type, op1, op2));
name = make_ssa_name (resvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name;
tsi = tsi_last (stmts);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
size_t i;
tree op;
expr = VEC_index (tree, results, 0);
for (i = 1; VEC_iterate (tree, results, i, op); i++)
expr = fold_build2 (wrap, type, expr, op);
}
VEC_free (tree, heap, results);
*stmts_to_insert = stmts;
return name;
resvar = create_tmp_var (type, "lletmp");
add_referenced_var (resvar);
return force_gimple_operand (fold (expr), stmts_to_insert, true, resvar);
}
/* Transform a lambda loopnest NEW_LOOPNEST, which had TRANSFORM applied to
@ -1869,8 +1691,12 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
type,
new_ivs,
invariants, MAX_EXPR, &stmts);
bsi_insert_on_edge (loop_preheader_edge (temp), stmts);
bsi_commit_edge_inserts ();
if (stmts)
{
bsi_insert_on_edge (loop_preheader_edge (temp), stmts);
bsi_commit_edge_inserts ();
}
/* Build the new upper bound and insert its statements in the
basic block of the exit condition */
newupperbound = lle_to_gcc_expression (LL_UPPER_BOUND (newloop),
@ -1882,7 +1708,8 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
exitcond = get_loop_exit_condition (temp);
bb = bb_for_stmt (exitcond);
bsi = bsi_after_labels (bb);
bsi_insert_before (&bsi, stmts, BSI_NEW_STMT);
if (stmts)
bsi_insert_before (&bsi, stmts, BSI_NEW_STMT);
/* Create the new iv. */
@ -1960,10 +1787,11 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
newiv = lbv_to_gcc_expression (newlbv, TREE_TYPE (oldiv),
new_ivs, &stmts);
bsi = bsi_for_stmt (stmt);
/* Insert the statements to build that
expression. */
bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
if (stmts)
{
bsi = bsi_for_stmt (stmt);
bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
}
FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
propagate_value (use_p, newiv);

View File

@ -434,5 +434,32 @@ lambda_vector_lexico_pos (lambda_vector v,
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 = fold_convert (type, integer_zero_node);
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;
}
#endif /* LAMBDA_H */

View File

@ -0,0 +1,21 @@
/* { dg-do compile } */
/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
/* { 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" } } */