Skip to content

Commit def0b1c

Browse files
Merge branch 'master' into fix/offset-operand-order
2 parents fac3cc2 + b3ea663 commit def0b1c

File tree

5 files changed

+46
-9
lines changed

5 files changed

+46
-9
lines changed

tests/unit/compiler/venom/test_algebraic_optimizer.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pytest
22

3+
import vyper
34
from vyper.venom.analysis import IRAnalysesCache
45
from vyper.venom.basicblock import IRBasicBlock, IRLabel
56
from vyper.venom.context import IRContext
@@ -176,3 +177,29 @@ def test_offsets():
176177
offset_count += 1
177178

178179
assert offset_count == 3
180+
181+
182+
# Test the case of https://github.com/vyperlang/vyper/issues/4288
183+
def test_ssa_after_algebraic_optimization():
184+
code = """
185+
@internal
186+
def _do_math(x: uint256) -> uint256:
187+
value: uint256 = x
188+
result: uint256 = 0
189+
190+
if (x >> 128 != 0):
191+
x >>= 128
192+
if (x >> 64 != 0):
193+
x >>= 64
194+
195+
if 1 < value:
196+
result = 1
197+
198+
return result
199+
200+
@external
201+
def run() -> uint256:
202+
return self._do_math(10)
203+
"""
204+
205+
vyper.compile_code(code, output_formats=["bytecode"])

vyper/venom/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ def _run_passes(fn: IRFunction, optimize: OptimizationLevel) -> None:
5555
StoreElimination(ac, fn).run_pass()
5656
SimplifyCFGPass(ac, fn).run_pass()
5757
AlgebraicOptimizationPass(ac, fn).run_pass()
58+
# NOTE: MakeSSA is after algebraic optimization it currently produces
59+
# smaller code by adding some redundant phi nodes. This is not a
60+
# problem for us, but we need to be aware of it, and should be
61+
# removed when the dft pass is fixed to produce the smallest code
62+
# without making the code generation more expensive by running
63+
# MakeSSA again.
64+
MakeSSA(ac, fn).run_pass()
5865
BranchOptimizationPass(ac, fn).run_pass()
5966
RemoveUnusedVariablesPass(ac, fn).run_pass()
6067

vyper/venom/analysis/cfg.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ def analyze(self) -> None:
3232
in_bb.add_cfg_out(bb)
3333

3434
def invalidate(self):
35-
from vyper.venom.analysis import DominatorTreeAnalysis, LivenessAnalysis
35+
from vyper.venom.analysis import DFGAnalysis, DominatorTreeAnalysis, LivenessAnalysis
3636

3737
self.analyses_cache.invalidate_analysis(DominatorTreeAnalysis)
3838
self.analyses_cache.invalidate_analysis(LivenessAnalysis)
39+
40+
# be conservative - assume cfg invalidation invalidates dfg
41+
self.analyses_cache.invalidate_analysis(DFGAnalysis)

vyper/venom/passes/sccp/sccp.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,19 +332,18 @@ def _replace_constants(self, inst: IRInstruction):
332332
def _fix_phi_nodes(self):
333333
# fix basic blocks whose cfg in was changed
334334
# maybe this should really be done in _visit_phi
335-
needs_sort = False
336-
337335
for bb in self.fn.get_basic_blocks():
338336
cfg_in_labels = OrderedSet(in_bb.label for in_bb in bb.cfg_in)
339337

338+
needs_sort = False
340339
for inst in bb.instructions:
341340
if inst.opcode != "phi":
342341
break
343342
needs_sort |= self._fix_phi_inst(inst, cfg_in_labels)
344343

345-
# move phi instructions to the top of the block
346-
if needs_sort:
347-
bb.instructions.sort(key=lambda inst: inst.opcode != "phi")
344+
# move phi instructions to the top of the block
345+
if needs_sort:
346+
bb.instructions.sort(key=lambda inst: inst.opcode != "phi")
348347

349348
def _fix_phi_inst(self, inst: IRInstruction, cfg_in_labels: OrderedSet):
350349
operands = [op for label, op in inst.phi_operands if label in cfg_in_labels]

vyper/venom/passes/store_elimination.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,17 @@ def run_pass(self):
2727
self.analyses_cache.invalidate_analysis(LivenessAnalysis)
2828
self.analyses_cache.invalidate_analysis(DFGAnalysis)
2929

30-
def _process_store(self, dfg, inst, var, new_var):
30+
def _process_store(self, dfg, inst, var: IRVariable, new_var: IRVariable):
3131
"""
3232
Process store instruction. If the variable is only used by a load instruction,
3333
forward the variable to the load instruction.
3434
"""
35-
uses = dfg.get_uses(var)
35+
if any([inst.opcode == "phi" for inst in dfg.get_uses(new_var)]):
36+
return
3637

38+
uses = dfg.get_uses(var)
3739
if any([inst.opcode == "phi" for inst in uses]):
3840
return
39-
4041
for use_inst in uses:
4142
for i, operand in enumerate(use_inst.operands):
4243
if operand == var:

0 commit comments

Comments
 (0)