diff options
Diffstat (limited to 'gcc-4.9/gcc/tree-ssa-loop-ivopts.c')
-rw-r--r-- | gcc-4.9/gcc/tree-ssa-loop-ivopts.c | 58 |
1 files changed, 27 insertions, 31 deletions
diff --git a/gcc-4.9/gcc/tree-ssa-loop-ivopts.c b/gcc-4.9/gcc/tree-ssa-loop-ivopts.c index 400187964..0bf8e2aff 100644 --- a/gcc-4.9/gcc/tree-ssa-loop-ivopts.c +++ b/gcc-4.9/gcc/tree-ssa-loop-ivopts.c @@ -142,9 +142,10 @@ struct iv tree base_object; /* A memory object to that the induction variable points. */ tree step; /* Step of the iv (constant only). */ tree ssa_name; /* The ssa name with the value. */ + unsigned use_id; /* The identifier in the use if it is the case. */ bool biv_p; /* Is it a biv? */ bool have_use_for; /* Do we already have a use for it? */ - unsigned use_id; /* The identifier in the use if it is the case. */ + bool no_overflow; /* True if the iv doesn't overflow. */ }; /* Per-ssa version information (induction variable descriptions, etc.). */ @@ -943,10 +944,10 @@ determine_base_object (tree expr) } /* Allocates an induction variable with given initial value BASE and step STEP - for loop LOOP. */ + for loop LOOP. NO_OVERFLOW implies the iv doesn't overflow. */ static struct iv * -alloc_iv (tree base, tree step) +alloc_iv (tree base, tree step, bool no_overflow = false) { tree base_object = base; struct iv *iv = XCNEW (struct iv); @@ -977,21 +978,24 @@ alloc_iv (tree base, tree step) iv->have_use_for = false; iv->use_id = 0; iv->ssa_name = NULL_TREE; + iv->no_overflow = no_overflow; return iv; } -/* Sets STEP and BASE for induction variable IV. */ +/* Sets STEP and BASE for induction variable IV. NO_OVERFLOW implies the IV + doesn't overflow. */ static void -set_iv (struct ivopts_data *data, tree iv, tree base, tree step) +set_iv (struct ivopts_data *data, tree iv, tree base, tree step, + bool no_overflow) { struct version_info *info = name_info (data, iv); gcc_assert (!info->iv); bitmap_set_bit (data->relevant, SSA_NAME_VERSION (iv)); - info->iv = alloc_iv (base, step); + info->iv = alloc_iv (base, step, no_overflow); info->iv->ssa_name = iv; } @@ -1013,37 +1017,19 @@ get_iv (struct ivopts_data *data, tree var) if (!bb || !flow_bb_inside_loop_p (data->current_loop, bb)) - set_iv (data, var, var, build_int_cst (type, 0)); + set_iv (data, var, var, build_int_cst (type, 0), true); } return name_info (data, var)->iv; } -/* Determines the step of a biv defined in PHI. Returns NULL if PHI does - not define a simple affine biv with nonzero step. */ - -static tree -determine_biv_step (gimple phi) -{ - struct loop *loop = gimple_bb (phi)->loop_father; - tree name = PHI_RESULT (phi); - affine_iv iv; - - if (virtual_operand_p (name)) - return NULL_TREE; - - if (!simple_iv (loop, loop, name, &iv, true)) - return NULL_TREE; - - return integer_zerop (iv.step) ? NULL_TREE : iv.step; -} - /* Finds basic ivs. */ static bool find_bivs (struct ivopts_data *data) { gimple phi; + affine_iv iv; tree step, type, base; bool found = false; struct loop *loop = data->current_loop; @@ -1056,10 +1042,16 @@ find_bivs (struct ivopts_data *data) if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi))) continue; - step = determine_biv_step (phi); - if (!step) + if (virtual_operand_p (PHI_RESULT (phi))) continue; + if (!simple_iv (loop, loop, PHI_RESULT (phi), &iv, true)) + continue; + + if (integer_zerop (iv.step)) + continue; + + step = iv.step; base = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop)); base = expand_simple_operations (base); if (contains_abnormal_ssa_name_p (base) @@ -1076,7 +1068,7 @@ find_bivs (struct ivopts_data *data) step = fold_convert (type, step); } - set_iv (data, PHI_RESULT (phi), base, step); + set_iv (data, PHI_RESULT (phi), base, step, iv.no_overflow); found = true; } @@ -1172,7 +1164,7 @@ find_givs_in_stmt (struct ivopts_data *data, gimple stmt) if (!find_givs_in_stmt_scev (data, stmt, &iv)) return; - set_iv (data, gimple_assign_lhs (stmt), iv.base, iv.step); + set_iv (data, gimple_assign_lhs (stmt), iv.base, iv.step, iv.no_overflow); } /* Finds general ivs in basic block BB. */ @@ -1584,6 +1576,7 @@ idx_find_step (tree base, tree *idx, void *data) { struct ifs_ivopts_data *dta = (struct ifs_ivopts_data *) data; struct iv *iv; + bool use_overflow_semantics = false; tree step, iv_base, iv_step, lbound, off; struct loop *loop = dta->ivopts_data->current_loop; @@ -1643,9 +1636,12 @@ idx_find_step (tree base, tree *idx, void *data) iv_base = iv->base; iv_step = iv->step; + if (iv->no_overflow && nowrap_type_p (TREE_TYPE (iv_step))) + use_overflow_semantics = true; + if (!convert_affine_scev (dta->ivopts_data->current_loop, sizetype, &iv_base, &iv_step, dta->stmt, - false)) + use_overflow_semantics)) { /* The index might wrap. */ return false; |