From: Carl Friedrich Bolz-Tereick <cfbolz@gmx.de>
Date: Fri, 3 Mar 2023 14:15:42 +0100
Subject: Upstream: #3892: fix wrong assert in intutils,
 it should be an InvalidLoop instead

I introduced the assert in 5909f5e0a75c. before that, inconsistent intersects
would just do nothing, which I am not sure is a better solution than raising
InvalidLoop

Bug-Debian: https://bugs.debian.org/1062460
Origin: upstream, https://github.com/pypy/pypy/commit/ba8a3c45b9afe068c06780b4c34709c852ae20ea
---
 rpython/jit/metainterp/optimizeopt/intutils.py     |  8 +++++-
 .../metainterp/optimizeopt/test/test_intbound.py   |  5 ++--
 rpython/jit/metainterp/test/test_ajit.py           | 33 ++++++++++++++++++++++
 3 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py b/rpython/jit/metainterp/optimizeopt/intutils.py
index 381d0a2..e9ba7f7 100644
--- a/rpython/jit/metainterp/optimizeopt/intutils.py
+++ b/rpython/jit/metainterp/optimizeopt/intutils.py
@@ -129,7 +129,13 @@ class IntBound(AbstractInfo):
         return 0 <= self.lower
 
     def intersect(self, other):
-        assert not self.known_gt(other) and not self.known_lt(other)
+        from rpython.jit.metainterp.optimize import InvalidLoop
+        if self.known_gt(other) or self.known_lt(other):
+            # they don't overlap, which makes the loop invalid
+            # this never happens in regular linear traces, but it can happen in
+            # combination with unrolling/loop peeling
+            raise InvalidLoop("two integer ranges don't overlap")
+
         r = False
         if self.make_ge_const(other.lower):
             r = True
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
index d4a0db4..ea9b74c 100644
--- a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
@@ -225,13 +225,12 @@ def test_intersect():
                     assert not b.contains(n)
 
 def test_intersect_bug():
+    from rpython.jit.metainterp.optimize import InvalidLoop
     b1 = bound(17, 17)
     b2 = bound(1, 1)
-    with pytest.raises(AssertionError):
+    with pytest.raises(InvalidLoop):
         b1.intersect(b2)
 
-
-
 def test_add_bound():
     for _, _, b1 in some_bounds():
         for _, _, b2 in some_bounds():
diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py
index 29a8bf8..68e7d60 100644
--- a/rpython/jit/metainterp/test/test_ajit.py
+++ b/rpython/jit/metainterp/test/test_ajit.py
@@ -3256,6 +3256,39 @@ class BasicTests:
         res = self.interp_operations(f, [127 - 256 * 29])
         assert res == 127
 
+    def test_bug_inline_short_preamble_can_be_inconsistent_in_optimizeopt(self):
+        myjitdriver = JitDriver(greens = [], reds = "auto")
+        class Str(object):
+            _immutable_fields_ = ['s']
+            def __init__(self, s):
+                self.s = s
+
+        empty = Str("")
+        space = Str(" ")
+
+        def f(a, b):
+            line = " " * a + " a" * b
+            token = ""
+            res = []
+            index = 0
+            while True:
+                myjitdriver.jit_merge_point()
+                if index >= len(line):
+                    break
+                char = line[index]
+                index += 1
+                if char == space.s:
+                    if token != empty.s:
+                        res.append(token)
+                        token = empty.s
+                else:
+                    token += char
+            return len(res)
+        args = [50, 50]
+        res = self.meta_interp(f, args)
+        assert res == f(*args)
+
+
 class BaseLLtypeTests(BasicTests):
 
     def test_identityhash(self):
