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.

Reply via email to