Skip to content

Commit dcc230c

Browse files
chore: improve optimizer rules for comparison operators (#3412)
after this commit, safe add between anything and 0 results in a no-op.
1 parent 3f70dd2 commit dcc230c

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

tests/compiler/ir/test_optimize_ir.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@
5757
(["le", 0, "x"], [1]),
5858
(["le", 0, ["sload", 0]], None), # no-op
5959
(["ge", "x", 0], [1]),
60+
(["le", "x", "x"], [1]),
61+
(["ge", "x", "x"], [1]),
62+
(["sle", "x", "x"], [1]),
63+
(["sge", "x", "x"], [1]),
64+
(["lt", "x", "x"], [0]),
65+
(["gt", "x", "x"], [0]),
66+
(["slt", "x", "x"], [0]),
67+
(["sgt", "x", "x"], [0]),
6068
# boundary conditions
6169
(["slt", "x", -(2**255)], [0]),
6270
(["sle", "x", -(2**255)], ["eq", "x", -(2**255)]),
@@ -253,3 +261,10 @@ def test_ir_optimizer(ir):
253261
def test_static_assertions(ir, assert_compile_failed):
254262
ir = IRnode.from_list(ir)
255263
assert_compile_failed(lambda: optimizer.optimize(ir), StaticAssertionException)
264+
265+
266+
def test_operator_set_values():
267+
# some sanity checks
268+
assert optimizer.COMPARISON_OPS == {"lt", "gt", "le", "ge", "slt", "sgt", "sle", "sge"}
269+
assert optimizer.STRICT_COMPARISON_OPS == {"lt", "gt", "slt", "sgt"}
270+
assert optimizer.UNSTRICT_COMPARISON_OPS == {"le", "ge", "sle", "sge"}

vyper/ir/optimizer.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ def _deep_contains(node_or_list, node):
7878

7979
COMMUTATIVE_OPS = {"add", "mul", "eq", "ne", "and", "or", "xor"}
8080
COMPARISON_OPS = {"gt", "sgt", "ge", "sge", "lt", "slt", "le", "sle"}
81+
STRICT_COMPARISON_OPS = {t for t in COMPARISON_OPS if t.endswith("t")}
82+
UNSTRICT_COMPARISON_OPS = {t for t in COMPARISON_OPS if t.endswith("e")}
83+
84+
assert not (STRICT_COMPARISON_OPS & UNSTRICT_COMPARISON_OPS)
85+
assert STRICT_COMPARISON_OPS | UNSTRICT_COMPARISON_OPS == COMPARISON_OPS
8186

8287

8388
def _flip_comparison_op(opname):
@@ -256,11 +261,15 @@ def _conservative_eq(x, y):
256261
return finalize("seq", [args[0]])
257262

258263
if binop in {"sub", "xor", "ne"} and _conservative_eq(args[0], args[1]):
259-
# x - x == x ^ x == x != x == 0
264+
# (x - x) == (x ^ x) == (x != x) == 0
265+
return finalize(0, [])
266+
267+
if binop in STRICT_COMPARISON_OPS and _conservative_eq(args[0], args[1]):
268+
# (x < x) == (x > x) == 0
260269
return finalize(0, [])
261270

262-
if binop == "eq" and _conservative_eq(args[0], args[1]):
263-
# (x == x) == 1
271+
if binop in {"eq"} | UNSTRICT_COMPARISON_OPS and _conservative_eq(args[0], args[1]):
272+
# (x == x) == (x >= x) == (x <= x) == 1
264273
return finalize(1, [])
265274

266275
# TODO associativity rules

0 commit comments

Comments
 (0)