From 957f92637d9093b3093fc39c274d7eaebdfd2f8d Mon Sep 17 00:00:00 2001 From: Hodan Date: Fri, 25 Oct 2024 15:09:00 +0200 Subject: [PATCH 1/3] used dfg instead of the different uses computation --- vyper/venom/analysis/dfg.py | 18 ++++++++++-------- vyper/venom/passes/sccp/sccp.py | 26 ++++++++------------------ 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/vyper/venom/analysis/dfg.py b/vyper/venom/analysis/dfg.py index 328ed47c72..255b9f0501 100644 --- a/vyper/venom/analysis/dfg.py +++ b/vyper/venom/analysis/dfg.py @@ -5,9 +5,10 @@ from vyper.venom.basicblock import IRInstruction, IRVariable from vyper.venom.function import IRFunction +from vyper.utils import OrderedSet class DFGAnalysis(IRAnalysis): - _dfg_inputs: dict[IRVariable, list[IRInstruction]] + _dfg_inputs: dict[IRVariable, OrderedSet[IRInstruction]] _dfg_outputs: dict[IRVariable, IRInstruction] def __init__(self, analyses_cache: IRAnalysesCache, function: IRFunction): @@ -16,19 +17,19 @@ def __init__(self, analyses_cache: IRAnalysesCache, function: IRFunction): self._dfg_outputs = dict() # return uses of a given variable - def get_uses(self, op: IRVariable) -> list[IRInstruction]: - return self._dfg_inputs.get(op, []) + def get_uses(self, op: IRVariable) -> OrderedSet[IRInstruction]: + return self._dfg_inputs.get(op, OrderedSet()) # the instruction which produces this variable. def get_producing_instruction(self, op: IRVariable) -> Optional[IRInstruction]: return self._dfg_outputs.get(op) def add_use(self, op: IRVariable, inst: IRInstruction): - uses = self._dfg_inputs.setdefault(op, []) - uses.append(inst) + uses = self._dfg_inputs.setdefault(op, OrderedSet()) + uses.add(inst) def remove_use(self, op: IRVariable, inst: IRInstruction): - uses = self._dfg_inputs.get(op, []) + uses: OrderedSet = self._dfg_inputs.get(op, OrderedSet()) uses.remove(inst) @property @@ -48,10 +49,11 @@ def analyze(self): res = inst.get_outputs() for op in operands: - inputs = self._dfg_inputs.setdefault(op, []) - inputs.append(inst) + inputs = self._dfg_inputs.setdefault(op, OrderedSet()) + inputs.add(inst) for op in res: # type: ignore + assert isinstance(op, IRVariable) self._dfg_outputs[op] = inst def as_graph(self) -> str: diff --git a/vyper/venom/passes/sccp/sccp.py b/vyper/venom/passes/sccp/sccp.py index 19d373f81a..437b3706d0 100644 --- a/vyper/venom/passes/sccp/sccp.py +++ b/vyper/venom/passes/sccp/sccp.py @@ -5,7 +5,7 @@ from vyper.exceptions import CompilerPanic, StaticAssertionException from vyper.utils import OrderedSet -from vyper.venom.analysis import CFGAnalysis, DominatorTreeAnalysis, IRAnalysesCache +from vyper.venom.analysis import CFGAnalysis, DominatorTreeAnalysis, DFGAnalysis, IRAnalysesCache from vyper.venom.basicblock import ( IRBasicBlock, IRInstruction, @@ -51,7 +51,8 @@ class SCCP(IRPass): fn: IRFunction dom: DominatorTreeAnalysis - uses: dict[IRVariable, OrderedSet[IRInstruction]] + dfg: DFGAnalysis + #uses: dict[IRVariable, OrderedSet[IRInstruction]] lattice: Lattice work_list: list[WorkListItem] cfg_in_exec: dict[IRBasicBlock, OrderedSet[IRBasicBlock]] @@ -67,7 +68,7 @@ def __init__(self, analyses_cache: IRAnalysesCache, function: IRFunction): def run_pass(self): self.fn = self.function self.dom = self.analyses_cache.request_analysis(DominatorTreeAnalysis) - self._compute_uses() + self.dfg = self.analyses_cache.request_analysis(DFGAnalysis) self._calculate_sccp(self.fn.entry) self._propagate_constants() @@ -75,6 +76,8 @@ def run_pass(self): self.analyses_cache.force_analysis(CFGAnalysis) self._fix_phi_nodes() + self.analyses_cache.invalidate_analysis(DFGAnalysis) + def _calculate_sccp(self, entry: IRBasicBlock): """ This method is the main entry point for the SCCP algorithm. It @@ -92,7 +95,7 @@ def _calculate_sccp(self, entry: IRBasicBlock): self.work_list.append(FlowWorkItem(dummy, entry)) # Initialize the lattice with TOP values for all variables - for v in self.uses.keys(): + for v in self.dfg._dfg_outputs: self.lattice[v] = LatticeEnum.TOP # Iterate over the work list until it is empty @@ -261,21 +264,8 @@ def _add_ssa_work_items(self, inst: IRInstruction): for target_inst in self._get_uses(inst.output): # type: ignore self.work_list.append(SSAWorkListItem(target_inst)) - def _compute_uses(self): - """ - This method computes the uses for each variable in the IR. - It iterates over the dominator tree and collects all the - instructions that use each variable. - """ - self.uses = {} - for bb in self.dom.dfs_walk: - for var, insts in bb.get_uses().items(): - self._get_uses(var).update(insts) - def _get_uses(self, var: IRVariable): - if var not in self.uses: - self.uses[var] = OrderedSet() - return self.uses[var] + return self.dfg.get_uses(var) def _propagate_constants(self): """ From 699e10dccc76803653cdb3046e08ec70415d6229 Mon Sep 17 00:00:00 2001 From: Hodan Date: Fri, 25 Oct 2024 15:15:20 +0200 Subject: [PATCH 2/3] removed _get_uses method --- vyper/venom/passes/sccp/sccp.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vyper/venom/passes/sccp/sccp.py b/vyper/venom/passes/sccp/sccp.py index 437b3706d0..8ff2e5fcc1 100644 --- a/vyper/venom/passes/sccp/sccp.py +++ b/vyper/venom/passes/sccp/sccp.py @@ -261,12 +261,9 @@ def _eval(self, inst) -> LatticeItem: return ret # type: ignore def _add_ssa_work_items(self, inst: IRInstruction): - for target_inst in self._get_uses(inst.output): # type: ignore + for target_inst in self.dfg.get_uses(inst.output): # type: ignore self.work_list.append(SSAWorkListItem(target_inst)) - def _get_uses(self, var: IRVariable): - return self.dfg.get_uses(var) - def _propagate_constants(self): """ This method iterates over the IR and replaces constant values From e945bf8a6b96a13da00d72d17e65f7793a5a74e0 Mon Sep 17 00:00:00 2001 From: Hodan Date: Fri, 25 Oct 2024 15:20:35 +0200 Subject: [PATCH 3/3] lint --- vyper/venom/analysis/dfg.py | 2 +- vyper/venom/passes/sccp/sccp.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/vyper/venom/analysis/dfg.py b/vyper/venom/analysis/dfg.py index 255b9f0501..f49b2ac6ac 100644 --- a/vyper/venom/analysis/dfg.py +++ b/vyper/venom/analysis/dfg.py @@ -1,11 +1,11 @@ from typing import Optional +from vyper.utils import OrderedSet from vyper.venom.analysis.analysis import IRAnalysesCache, IRAnalysis from vyper.venom.analysis.liveness import LivenessAnalysis from vyper.venom.basicblock import IRInstruction, IRVariable from vyper.venom.function import IRFunction -from vyper.utils import OrderedSet class DFGAnalysis(IRAnalysis): _dfg_inputs: dict[IRVariable, OrderedSet[IRInstruction]] diff --git a/vyper/venom/passes/sccp/sccp.py b/vyper/venom/passes/sccp/sccp.py index 8ff2e5fcc1..d85e09c9b4 100644 --- a/vyper/venom/passes/sccp/sccp.py +++ b/vyper/venom/passes/sccp/sccp.py @@ -5,7 +5,7 @@ from vyper.exceptions import CompilerPanic, StaticAssertionException from vyper.utils import OrderedSet -from vyper.venom.analysis import CFGAnalysis, DominatorTreeAnalysis, DFGAnalysis, IRAnalysesCache +from vyper.venom.analysis import CFGAnalysis, DFGAnalysis, DominatorTreeAnalysis, IRAnalysesCache from vyper.venom.basicblock import ( IRBasicBlock, IRInstruction, @@ -52,7 +52,6 @@ class SCCP(IRPass): fn: IRFunction dom: DominatorTreeAnalysis dfg: DFGAnalysis - #uses: dict[IRVariable, OrderedSet[IRInstruction]] lattice: Lattice work_list: list[WorkListItem] cfg_in_exec: dict[IRBasicBlock, OrderedSet[IRBasicBlock]]