Skip to content

Commit

Permalink
fix[venom]: move loop invariant assertion to entry block (vyperlang#4098
Browse files Browse the repository at this point in the history
)

loop invariant bound check was in the body of the loop, not the entry
block. move it up to the entry so we don't re-check the same assertion
every loop iteration.
  • Loading branch information
charles-cooper committed Jun 10, 2024
1 parent 24cfe0b commit 4d1bacd
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 14 deletions.
4 changes: 2 additions & 2 deletions tests/functional/syntax/test_for_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,14 +368,14 @@ def foo():
"""
@external
def foo():
x: int128 = 5
x: int128 = 4
for i: int128 in range(x, bound=4):
pass
""",
"""
@external
def foo():
x: int128 = 5
x: int128 = 4
for i: int128 in range(0, x, bound=4):
pass
""",
Expand Down
20 changes: 8 additions & 12 deletions vyper/venom/ir_node_to_venom.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,14 +468,7 @@ def emit_body_blocks():
start, end, _ = _convert_ir_bb_list(fn, ir.args[1:4], symbols)

assert ir.args[3].is_literal, "repeat bound expected to be literal"

bound = ir.args[3].value
if (
isinstance(end, IRLiteral)
and isinstance(start, IRLiteral)
and end.value + start.value <= bound
):
bound = None

body = ir.args[4]

Expand All @@ -491,19 +484,22 @@ def emit_body_blocks():

counter_var = entry_block.append_instruction("store", start)
symbols[sym.value] = counter_var

if bound is not None:
# assert le end bound
invalid_end = entry_block.append_instruction("gt", bound, end)
valid_end = entry_block.append_instruction("iszero", invalid_end)
entry_block.append_instruction("assert", valid_end)

end = entry_block.append_instruction("add", start, end)
if bound:
bound = entry_block.append_instruction("add", start, bound)

entry_block.append_instruction("jmp", cond_block.label)

xor_ret = cond_block.append_instruction("xor", counter_var, end)
cont_ret = cond_block.append_instruction("iszero", xor_ret)
fn.append_basic_block(cond_block)

fn.append_basic_block(body_block)
if bound:
xor_ret = body_block.append_instruction("xor", counter_var, bound)
body_block.append_instruction("assert", xor_ret)

emit_body_blocks()
body_end = fn.get_basic_block()
Expand Down

0 comments on commit 4d1bacd

Please sign in to comment.