> -----Original Message-----
> From: Richard Biener <[email protected]>
> Sent: 27 August 2026 12:03
> To: [email protected]
> Cc: Jakub Jelinek <[email protected]>; Tamar Christina
> <[email protected]>; [email protected]
> Subject: [PATCH] Remove -ftree-loop-if-convert, tie tree-if-conv.cc to
> vectorization only
>
> The following removes the ability to enable stand-alone loop if-conversion
> or to disable loop if-conversion even though vectorization runs. This
> was hardly useful before and testing and coverage of this mode is
> basically non-existent. Instead phiopt and cselimg are the general
> if-conversion vehicles.
>
> This will allow to more tightly integrate vectorizer loop if-conversion
> with loop vectorization.
>
> I have likely left some dead code removal on the plate and will followup
> with that if there's consensus on this.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu.
>
> There's a few more testcases using -ftree-loop-if-convert, I have
> left those untouched (but no more target specific testcases).
>
> Any comments?
>
> Thanks,
> Richard.
>
> * common.opt (ftree-loop-if-convert): Mark as ignored.
> * doc/invoke.texi (ftree-loop-if-convert): Remove.
> * tree-ssa-phiopt.cc (cond_if_else_store_replacement):
> Do not check !flag_tree_loop_if_convert.
> * tree-if-conv.cc (pass_if_conversion::gate): Only
> run when loop vectorization is enabled on any loop.
> (pass_if_conversion::execute): Adjust.
> (tree_if_conversion): Likewise. Simplify as we now
> always version.
>
> * gcc.dg/vect/bb-slp-pattern-2.c: Adjust.
> * gcc.target/i386/pr45685.c: Likewise.
> ---
>
> -/* { dg-final { scan-assembler-times "cmov" 6 } } */
> +/* { dg-final { scan-assembler-times "cmov" 6 { xfail *-*-* } } } */
> diff --git a/gcc/tree-if-conv.cc b/gcc/tree-if-conv.cc
> index 5d8abfb52b5..23b4e4cd63a 100644
> --- a/gcc/tree-if-conv.cc
> +++ b/gcc/tree-if-conv.cc
> @@ -4084,7 +4084,7 @@ tree_if_conversion (class loop *loop, vec<gimple *>
> *preds)
> bitmap exit_bbs;
> edge pe;
> auto_vec<data_reference_p, 10> refs;
> - bool loop_versioned;
> + class loop *vloop, *nloop;
>
> again:
> rloop = NULL;
> @@ -4094,7 +4094,6 @@ tree_if_conversion (class loop *loop, vec<gimple *>
> *preds)
> need_to_predicate = false;
> need_to_rewrite_undefined = false;
> any_complicated_phi = false;
> - loop_versioned = false;
>
> /* Apply more aggressive if-conversion when loop or its outer loop were
> marked with simd pragma. When that's the case, we try to if-convert
> @@ -4147,8 +4146,7 @@ tree_if_conversion (class loop *loop, vec<gimple *>
> *preds)
> }
> }
>
> - if ((flag_tree_loop_vectorize || loop->force_vectorize)
> - && !loop->dont_vectorize)
> + if (!loop->dont_vectorize)
> need_to_lower_bitfields = bitfields_to_lower_p (loop, reads_to_lower,
> writes_to_lower);
>
LGTM too FWIW, but is this check not redundant? Since in ::execute
tree_if_conversion won't be called anymore if loop->dont_vectorize no?
Thanks,
Tamar
> @@ -4158,28 +4156,21 @@ tree_if_conversion (class loop *loop, vec<gimple
> *> *preds)
> /* The edge to insert invariant stmts on. */
> pe = loop_preheader_edge (loop);
>
> - /* Since we have no cost model, always version loops unless the user
> - specified -ftree-loop-if-convert or unless versioning is required.
> + /* Since we have no cost model, always version loops.
> Either version this loop, or if the pattern is right for outer-loop
> vectorization, version the outer loop. In the latter case we will
> still if-convert the original inner loop. */
> - if (need_to_lower_bitfields
> - || need_to_predicate
> - || any_complicated_phi
> - || flag_tree_loop_if_convert != 1)
> - {
> - class loop *vloop
> - = (versionable_outer_loop_p (loop_outer (loop))
> + vloop = (versionable_outer_loop_p (loop_outer (loop))
> ? loop_outer (loop) : loop);
> - class loop *nloop = version_loop_for_if_conversion (vloop, preds);
> - if (nloop == NULL)
> - goto cleanup;
> - if (vloop != loop)
> - {
> - /* If versionable_outer_loop_p decided to version the
> - outer loop, version also the inner loop of the non-vectorized
> - loop copy. So we transform:
> - loop1
> + nloop = version_loop_for_if_conversion (vloop, preds);
> + if (nloop == NULL)
> + goto cleanup;
> + if (vloop != loop)
> + {
> + /* If versionable_outer_loop_p decided to version the
> + outer loop, version also the inner loop of the non-vectorized
> + loop copy. So we transform:
> + loop1
> loop2
> into:
> if (LOOP_VECTORIZED (1, 3))
> @@ -4193,18 +4184,15 @@ tree_if_conversion (class loop *loop, vec<gimple
> *> *preds)
> loop4 (copy of loop2)
> else
> loop5 (copy of loop4) */
> - gcc_assert (nloop->inner && nloop->inner->next == NULL);
> - rloop = nloop->inner;
> - }
> - else
> - /* If we versioned loop then make sure to insert invariant
> - stmts before the .LOOP_VECTORIZED check since the vectorizer
> - will re-use that for things like runtime alias versioning
> - whose condition can end up using those invariants. */
> - pe = single_pred_edge (gimple_bb (preds->last ()));
> -
> - loop_versioned = true;
> + gcc_assert (nloop->inner && nloop->inner->next == NULL);
> + rloop = nloop->inner;
> }
> + else
> + /* If we versioned loop then make sure to insert invariant
> + stmts before the .LOOP_VECTORIZED check since the vectorizer
> + will re-use that for things like runtime alias versioning
> + whose condition can end up using those invariants. */
> + pe = single_pred_edge (gimple_bb (preds->last ()));
>
> if (need_to_lower_bitfields)
> {
> @@ -4236,7 +4224,7 @@ tree_if_conversion (class loop *loop, vec<gimple *>
> *preds)
> /* Now all statements are if-convertible. Combine all the basic
> blocks into one huge basic block doing the if-conversion
> on-the-fly. */
> - combine_blocks (loop, loop_versioned);
> + combine_blocks (loop, true);
> }
>
> std::pair <tree, tree> *name_pair;
> @@ -4327,9 +4315,7 @@ public:
> bool
> pass_if_conversion::gate (function *fun)
> {
> - return (((flag_tree_loop_vectorize || fun->has_force_vectorize_loops)
> - && flag_tree_loop_if_convert != 0)
> - || flag_tree_loop_if_convert == 1);
> + return flag_tree_loop_vectorize || fun->has_force_vectorize_loops;
> }
>
> unsigned int
> @@ -4342,9 +4328,8 @@ pass_if_conversion::execute (function *fun)
>
> auto_vec<gimple *> preds;
> for (auto loop : loops_list (cfun, 0))
> - if (flag_tree_loop_if_convert == 1
> - || ((flag_tree_loop_vectorize || loop->force_vectorize)
> - && !loop->dont_vectorize))
> + if ((flag_tree_loop_vectorize || loop->force_vectorize)
> + && !loop->dont_vectorize)
> todo |= tree_if_conversion (loop, &preds);
>
> if (todo)
> diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
> index f8dbd26abc1..fd9aa2bedb4 100644
> --- a/gcc/tree-ssa-phiopt.cc
> +++ b/gcc/tree-ssa-phiopt.cc
> @@ -3947,8 +3947,7 @@ cond_if_else_store_replacement (basic_block
> then_bb, basic_block else_bb,
> /* If either vectorization or if-conversion is disabled then do
> not sink any stores. */
> if (param_max_stores_to_sink == 0
> - || (!flag_tree_loop_vectorize && !flag_tree_slp_vectorize)
> - || !flag_tree_loop_if_convert)
> + || (!flag_tree_loop_vectorize && !flag_tree_slp_vectorize))
> return false;
>
> /* Find data references. */
> --
> 2.51.0