/* Compute the least common multiple of two numbers A and B . */
-static int
-lcm (int a, int b)
+int
+least_common_multiple (int a, int b)
{
return (abs (a) * abs (b) / gcd (a, b));
}
{
if (A[k][i] < 0)
{
- multiple = lcm (A[j][i], A[k][i]);
+ multiple = least_common_multiple (A[j][i], A[k][i]);
f1 = multiple / A[j][i];
f2 = -1 * multiple / A[k][i];
4. Multiply the composed transformation matrix times the matrix form of the
loop.
5. Transform the newly created matrix (from step 4) back into a loop nest
- using fourier motzkin elimination to figure out the bounds. */
+ using Fourier-Motzkin elimination to figure out the bounds. */
static lambda_loopnest
lambda_compute_auxillary_space (lambda_loopnest nest,
lambda_matrix_add_mc (B, 1, B1, -1, B1, size, invariants);
/* Now compute the auxiliary space bounds by first inverting U, multiplying
- it by A1, then performing fourier motzkin. */
+ it by A1, then performing Fourier-Motzkin. */
invertedtrans = lambda_matrix_new (depth, depth);
/* Create a statement list and a linear expression temporary. */
stmts = alloc_stmt_list ();
resvar = create_tmp_var (type, "lbvtmp");
- add_referenced_tmp_var (resvar);
+ add_referenced_var (resvar);
/* Start at 0. */
stmt = build2 (MODIFY_EXPR, void_type_node, resvar, integer_zero_node);
/* Create a statement list and a linear expression temporary. */
stmts = alloc_stmt_list ();
resvar = create_tmp_var (type, "lletmp");
- add_referenced_tmp_var (resvar);
+ add_referenced_var (resvar);
/* Build up the linear expressions, and put the variable representing the
result in the results array. */
/* First, build the new induction variable temporary */
ivvar = create_tmp_var (type, "lnivtmp");
- add_referenced_tmp_var (ivvar);
+ add_referenced_var (ivvar);
VEC_safe_push (tree, heap, new_ivs, ivvar);
return true;
}
-/* Replace the USES of X in STMT, or uses with the same step as X with Y. */
+/* Replace the USES of X in STMT, or uses with the same step as X with Y.
+ YINIT is the initial value of Y, REPLACEMENTS is a hash table to
+ avoid creating duplicate temporaries and FIRSTBSI is statement
+ iterator where new temporaries should be inserted at the beginning
+ of body basic block. */
static void
replace_uses_equiv_to_x_with_y (struct loop *loop, tree stmt, tree x,
- int xstep, tree y)
+ int xstep, tree y, tree yinit,
+ htab_t replacements,
+ block_stmt_iterator *firstbsi)
{
ssa_op_iter iter;
use_operand_p use_p;
{
tree use = USE_FROM_PTR (use_p);
tree step = NULL_TREE;
- tree scev = instantiate_parameters (loop,
- analyze_scalar_evolution (loop, use));
+ tree scev, init, val, var, setstmt;
+ struct tree_map *h, in;
+ void **loc;
- if (scev != NULL_TREE && scev != chrec_dont_know)
- step = evolution_part_in_loop_num (scev, loop->num);
+ /* Replace uses of X with Y right away. */
+ if (use == x)
+ {
+ SET_USE (use_p, y);
+ continue;
+ }
+
+ scev = instantiate_parameters (loop,
+ analyze_scalar_evolution (loop, use));
+
+ if (scev == NULL || scev == chrec_dont_know)
+ continue;
+
+ step = evolution_part_in_loop_num (scev, loop->num);
+ if (step == NULL
+ || step == chrec_dont_know
+ || TREE_CODE (step) != INTEGER_CST
+ || int_cst_value (step) != xstep)
+ continue;
+
+ /* Use REPLACEMENTS hash table to cache already created
+ temporaries. */
+ in.hash = htab_hash_pointer (use);
+ in.from = use;
+ h = htab_find_with_hash (replacements, &in, in.hash);
+ if (h != NULL)
+ {
+ SET_USE (use_p, h->to);
+ continue;
+ }
+
+ /* USE which has the same step as X should be replaced
+ with a temporary set to Y + YINIT - INIT. */
+ init = initial_condition_in_loop_num (scev, loop->num);
+ gcc_assert (init != NULL && init != chrec_dont_know);
+ if (TREE_TYPE (use) == TREE_TYPE (y))
+ {
+ val = fold_build2 (MINUS_EXPR, TREE_TYPE (y), init, yinit);
+ val = fold_build2 (PLUS_EXPR, TREE_TYPE (y), y, val);
+ if (val == y)
+ {
+ /* If X has the same type as USE, the same step
+ and same initial value, it can be replaced by Y. */
+ SET_USE (use_p, y);
+ continue;
+ }
+ }
+ else
+ {
+ val = fold_build2 (MINUS_EXPR, TREE_TYPE (y), y, yinit);
+ val = fold_convert (TREE_TYPE (use), val);
+ val = fold_build2 (PLUS_EXPR, TREE_TYPE (use), val, init);
+ }
- 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);
+ /* Create a temporary variable and insert it at the beginning
+ of the loop body basic block, right after the PHI node
+ which sets Y. */
+ var = create_tmp_var (TREE_TYPE (use), "perfecttmp");
+ add_referenced_var (var);
+ val = force_gimple_operand_bsi (firstbsi, val, false, NULL);
+ setstmt = build2 (MODIFY_EXPR, void_type_node, var, val);
+ var = make_ssa_name (var, setstmt);
+ TREE_OPERAND (setstmt, 0) = var;
+ bsi_insert_before (firstbsi, setstmt, BSI_SAME_STMT);
+ update_stmt (setstmt);
+ SET_USE (use_p, var);
+ h = ggc_alloc (sizeof (struct tree_map));
+ h->hash = in.hash;
+ h->from = use;
+ h->to = var;
+ loc = htab_find_slot_with_hash (replacements, h, in.hash, INSERT);
+ gcc_assert ((*(struct tree_map **)loc) == NULL);
+ *(struct tree_map **) loc = h;
}
}
tree then_label, else_label, cond_stmt;
basic_block preheaderbb, headerbb, bodybb, latchbb, olddest;
int i;
- block_stmt_iterator bsi;
+ block_stmt_iterator bsi, firstbsi;
bool insert_after;
edge e;
struct loop *newloop;
tree stmt;
tree oldivvar, ivvar, ivvarinced;
VEC(tree,heap) *phis = NULL;
-
+ htab_t replacements = NULL;
+
/* Create the new loop. */
olddest = loop->single_exit->dest;
preheaderbb = loop_split_edge_with (loop->single_exit, NULL);
/* Create the new iv. */
oldivvar = VEC_index (tree, loopivs, 0);
ivvar = create_tmp_var (TREE_TYPE (oldivvar), "perfectiv");
- add_referenced_tmp_var (ivvar);
+ add_referenced_var (ivvar);
standard_iv_increment_position (newloop, &bsi, &insert_after);
create_iv (VEC_index (tree, lbounds, 0),
build_int_cst (TREE_TYPE (oldivvar), VEC_index (int, steps, 0)),
exit_condition = get_loop_exit_condition (newloop);
uboundvar = create_tmp_var (integer_type_node, "uboundvar");
- add_referenced_tmp_var (uboundvar);
+ add_referenced_var (uboundvar);
stmt = build2 (MODIFY_EXPR, void_type_node, uboundvar,
VEC_index (tree, ubounds, 0));
uboundvar = make_ssa_name (uboundvar, stmt);
uboundvar,
ivvarinced);
update_stmt (exit_condition);
+ replacements = htab_create_ggc (20, tree_map_hash,
+ tree_map_eq, NULL);
bbs = get_loop_body_in_dom_order (loop);
/* Now move the statements, and replace the induction variable in the moved
statements with the correct loop induction variable. */
oldivvar = VEC_index (tree, loopivs, 0);
+ firstbsi = bsi_start (bodybb);
for (i = loop->num_nodes - 1; i >= 0 ; i--)
{
block_stmt_iterator tobsi = bsi_last (bodybb);
if (dominated_by_p (CDI_DOMINATORS, loop->inner->header, bbs[i]))
{
- for (bsi = bsi_last (bbs[i]); !bsi_end_p (bsi);)
+ block_stmt_iterator header_bsi
+ = bsi_after_labels (loop->inner->header);
+
+ for (bsi = bsi_start (bbs[i]); !bsi_end_p (bsi);)
{
- use_operand_p use_p;
- imm_use_iterator imm_iter;
- tree imm_stmt;
tree stmt = bsi_stmt (bsi);
if (stmt == exit_condition
|| not_interesting_stmt (stmt)
|| stmt_is_bumper_for_loop (loop, stmt))
{
- if (!bsi_end_p (bsi))
- bsi_prev (&bsi);
+ bsi_next (&bsi);
continue;
}
-
- /* Make copies of this statement to put it back next
- to its uses. */
- FOR_EACH_IMM_USE_STMT (imm_stmt, imm_iter,
- TREE_OPERAND (stmt, 0))
- {
- if (!exit_phi_for_loop_p (loop->inner, imm_stmt))
- {
- 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;
-
- FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
- SET_USE (use_p, newname);
-
- bsi_insert_before (&tobsi, newstmt, BSI_SAME_STMT);
- update_stmt (newstmt);
- update_stmt (imm_stmt);
- }
- }
- if (!bsi_end_p (bsi))
- bsi_prev (&bsi);
+
+ bsi_move_before (&bsi, &header_bsi);
}
}
else
}
replace_uses_equiv_to_x_with_y
- (loop, stmt, oldivvar, VEC_index (int, steps, 0), ivvar);
+ (loop, stmt, oldivvar, VEC_index (int, steps, 0), ivvar,
+ VEC_index (tree, lbounds, 0), replacements, &firstbsi);
bsi_move_before (&bsi, &tobsi);
}
free (bbs);
+ htab_delete (replacements);
return perfect_nest_p (loop);
}