diff options
Diffstat (limited to 'gcc/tree-ssa-loop-manip.c')
-rw-r--r-- | gcc/tree-ssa-loop-manip.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index 19b0ca2..e096d26 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -37,6 +37,77 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "cfglayout.h" #include "tree-scalar-evolution.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 + (unless the sharing rules allow this). Use VAR as a base var_decl for it + (if NULL, a new temporary will be created). The increment will occur at + INCR_POS (after it if AFTER is true, before it otherwise). The ssa versions + of the variable before and after increment will be stored in VAR_BEFORE and + VAR_AFTER (unless they are NULL). */ + +void +create_iv (tree base, tree step, tree var, struct loop *loop, + block_stmt_iterator *incr_pos, bool after, + tree *var_before, tree *var_after) +{ + tree stmt, initial, step1; + tree vb, va; + enum tree_code incr_op = PLUS_EXPR; + + if (!var) + { + var = create_tmp_var (TREE_TYPE (base), "ivtmp"); + add_referenced_tmp_var (var); + } + + vb = make_ssa_name (var, NULL_TREE); + if (var_before) + *var_before = vb; + va = make_ssa_name (var, NULL_TREE); + if (var_after) + *var_after = va; + + /* For easier readability of the created code, produce MINUS_EXPRs + when suitable. */ + if (TREE_CODE (step) == INTEGER_CST) + { + if (TYPE_UNSIGNED (TREE_TYPE (step))) + { + step1 = fold (build1 (NEGATE_EXPR, TREE_TYPE (step), step)); + if (tree_int_cst_lt (step1, step)) + { + incr_op = MINUS_EXPR; + step = step1; + } + } + else + { + if (!tree_expr_nonnegative_p (step) + && may_negate_without_overflow_p (step)) + { + incr_op = MINUS_EXPR; + step = fold (build1 (NEGATE_EXPR, TREE_TYPE (step), step)); + } + } + } + + stmt = build2 (MODIFY_EXPR, void_type_node, va, + build2 (incr_op, TREE_TYPE (base), + vb, step)); + SSA_NAME_DEF_STMT (va) = stmt; + if (after) + bsi_insert_after (incr_pos, stmt, BSI_NEW_STMT); + else + bsi_insert_before (incr_pos, stmt, BSI_NEW_STMT); + + initial = base; + + stmt = create_phi_node (vb, loop->header); + SSA_NAME_DEF_STMT (vb) = stmt; + add_phi_arg (&stmt, initial, loop_preheader_edge (loop)); + add_phi_arg (&stmt, va, loop_latch_edge (loop)); +} + /* Add exit phis for the USE on EXIT. */ static void |