diff --git a/tests/unit/compiler/venom/test_sccp_algebraic.py b/tests/unit/compiler/venom/test_sccp_algebraic.py index 1103363314..875dce6b97 100644 --- a/tests/unit/compiler/venom/test_sccp_algebraic.py +++ b/tests/unit/compiler/venom/test_sccp_algebraic.py @@ -8,7 +8,6 @@ RemoveUnusedVariablesPass, StoreElimination, ) -from vyper.venom.passes.sccp.eval import signed_to_unsigned """ Test abstract binop+unop optimizations in sccp and algebraic optimizations pass @@ -380,7 +379,7 @@ def test_comparison_almost_never(): max_uint256 = 2**256 - 1 max_int256 = 2**255 - 1 - min_int256 = 2**255 + min_int256 = -(2**255) pre = f""" _global: %par = param @@ -418,7 +417,7 @@ def test_comparison_almost_always(): max_uint256 = 2**256 - 1 max_int256 = 2**255 - 1 - min_int256 = 2**255 + min_int256 = -(2**255) pre = f""" _global: @@ -466,15 +465,15 @@ def test_comparison_ge_le(val): up = val + 1 down = val - 1 - val = signed_to_unsigned(val, 256) - up = signed_to_unsigned(up, 256) - down = signed_to_unsigned(down, 256) + abs_val = abs(val) + abs_up = abs_val + 1 + abs_down = abs_val - 1 pre = f""" _global: %par = param - %1 = lt %par, {val} - %3 = gt %par, {val} + %1 = lt %par, {abs_val} + %3 = gt %par, {abs_val} %4 = iszero %3 %2 = iszero %1 %5 = slt %par, {val} @@ -486,8 +485,8 @@ def test_comparison_ge_le(val): post = f""" _global: %par = param - %1 = lt {down}, %par - %3 = gt {up}, %par + %1 = lt {abs_down}, %par + %3 = gt {abs_up}, %par %5 = slt {down}, %par %7 = sgt {up}, %par return %1, %3, %5, %7 diff --git a/vyper/venom/passes/algebraic_optimization.py b/vyper/venom/passes/algebraic_optimization.py index 0055e16e82..c558ba742e 100644 --- a/vyper/venom/passes/algebraic_optimization.py +++ b/vyper/venom/passes/algebraic_optimization.py @@ -348,18 +348,13 @@ def _optimize_comparator_instruction(self, inst, prefer_iszero): almost_always, never = hi, lo almost_never = lo + 1 - if not unsigned: - almost_never = signed_to_unsigned(almost_never, 256, strict=True) - almost_always = signed_to_unsigned(almost_always, 256, strict=True) - never = signed_to_unsigned(never, 256, strict=True) - - if lit_eq(operands[0], almost_never): + if lit_eq(operands[0], almost_never, unsigned): # (lt x 1), (gt x (MAX_UINT256 - 1)), (slt x (MIN_INT256 + 1)) self.updater._update(inst, "eq", [operands[1], IRLiteral(never)]) return # rewrites. in positions where iszero is preferred, (gt x 5) => (ge x 6) - if prefer_iszero and lit_eq(operands[0], almost_always): + if prefer_iszero and lit_eq(operands[0], almost_always, unsigned): # e.g. gt x 0, slt x MAX_INT256 tmp = self.updater._add_before(inst, "eq", operands) self.updater._update(inst, "iszero", [tmp]) @@ -368,7 +363,7 @@ def _optimize_comparator_instruction(self, inst, prefer_iszero): # since push0 was introduced in shanghai, it's potentially # better to actually reverse this optimization -- i.e. # replace iszero(iszero(x)) with (gt x 0) - if opcode == "gt" and lit_eq(operands[0], 0): + if opcode == "gt" and lit_eq(operands[0], 0, unsigned): tmp = self.updater._add_before(inst, "iszero", [operands[1]]) self.updater._update(inst, "iszero", [tmp]) return @@ -405,13 +400,10 @@ def _rewrite_ge_le(self, inst: IRInstruction): val -= 1 new_opcode = _flip_comparison_op(opcode) - if not unsigned: - val = signed_to_unsigned(val, 256) - # this can happen for cases like `lt x 0` which get reduced in SCCP. # don't handle them here, just return # unsigned is true since we already converted it if needed - if _wrap256(val, unsigned=True) != val: + if _wrap256(val, unsigned) != val: return self.updater._update(inst, new_opcode, [IRLiteral(val), operands[1]]) diff --git a/vyper/venom/passes/sccp/eval.py b/vyper/venom/passes/sccp/eval.py index 7af7931c86..d5ed7fb0c8 100644 --- a/vyper/venom/passes/sccp/eval.py +++ b/vyper/venom/passes/sccp/eval.py @@ -14,7 +14,9 @@ from vyper.venom.basicblock import IRLiteral, IROperand -def lit_eq(op: IROperand, val: int) -> bool: +def lit_eq(op: IROperand, val: int, unsigned: bool = True) -> bool: + if not unsigned: + return isinstance(op, IRLiteral) and _unsigned_to_signed(op.value) == val return isinstance(op, IRLiteral) and op.value == val