https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122755
--- Comment #1 from Di Zhao <dizhao at os dot amperecomputing.com> ---
The tiny case can be optimized with the following change:
--- a/gcc/tree-ssa-loop-split.cc
+++ b/gcc/tree-ssa-loop-split.cc
@@ -1273,6 +1273,12 @@ control_dep_semi_invariant_p (struct loop *loop,
basic_block bb,
&& gimple_code (last) != GIMPLE_SWITCH)
return false;
+ /* The other edge of GIMPLE_COND is loop exit, so there is no chance
+ for it to change the result of COND_EXPRs in BB. */
+ if (gimple_code (last) == GIMPLE_COND
+ && loop_exits_from_bb_p (loop, pred))
+ continue;
+
if (!stmt_semi_invariant_p_1 (loop, last, skip_head, stmt_stat))
return false;
}
@@ -1468,9 +1474,12 @@ get_cond_invariant_branch (struct loop *loop, gcond
*cond)
invar_checks++;
}
- /* With both branches being invariant (handled by loop unswitch) or
- variant is not what we want. */
- if (invar[0] ^ !invar[1])
+ /* Variant is not what we want.
+
+ Since lsplit doesn't assume define statement of loop-invarient to be
+ (lifted) outside the loop, it is possible to recognize opportunities
+ that loop unswitch missed. No harm splitting the loop here. */
+ if (!invar[0] && !invar[1])
return NULL;
/* Found a real loop-invariant condition, do nothing. */
This can be further improved to optimize more general cases, for example,
the current GCC sccvn code has another conditional statement before calling
dominated_by_p.