https://gcc.gnu.org/g:e55de74d50d236db0472431fe242f3244e41b884

commit r16-7431-ge55de74d50d236db0472431fe242f3244e41b884
Author: Richard Biener <[email protected]>
Date:   Tue Feb 10 09:46:08 2026 +0100

    tree-optimization/107690 - avoid creating un-analyzable loop exits
    
    The following adds a heuristic to ifcombine that avoids turning
    analyzable loop exits into unanalyzable ones.  This allows vectorizing
    the testcase in the PR again.  I've refrained from actually
    analyzing niters but instead used a cheaper heuristic.  I believe
    we'll only ever attempt to combine two ifs if they are in the same
    loop and if either both exit the loop or stay within.
    
            PR tree-optimization/107690
            * tree-ssa-ifcombine.cc (ifcombine_ifandif): Do not merge
            possibly analyzable exit conditions.
    
            * g++.dg/vect/vect-pr107690.cc: New testcase.

Diff:
---
 gcc/testsuite/g++.dg/vect/vect-pr107690.cc | 16 ++++++++++++++++
 gcc/tree-ssa-ifcombine.cc                  | 16 ++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/gcc/testsuite/g++.dg/vect/vect-pr107690.cc 
b/gcc/testsuite/g++.dg/vect/vect-pr107690.cc
new file mode 100644
index 000000000000..847dbca5f62d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/vect-pr107690.cc
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-require-effective-target vect_int }
+// { dg-additional-options "-std=gnu++20" }
+
+#include <algorithm>
+#include <array>
+#include <ranges>
+
+std::array<int, 16> foo(std::array<int, 16> u, std::array<int, 16> const &v)
+{
+  std::ranges::transform(u, v, u.begin(), std::plus<int>());
+  return u;
+}
+
+// { dg-final { scan-tree-dump "optimized: loop vectorized" "vect" } }
+// { dg-final { scan-tree-dump-not "Loop being analyzed as uncounted" "vect" } 
}
diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
index 7769118b9f6e..a60e6914e68c 100644
--- a/gcc/tree-ssa-ifcombine.cc
+++ b/gcc/tree-ssa-ifcombine.cc
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "attribs.h"
 #include "asan.h"
 #include "bitmap.h"
+#include "cfgloop.h"
 
 #ifndef LOGICAL_OP_NON_SHORT_CIRCUIT
 #define LOGICAL_OP_NON_SHORT_CIRCUIT \
@@ -818,6 +819,21 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
   if (!outer_cond)
     return false;
 
+  /* niter analysis does not cope with boolean typed loop exit conditions.
+     Avoid turning an analyzable exit into an unanalyzable one.  */
+  if (inner_cond_bb->loop_father == outer_cond_bb->loop_father
+      && loop_exits_from_bb_p (inner_cond_bb->loop_father, inner_cond_bb)
+      && loop_exits_from_bb_p (outer_cond_bb->loop_father, outer_cond_bb))
+    {
+      tree outer_type = TREE_TYPE (gimple_cond_lhs (outer_cond));
+      tree inner_type = TREE_TYPE (gimple_cond_lhs (inner_cond));
+      if (TREE_CODE (outer_type) == INTEGER_TYPE
+         || POINTER_TYPE_P (outer_type)
+         || TREE_CODE (inner_type) == INTEGER_TYPE
+         || POINTER_TYPE_P (inner_type))
+       return false;
+    }
+
   /* See if we test a single bit of the same name in both tests.  In
      that case remove the outer test, merging both else edges,
      and change the inner one to test for

Reply via email to