Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unroll local var loop #1

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 64 additions & 19 deletions vyper/parser/self_call.py
Expand Up @@ -82,36 +82,81 @@ def call_self_private(stmt_expr, context, sig):
push_args = []

# Push local variables.
# use a partially unrolled loop
if context.vars:
var_slots = [(v.pos, v.size) for name, v in context.vars.items()]
var_slots.sort(key=lambda x: x[0])
mem_from, mem_to = var_slots[0][0], var_slots[-1][0] + var_slots[-1][1] * 32
mem_from = var_slots[0][0]
mem_to = var_slots[-1][0] + var_slots[-1][1] * 32

LOOP_UNROLL_SIZE = 8
WORD = 32 # TODO make this global constant
LOOP_UNROLL_BYTES = LOOP_UNROLL_SIZE * WORD

mem_to_aligned = mem_to - (mem_to - mem_from) % LOOP_UNROLL_BYTES

i_placeholder = context.new_placeholder(BaseType('uint256'))
local_save_ident = "_%d_%d" % (stmt_expr.lineno, stmt_expr.col_offset)
push_loop_label = 'save_locals_start' + local_save_ident
pop_loop_label = 'restore_locals_start' + local_save_ident

if mem_to - mem_from > 320:
push_local_vars = [
push_local_vars = []
pop_local_vars = []

# mstores happen in reverse
for pos in reversed(range(mem_to_aligned, mem_to, WORD)):
pop_local_vars.append(['mstore', pos, 'pass'])

if mem_to - mem_from >= LOOP_UNROLL_BYTES:

###
# back up locals routine
loop_start = [
['mstore', i_placeholder, mem_from],
['label', push_loop_label],
['label', push_loop_label]]

unroll_mloads = []
for _ in range(LOOP_UNROLL_SIZE):
unroll_mloads.extend([
['mload', ['mload', i_placeholder]],
['mstore', i_placeholder, ['add', ['mload', i_placeholder], 32]],
['if', ['lt', ['mload', i_placeholder], mem_to],
['goto', push_loop_label]]
]
pop_local_vars = [
['mstore', i_placeholder, mem_to - 32],
['label', pop_loop_label],
['mstore', ['mload', i_placeholder], 'pass'],
['mstore', i_placeholder, ['sub', ['mload', i_placeholder], 32]],
['if', ['ge', ['mload', i_placeholder], mem_from],
['goto', pop_loop_label]]
]
else:
push_local_vars = [['mload', pos] for pos in range(mem_from, mem_to, 32)]
pop_local_vars = [['mstore', pos, 'pass'] for pos in range(mem_to-32, mem_from-32, -32)]
['mstore', i_placeholder, ['add', ['mload', i_placeholder], WORD]]])

loop_condition = \
[['if', ['ne', ['mload', i_placeholder], mem_to_aligned],
['goto', push_loop_label]]]

loop_body = ['seq_unchecked'] + \
loop_start + \
unroll_mloads + \
loop_condition

push_local_vars.append(loop_body)

###
# restore local variables routine
loop_start = [
['mstore', i_placeholder, mem_to_aligned],
['label', pop_loop_label]]

unroll_mstores = []
for _ in range(LOOP_UNROLL_SIZE):
unroll_mstores.extend([
['mstore', i_placeholder, ['sub', ['mload', i_placeholder], WORD]],
['mstore', ['mload', i_placeholder], 'pass']])

loop_condition = [
['if', ['ne', ['mload', i_placeholder], mem_from],
['goto', pop_loop_label]]]

loop_body = ['seq_unchecked'] + \
loop_start + \
unroll_mstores + \
loop_condition

pop_local_vars.append(loop_body)

for pos in range(mem_to_aligned, mem_to, WORD):
push_local_vars.append(['mload', pos])

# Push Arguments
if expr_args:
Expand Down