diff --git a/vyper/venom/basicblock.py b/vyper/venom/basicblock.py index 19e24e5a1e..89d3094b61 100644 --- a/vyper/venom/basicblock.py +++ b/vyper/venom/basicblock.py @@ -190,6 +190,13 @@ def __init__(self, name: str, version: int = 0) -> None: value = f"{name}:{version}" super().__init__(value) + def with_version(self, version: int) -> "IRVariable": + if version == self.version: + # IRVariable ctor is a hotspot, try to avoid calling it + # if possible + return self + return self.__class__(self.name, version) + @property def name(self) -> str: return self._name diff --git a/vyper/venom/passes/make_ssa.py b/vyper/venom/passes/make_ssa.py index d2a0ab4408..6b404da407 100644 --- a/vyper/venom/passes/make_ssa.py +++ b/vyper/venom/passes/make_ssa.py @@ -69,6 +69,11 @@ def _place_phi(self, var: IRVariable, basic_block: IRBasicBlock): basic_block.insert_instruction(IRInstruction("phi", args, var), 0) + def latest_version_of(self, var: IRVariable) -> IRVariable: + name = var.name + version = self.var_name_stacks[name][-1] + return var.with_version(version) + def _rename_vars(self, basic_block: IRBasicBlock): """ Rename variables. This follows the placement of phi nodes. @@ -84,7 +89,8 @@ def _rename_vars(self, basic_block: IRBasicBlock): new_ops.append(op) continue - new_ops.append(IRVariable(op.name, version=self.var_name_stacks[op.name][-1])) + op = self.latest_version_of(op) + new_ops.append(op) inst.operands = new_ops @@ -95,7 +101,7 @@ def _rename_vars(self, basic_block: IRBasicBlock): self.var_name_stacks[v_name].append(i) self.var_name_counters[v_name] = i + 1 - inst.output = IRVariable(v_name, version=i) + inst.output = self.latest_version_of(inst.output) outs.append(inst.output.name) for bb in basic_block.cfg_out: @@ -106,9 +112,7 @@ def _rename_vars(self, basic_block: IRBasicBlock): for i, op in enumerate(inst.operands): if op == basic_block.label: var = inst.operands[i + 1] - inst.operands[i + 1] = IRVariable( - var.name, version=self.var_name_stacks[var.name][-1] - ) + inst.operands[i + 1] = self.latest_version_of(var) for bb in self.dom.dominated[basic_block]: if bb == basic_block: