aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-manip.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-loop-manip.c')
-rw-r--r--gcc/tree-ssa-loop-manip.c71
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