diff options
author | Razya Ladelsky <razya@il.ibm.com> | 2009-07-30 08:39:57 +0000 |
---|---|---|
committer | Razya Ladelsky <razya@gcc.gnu.org> | 2009-07-30 08:39:57 +0000 |
commit | 08dab97a61578a3f9145786b3d07f73cb63ef276 (patch) | |
tree | 299bb21c623018572b34cfc6bc1013e8fb209dea /gcc/tree-ssa-loop-manip.c | |
parent | 88c2fd3d625c9a0536d72f07fd969ef535b90c52 (diff) | |
download | gcc-08dab97a61578a3f9145786b3d07f73cb63ef276.zip gcc-08dab97a61578a3f9145786b3d07f73cb63ef276.tar.gz gcc-08dab97a61578a3f9145786b3d07f73cb63ef276.tar.bz2 |
ssa-loop-manip.c: Include langhooks.h.
2009-07-30 Razya Ladelsky <razya@il.ibm.com>
* ssa-loop-manip.c: Include langhooks.h.
(rewrite_phi_with_iv): New.
(rewrite_all_phi_nodes_with_iv): New.
(canonicalize_loop_ivs): Move here from tree-parloops.c.
Remove reduction_list argument. Use rewrite_all_phi_nodes_with_iv.
* tree-parloops.c (loop_parallel_p): Move out all conditions
except dependency check.
(canonicalize_loop_ivs): Move to tree-ssa-loop-manip.c.
(gen_parallel_loop): Call canonicalize_loop_ivs without
reduction_list argument.
(build_new_reduction): New.
(gather_scalar_reductions): New.
(try_get_loop_niter): New.
(try_create_reduction_list): New.
(parallleize_loops): Change the parallel conditions check.
* tree-flow.h (canonicalize_loop_ivs): Remove one argument.
* Makefile.in (tree-ssa-loop-manip.o): Add langhooks.h dependency.
From-SVN: r150250
Diffstat (limited to 'gcc/tree-ssa-loop-manip.c')
-rw-r--r-- | gcc/tree-ssa-loop-manip.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index b891ea6..c4a40b0 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-scalar-evolution.h" #include "params.h" #include "tree-inline.h" +#include "langhooks.h" /* Creates an induction variable with value BASE + STEP * iteration in LOOP. It is expected that neither BASE nor STEP are shared with other expressions @@ -1100,3 +1101,132 @@ tree_unroll_loop (struct loop *loop, unsigned factor, tree_transform_and_unroll_loop (loop, factor, exit, desc, NULL, NULL); } + +/* Rewrite the phi node at position PSI in function of the main + induction variable MAIN_IV and insert the generated code at GSI. */ + +static void +rewrite_phi_with_iv (loop_p loop, + gimple_stmt_iterator *psi, + gimple_stmt_iterator *gsi, + tree main_iv) +{ + affine_iv iv; + gimple stmt, phi = gsi_stmt (*psi); + tree atype, mtype, val, res = PHI_RESULT (phi); + + if (!is_gimple_reg (res) || res == main_iv) + { + gsi_next (psi); + return; + } + + if (!simple_iv (loop, loop, res, &iv, true)) + { + gsi_next (psi); + return; + } + + remove_phi_node (psi, false); + + atype = TREE_TYPE (res); + mtype = POINTER_TYPE_P (atype) ? sizetype : atype; + val = fold_build2 (MULT_EXPR, mtype, unshare_expr (iv.step), + fold_convert (mtype, main_iv)); + val = fold_build2 (POINTER_TYPE_P (atype) + ? POINTER_PLUS_EXPR : PLUS_EXPR, + atype, unshare_expr (iv.base), val); + val = force_gimple_operand_gsi (gsi, val, false, NULL_TREE, true, + GSI_SAME_STMT); + stmt = gimple_build_assign (res, val); + gsi_insert_before (gsi, stmt, GSI_SAME_STMT); + SSA_NAME_DEF_STMT (res) = stmt; +} + +/* Rewrite all the phi nodes of LOOP in function of the main induction + variable MAIN_IV. */ + +static void +rewrite_all_phi_nodes_with_iv (loop_p loop, tree main_iv) +{ + unsigned i; + basic_block *bbs = get_loop_body_in_dom_order (loop); + gimple_stmt_iterator psi; + + for (i = 0; i < loop->num_nodes; i++) + { + basic_block bb = bbs[i]; + gimple_stmt_iterator gsi = gsi_after_labels (bb); + + if (bb->loop_father != loop) + continue; + + for (psi = gsi_start_phis (bb); !gsi_end_p (psi); ) + rewrite_phi_with_iv (loop, &psi, &gsi, main_iv); + } + + free (bbs); +} + +/* Bases all the induction variables in LOOP on a single induction + variable (unsigned with base 0 and step 1), whose final value is + compared with *NIT. When the IV type precision has to be larger + than *NIT type precision, *NIT is converted to the larger type, the + conversion code is inserted before the loop, and *NIT is updated to + the new definition. The induction variable is incremented in the + loop latch. Return the induction variable that was created. */ + +tree +canonicalize_loop_ivs (struct loop *loop, tree *nit) +{ + unsigned precision = TYPE_PRECISION (TREE_TYPE (*nit)); + unsigned original_precision = precision; + tree type, var_before; + gimple_stmt_iterator gsi, psi; + gimple stmt; + edge exit = single_dom_exit (loop); + gimple_seq stmts; + + for (psi = gsi_start_phis (loop->header); + !gsi_end_p (psi); gsi_next (&psi)) + { + gimple phi = gsi_stmt (psi); + tree res = PHI_RESULT (phi); + + if (is_gimple_reg (res) && TYPE_PRECISION (TREE_TYPE (res)) > precision) + precision = TYPE_PRECISION (TREE_TYPE (res)); + } + + type = lang_hooks.types.type_for_size (precision, 1); + + if (original_precision != precision) + { + *nit = fold_convert (type, *nit); + *nit = force_gimple_operand (*nit, &stmts, true, NULL_TREE); + if (stmts) + gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); + } + + gsi = gsi_last_bb (loop->latch); + create_iv (build_int_cst_type (type, 0), build_int_cst (type, 1), NULL_TREE, + loop, &gsi, true, &var_before, NULL); + + rewrite_all_phi_nodes_with_iv (loop, var_before); + + stmt = last_stmt (exit->src); + /* Make the loop exit if the control condition is not satisfied. */ + if (exit->flags & EDGE_TRUE_VALUE) + { + edge te, fe; + + extract_true_false_edges_from_block (exit->src, &te, &fe); + te->flags = EDGE_FALSE_VALUE; + fe->flags = EDGE_TRUE_VALUE; + } + gimple_cond_set_code (stmt, LT_EXPR); + gimple_cond_set_lhs (stmt, var_before); + gimple_cond_set_rhs (stmt, *nit); + update_stmt (stmt); + + return var_before; +} |