You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
#include "config.h"
#include "system.h"
ubound = gcc_tree_to_linear_expression (depth, uboundvar,
outerinductionvars,
*invariants, extra);
- uboundresult = build (PLUS_EXPR, TREE_TYPE (uboundvar), uboundvar,
- build_int_cst (TREE_TYPE (uboundvar), extra));
+ uboundresult = build2 (PLUS_EXPR, TREE_TYPE (uboundvar), uboundvar,
+ build_int_cst (TREE_TYPE (uboundvar), extra));
VEC_safe_push (tree, heap, *uboundvars, uboundresult);
VEC_safe_push (tree, heap, *lboundvars, lboundvar);
VEC_safe_push (int, heap, *steps, stepint);
add_referenced_tmp_var (resvar);
/* Start at 0. */
- stmt = build (MODIFY_EXPR, void_type_node, resvar, integer_zero_node);
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar, integer_zero_node);
name = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = name;
tsi = tsi_last (stmts);
/* newname = coefficient * induction_variable */
coeffmult = build_int_cst (type, LBV_COEFFICIENTS (lbv)[i]);
- stmt = build (MODIFY_EXPR, void_type_node, resvar,
- fold (build (MULT_EXPR, type, iv, coeffmult)));
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar,
+ fold_build2 (MULT_EXPR, type, iv, coeffmult));
newname = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = newname;
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
/* name = name + newname */
- stmt = build (MODIFY_EXPR, void_type_node, resvar,
- build (PLUS_EXPR, type, name, newname));
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar,
+ build2 (PLUS_EXPR, type, name, newname));
name = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
if (LBV_DENOMINATOR (lbv) != 1)
{
tree denominator = build_int_cst (type, LBV_DENOMINATOR (lbv));
- stmt = build (MODIFY_EXPR, void_type_node, resvar,
- build (CEIL_DIV_EXPR, type, name, denominator));
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar,
+ build2 (CEIL_DIV_EXPR, type, name, denominator));
name = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
for (; lle != NULL; lle = LLE_NEXT (lle))
{
/* Start at name = 0. */
- stmt = build (MODIFY_EXPR, void_type_node, resvar, integer_zero_node);
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar, integer_zero_node);
name = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
{
coeff = build_int_cst (type,
LLE_COEFFICIENTS (lle)[i]);
- mult = fold (build (MULT_EXPR, type, iv, coeff));
+ mult = fold_build2 (MULT_EXPR, type, iv, coeff);
}
/* newname = mult */
- stmt = build (MODIFY_EXPR, void_type_node, resvar, mult);
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar, mult);
newname = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = newname;
fold_stmt (&stmt);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
/* name = name + newname */
- stmt = build (MODIFY_EXPR, void_type_node, resvar,
- build (PLUS_EXPR, type, name, newname));
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar,
+ build2 (PLUS_EXPR, type, name, newname));
name = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
else
{
coeff = build_int_cst (type, invcoeff);
- mult = fold (build (MULT_EXPR, type, invar, coeff));
+ mult = fold_build2 (MULT_EXPR, type, invar, coeff);
}
/* newname = mult */
- stmt = build (MODIFY_EXPR, void_type_node, resvar, mult);
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar, mult);
newname = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = newname;
fold_stmt (&stmt);
tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
/* name = name + newname */
- stmt = build (MODIFY_EXPR, void_type_node, resvar,
- build (PLUS_EXPR, type, name, newname));
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar,
+ build2 (PLUS_EXPR, type, name, newname));
name = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
name = name + constant. */
if (LLE_CONSTANT (lle) != 0)
{
- stmt = build (MODIFY_EXPR, void_type_node, resvar,
- build (PLUS_EXPR, type, name,
- build_int_cst (type, LLE_CONSTANT (lle))));
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar,
+ build2 (PLUS_EXPR, type, name,
+ build_int_cst (type, LLE_CONSTANT (lle))));
name = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
name = name + linear offset. */
if (LLE_CONSTANT (offset) != 0)
{
- stmt = build (MODIFY_EXPR, void_type_node, resvar,
- build (PLUS_EXPR, type, name,
- build_int_cst (type, LLE_CONSTANT (offset))));
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar,
+ build2 (PLUS_EXPR, type, name,
+ build_int_cst (type, LLE_CONSTANT (offset))));
name = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = name;
fold_stmt (&stmt);
if (LLE_DENOMINATOR (lle) != 1)
{
stmt = build_int_cst (type, LLE_DENOMINATOR (lle));
- stmt = build (wrap == MAX_EXPR ? CEIL_DIV_EXPR : FLOOR_DIV_EXPR,
- type, name, stmt);
- stmt = build (MODIFY_EXPR, void_type_node, resvar, stmt);
+ stmt = build2 (wrap == MAX_EXPR ? CEIL_DIV_EXPR : FLOOR_DIV_EXPR,
+ type, name, stmt);
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar, stmt);
/* name = {ceil, floor}(name/denominator) */
name = make_ssa_name (resvar, stmt);
{
tree op1 = VEC_index (tree, results, 0);
tree op2 = VEC_index (tree, results, 1);
- stmt = build (MODIFY_EXPR, void_type_node, resvar,
- build (wrap, type, op1, op2));
+ stmt = build2 (MODIFY_EXPR, void_type_node, resvar,
+ build2 (wrap, type, op1, op2));
name = make_ssa_name (resvar, stmt);
TREE_OPERAND (stmt, 0) = name;
tsi = tsi_last (stmts);
dominate the block containing the exit condition.
So we simply create our own incremented iv to use in the new exit
test, and let redundancy elimination sort it out. */
- inc_stmt = build (PLUS_EXPR, type,
- ivvar, build_int_cst (type, LL_STEP (newloop)));
- inc_stmt = build (MODIFY_EXPR, void_type_node, SSA_NAME_VAR (ivvar),
- inc_stmt);
+ inc_stmt = build2 (PLUS_EXPR, type,
+ ivvar, build_int_cst (type, LL_STEP (newloop)));
+ inc_stmt = build2 (MODIFY_EXPR, void_type_node, SSA_NAME_VAR (ivvar),
+ inc_stmt);
ivvarinced = make_ssa_name (SSA_NAME_VAR (ivvar), inc_stmt);
TREE_OPERAND (inc_stmt, 0) = ivvarinced;
bsi = bsi_for_stmt (exitcond);
if (exit->flags & EDGE_FALSE_VALUE)
testtype = swap_tree_comparison (testtype);
- COND_EXPR_COND (exitcond) = build (testtype,
- boolean_type_node,
- newupperbound, ivvarinced);
+ COND_EXPR_COND (exitcond) = build2 (testtype,
+ boolean_type_node,
+ newupperbound, ivvarinced);
update_stmt (exitcond);
VEC_replace (tree, new_ivs, i, ivvar);
VEC_free (tree, heap, new_ivs);
}
-/* Returns true when the vector V is lexicographically positive, in
- other words, when the first nonzero element is positive. */
-
-static 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 this is not interesting statement from the perspective of
determining if we have a perfect loop nest. */
access_fn = instantiate_parameters
(loop, analyze_scalar_evolution (loop, use));
- if (access_fn != NULL_TREE)
+ if (access_fn != NULL_TREE && access_fn != chrec_dont_know)
step = evolution_part_in_loop_num (access_fn, loop->num);
- if ((step && int_cst_value (step) == xstep)
+ if ((step && step != chrec_dont_know
+ && TREE_CODE (step) == INTEGER_CST
+ && int_cst_value (step) == xstep)
|| USE_FROM_PTR (use_p) == x)
SET_USE (use_p, y);
}
return true;
}
-/* Return true if STMT can be put back into INNER, a loop by moving it to the
- beginning of that loop. */
+/* Return true if STMT can be put back into the loop INNER, by
+ copying it to the beginning of that loop and changing the uses. */
static bool
can_put_in_inner_loop (struct loop *inner, tree stmt)
{
imm_use_iterator imm_iter;
use_operand_p use_p;
- basic_block use_bb = NULL;
gcc_assert (TREE_CODE (stmt) == MODIFY_EXPR);
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)
|| !expr_invariant_in_loop_p (inner, TREE_OPERAND (stmt, 1)))
return false;
- /* We require that the basic block of all uses be the same, or the use be an
- exit phi. */
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, TREE_OPERAND (stmt, 0))
{
if (!exit_phi_for_loop_p (inner, USE_STMT (use_p)))
if (!flow_bb_inside_loop_p (inner, immbb))
return false;
- if (use_bb == NULL)
- use_bb = immbb;
- else if (immbb != use_bb)
+ }
+ }
+ return true;
+}
+
+/* Return true if STMT can be put *after* the inner loop of LOOP. */
+static bool
+can_put_after_inner_loop (struct loop *loop, tree stmt)
+{
+ imm_use_iterator imm_iter;
+ use_operand_p use_p;
+
+ if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+ return false;
+
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, TREE_OPERAND (stmt, 0))
+ {
+ if (!exit_phi_for_loop_p (loop, USE_STMT (use_p)))
+ {
+ basic_block immbb = bb_for_stmt (USE_STMT (use_p));
+
+ if (!dominated_by_p (CDI_DOMINATORS,
+ immbb,
+ loop->inner->header)
+ && !can_put_in_inner_loop (loop->inner, stmt))
return false;
}
}
return true;
-
}
+
/* Return TRUE if LOOP is an imperfect nest that we can convert to a perfect
one. LOOPIVS is a vector of induction variables, one per loop.
ATM, we only handle imperfect nests of depth 2, where all of the statements
if (stmt_uses_op (stmt, iv))
goto fail;
- /* If this is a simple operation like a cast that is invariant
- in the inner loop, only used there, and we can place it
- there, then it's not going to hurt us.
- This means that we will propagate casts and other cheap
- invariant operations *back*
- into the inner loop if we can interchange the loop, on the
- theory that we are going to gain a lot more by interchanging
- the loop than we are by leaving some invariant code there for
- some other pass to clean up. */
+ /* If this is a simple operation like a cast that is
+ invariant in the inner loop, or after the inner loop,
+ then see if we can place it back where it came from.
+ This means that we will propagate casts and other
+ cheap invariant operations *back* into or after
+ the inner loop if we can interchange the loop, on the
+ theory that we are going to gain a lot more by
+ interchanging the loop than we are by leaving some
+ invariant code there for some other pass to clean
+ up. */
if (TREE_CODE (stmt) == MODIFY_EXPR
&& is_gimple_cast (TREE_OPERAND (stmt, 1))
- && can_put_in_inner_loop (loop->inner, stmt))
+ && (can_put_in_inner_loop (loop->inner, stmt)
+ || can_put_after_inner_loop (loop, stmt)))
continue;
/* Otherwise, if the bb of a statement we care about isn't
make_edge (headerbb, bodybb, EDGE_FALLTHRU);
then_label = build1 (GOTO_EXPR, void_type_node, tree_block_label (latchbb));
else_label = build1 (GOTO_EXPR, void_type_node, tree_block_label (olddest));
- cond_stmt = build (COND_EXPR, void_type_node,
- build (NE_EXPR, boolean_type_node,
- integer_one_node,
- integer_zero_node),
- then_label, else_label);
+ cond_stmt = build3 (COND_EXPR, void_type_node,
+ build2 (NE_EXPR, boolean_type_node,
+ integer_one_node,
+ integer_zero_node),
+ then_label, else_label);
bsi = bsi_start (bodybb);
bsi_insert_after (&bsi, cond_stmt, BSI_NEW_STMT);
e = make_edge (bodybb, olddest, EDGE_FALSE_VALUE);
exit_condition = get_loop_exit_condition (newloop);
uboundvar = create_tmp_var (integer_type_node, "uboundvar");
add_referenced_tmp_var (uboundvar);
- stmt = build (MODIFY_EXPR, void_type_node, uboundvar,
- VEC_index (tree, ubounds, 0));
+ stmt = build2 (MODIFY_EXPR, void_type_node, uboundvar,
+ VEC_index (tree, ubounds, 0));
uboundvar = make_ssa_name (uboundvar, stmt);
TREE_OPERAND (stmt, 0) = uboundvar;
else
bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
update_stmt (stmt);
- COND_EXPR_COND (exit_condition) = build (GE_EXPR,
- boolean_type_node,
- uboundvar,
- ivvarinced);
+ COND_EXPR_COND (exit_condition) = build2 (GE_EXPR,
+ boolean_type_node,
+ uboundvar,
+ ivvarinced);
update_stmt (exit_condition);
bbs = get_loop_body_in_dom_order (loop);
/* Now move the statements, and replace the induction variable in the moved
bsi_prev (&bsi);
continue;
}
- /* Move this statement back into the inner loop.
- This looks a bit confusing, but we are really just
- finding the first non-exit phi use and moving the
- statement to the beginning of that use's basic
- block. */
+
+ /* Make copies of this statement to put it back next
+ to its uses. */
FOR_EACH_IMM_USE_SAFE (use_p, imm_iter,
TREE_OPERAND (stmt, 0))
{
tree imm_stmt = USE_STMT (use_p);
if (!exit_phi_for_loop_p (loop->inner, imm_stmt))
{
- block_stmt_iterator tobsi = bsi_after_labels (bb_for_stmt (imm_stmt));
- bsi_move_after (&bsi, &tobsi);
- update_stmt (stmt);
- BREAK_FROM_SAFE_IMM_USE (imm_iter);
+ block_stmt_iterator tobsi;
+ tree newname;
+ tree newstmt;
+
+ newstmt = unshare_expr (stmt);
+ tobsi = bsi_after_labels (bb_for_stmt (imm_stmt));
+ newname = TREE_OPERAND (newstmt, 0);
+ newname = SSA_NAME_VAR (newname);
+ newname = make_ssa_name (newname, newstmt);
+ TREE_OPERAND (newstmt, 0) = newname;
+ SET_USE (use_p, TREE_OPERAND (newstmt, 0));
+ bsi_insert_before (&tobsi, newstmt, BSI_SAME_STMT);
+ update_stmt (newstmt);
+ update_stmt (imm_stmt);
}
}
+ if (!bsi_end_p (bsi))
+ bsi_prev (&bsi);
}
}
else
int nb_loops,
varray_type dependence_relations)
{
- unsigned int i;
+ unsigned int i, j;
lambda_vector distres;
struct data_dependence_relation *ddr;
/* If the dependence could not be captured by a distance vector,
conservatively answer that the transform is not valid. */
- if (DDR_DIST_VECT (ddr) == NULL)
+ if (DDR_NUM_DIST_VECTS (ddr) == 0)
return false;
/* Compute trans.dist_vect */
- lambda_matrix_vector_mult (LTM_MATRIX (trans), nb_loops, nb_loops,
- DDR_DIST_VECT (ddr), distres);
+ 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;
+ if (!lambda_vector_lexico_pos (distres, nb_loops))
+ return false;
+ }
}
return true;
}