Skip to content

Commit

Permalink
refactor[venom]: refactor mem2var (vyperlang#4421)
Browse files Browse the repository at this point in the history
remove special cases which were necessary before introduction of
`palloca`. now they represent useless variable read/writes which are
safe to remove. results in removal of a few instructions on benchmark
contracts.

---------

Co-authored-by: Harry Kalogirou <[email protected]>
  • Loading branch information
charles-cooper and harkal authored Dec 26, 2024
1 parent c9d8f5b commit 7caa055
Showing 1 changed file with 26 additions and 25 deletions.
51 changes: 26 additions & 25 deletions vyper/venom/passes/mem2var.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,30 @@ def _mk_varname(self, varname: str):

def _process_alloca_var(self, dfg: DFGAnalysis, var: IRVariable):
"""
Process alloca allocated variable. If it is only used by mstore/mload/return
instructions, it is promoted to a stack variable. Otherwise, it is left as is.
Process alloca allocated variable. If it is only used by
mstore/mload/return instructions, it is promoted to a stack variable.
Otherwise, it is left as is.
"""
uses = dfg.get_uses(var)
if all([inst.opcode == "mload" for inst in uses]):
return
elif all([inst.opcode == "mstore" for inst in uses]):
if not all([inst.opcode in ["mstore", "mload", "return"] for inst in uses]):
return
elif all([inst.opcode in ["mstore", "mload", "return"] for inst in uses]):
var_name = self._mk_varname(var.name)
for inst in uses:
if inst.opcode == "mstore":
inst.opcode = "store"
inst.output = IRVariable(var_name)
inst.operands = [inst.operands[0]]
elif inst.opcode == "mload":
inst.opcode = "store"
inst.operands = [IRVariable(var_name)]
elif inst.opcode == "return":
bb = inst.parent
idx = len(bb.instructions) - 1
assert inst == bb.instructions[idx] # sanity
bb.insert_instruction(
IRInstruction("mstore", [IRVariable(var_name), inst.operands[1]]), idx
)

var_name = self._mk_varname(var.name)
var = IRVariable(var_name)
for inst in uses:
if inst.opcode == "mstore":
inst.opcode = "store"
inst.output = var
inst.operands = [inst.operands[0]]
elif inst.opcode == "mload":
inst.opcode = "store"
inst.operands = [var]
elif inst.opcode == "return":
bb = inst.parent
idx = len(bb.instructions) - 1
assert inst == bb.instructions[idx] # sanity
new_inst = IRInstruction("mstore", [var, inst.operands[1]])
bb.insert_instruction(new_inst, idx)

def _process_palloca_var(self, dfg: DFGAnalysis, palloca_inst: IRInstruction, var: IRVariable):
"""
Expand All @@ -70,16 +69,18 @@ def _process_palloca_var(self, dfg: DFGAnalysis, palloca_inst: IRInstruction, va
return

var_name = self._mk_varname(var.name)
var = IRVariable(var_name)

# some value given to us by the calling convention
palloca_inst.opcode = "mload"
palloca_inst.operands = [palloca_inst.operands[0]]
palloca_inst.output = IRVariable(var_name)
palloca_inst.output = var

for inst in uses:
if inst.opcode == "mstore":
inst.opcode = "store"
inst.output = IRVariable(var_name)
inst.output = var
inst.operands = [inst.operands[0]]
elif inst.opcode == "mload":
inst.opcode = "store"
inst.operands = [IRVariable(var_name)]
inst.operands = [var]

0 comments on commit 7caa055

Please sign in to comment.