Commit 1b7535e2 authored by Carl Friedrich Bolz-Tereick's avatar Carl Friedrich Bolz-Tereick
Browse files

(cfbolz, mattip around, arigo around): unbreak b38599cd5da0: we can't just

remove get_box_replacement here, that has wrong effects down the line, issue
#3867

unfortunately this means that the original bug is back, in some forms. that
needs a bigger refactoring and some more conceptual thinking though (the bug is
somewhat theoretical though, it can only happens if you use __pypy__.intop)
parent 09d451a5967f
Pipeline #59326 passed with stage
in 7 minutes and 49 seconds
......@@ -73,7 +73,7 @@ class RecentPureOps(object):
box1.same_box(get_box_replacement(op.getarg(1))) and
op.getdescr() is descr):
op = self.force_preamble_op(opt, op, i)
return op
return get_box_replacement(op)
return None
def lookup(self, optimizer, op):
......@@ -136,9 +136,8 @@ class OptPure(Optimization):
save = True
if recentops is not None:
oldop = recentops.lookup(self.optimizer, op)
# careful! if this is an ovf operation we can only re-use the
# result of a prior ovf operation (the other direction is fine)
if oldop is not None and (not ovf or oldop.opnum == op.opnum):
if oldop is not None and self._can_reuse_oldop(
recentops, oldop, op, ovf):
self.optimizer.make_equal_to(op, oldop)
return
......@@ -148,6 +147,17 @@ class OptPure(Optimization):
return self.emit(op)
return self.emit_result(DefaultOptimizationResult(self, op, save, nextop))
def _can_reuse_oldop(self, recentops, oldop, op, ovf):
if ovf:
# careful! this is an ovf operation. so we can only
# re-use the result of a prior ovf operation, but not a
# regular int_... up, because that might have
# overflowed (the other direction is fine). therefore
# we need to check that the previous op and the current
# op have the same opnum.
return isinstance(oldop, AbstractResOp) and oldop.opnum == op.opnum
return True
def getrecentops(self, opnum, create=True):
if rop._OVF_FIRST <= opnum <= rop._OVF_LAST:
opnum = opnum - rop._OVF_FIRST
......
......@@ -1970,7 +1970,17 @@ class TestOptimizeIntBounds(BaseTestBasic):
"""
self.optimize_loop(ops, expected)
def test_pure_ovf_bug(self):
def test_pure_ovf_bug_simple(self):
ops = """
[i1, i2]
i3 = int_add(i2, i1)
i4 = int_add_ovf(i2, i1)
guard_no_overflow() []
jump(i4)
"""
self.optimize_loop(ops, ops)
def test_pure_ovf_bug_with_replacement(self):
ops = """
[i1, i2]
i3 = int_add(i2, i1)
......@@ -1980,6 +1990,44 @@ class TestOptimizeIntBounds(BaseTestBasic):
"""
self.optimize_loop(ops, ops)
@pytest.mark.xfail() # this test is wrong! it fails in Z3
def test_pure_ovf_bug_with_arithmetic_rewrites(self):
ops = """
[i1, i2]
i3 = int_add_ovf(i1, i2)
guard_no_overflow() []
i4 = int_sub_ovf(i3, i2)
guard_no_overflow() []
jump(i4)
"""
result = """
[i1, i2]
i3 = int_add_ovf(i1, i2)
guard_no_overflow() []
jump(i1)
"""
self.optimize_loop(ops, result)
@pytest.mark.xfail() # this test is wrong! it fails in Z3
def test_pure_ovf_bug_with_replacement(self):
ops = """
[i0, i1, i10, i11]
i2 = int_sub_ovf(i0, i1)
guard_no_overflow() []
i3 = int_add(i2, i11)
i4 = int_sub_ovf(i3, i11)
guard_no_overflow() []
jump(i4)
"""
result = """
[i0, i1, i10, i11]
i2 = int_sub_ovf(i0, i1)
guard_no_overflow() []
i3 = int_add(i2, i11)
jump(i2)
"""
self.optimize_loop(ops, result)
def test_intdiv_bounds(self):
ops = """
[i0, i1]
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment