diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 3faed93..adc28aa 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -3035,6 +3035,27 @@ add_standard_iv_candidates (struct ivopts_data *data) build_int_cst (long_long_integer_type_node, 1), true, NULL); } +/* Return true if STMT is the increment stmt for a biv. BEFORE and AFTER + are the corresponding vars before and after increment. */ + +static bool +increment_stmt_for_biv_p (gimple *stmt, tree before, tree after) +{ + enum tree_code code; + + gcc_assert (is_gimple_assign (stmt)); + gcc_assert (gimple_assign_lhs (stmt) == after); + + code = gimple_assign_rhs_code (stmt); + if (code != PLUS_EXPR && code != MINUS_EXPR && code != POINTER_PLUS_EXPR) + return false; + + if (gimple_assign_rhs1 (stmt) != before + && gimple_assign_rhs2 (stmt) != before) + return false; + + return true; +} /* Adds candidates bases on the old induction variable IV. */ @@ -3078,7 +3099,11 @@ add_iv_candidate_for_biv (struct ivopts_data *data, struct iv *iv) /* Don't add candidate if it's from another PHI node because it's an affine iv appearing in the form of PEELED_CHREC. */ phi = SSA_NAME_DEF_STMT (def); - if (gimple_code (phi) != GIMPLE_PHI) + if (gimple_code (phi) == GIMPLE_PHI) + gcc_assert (gimple_bb (phi) == data->current_loop->header); + /* Don't add candidate if we don't know where biv's increment + stmt is. */ + else if (increment_stmt_for_biv_p (phi, iv->ssa_name, def)) { cand = add_candidate_1 (data, iv->base, iv->step, true, IP_ORIGINAL, NULL, @@ -3086,8 +3111,6 @@ add_iv_candidate_for_biv (struct ivopts_data *data, struct iv *iv) cand->var_before = iv->ssa_name; cand->var_after = def; } - else - gcc_assert (gimple_bb (phi) == data->current_loop->header); } } @@ -7053,20 +7076,14 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data, if (cand->pos == IP_ORIGINAL && cand->incremented_at == use->stmt) { - enum tree_code stmt_code; - - gcc_assert (is_gimple_assign (use->stmt)); - gcc_assert (gimple_assign_lhs (use->stmt) == cand->var_after); - /* Check whether we may leave the computation unchanged. This is the case only if it does not rely on other computations in the loop -- otherwise, the computation we rely upon may be removed in remove_unused_ivs, thus leading to ICE. */ - stmt_code = gimple_assign_rhs_code (use->stmt); - if (stmt_code == PLUS_EXPR - || stmt_code == MINUS_EXPR - || stmt_code == POINTER_PLUS_EXPR) + if (increment_stmt_for_biv_p (use->stmt, + cand->var_before, + cand->var_after)) { if (gimple_assign_rhs1 (use->stmt) == cand->var_before) op = gimple_assign_rhs2 (use->stmt); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68021.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68021.c new file mode 100644 index 0000000..f60b1ff --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr68021.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +char a; +void fn1 (char *p1, int p2, int p3) +{ + int i, x; + for (i = 0; i < 10; i++) + { + for (x = 0; x < p3; x++) + { + *p1 = a; + p1--; + } + p1 += p2; + } +}