micropython/tests/cmdline/cmd_showbc_const.py
Angus Gratton 25ff5b52d9 py/parse: Allow const types other than int to optimise as true/false.
Allows optimisation of cases like:

    import micropython
    _DEBUG = micropython.const(False)
    if _DEBUG:
        print('Debugging info')

Previously the 'if' statement was only optimised out if the type of the
const() argument was integer.

The change is implemented in a way that makes the compiler slightly smaller
(-16 bytes on PYBV11) but compilation will also be very slightly slower.

As a bonus, if const support is enabled then the compiler can now optimise
const truthy/falsey expressions of other types, like:

    while "something":
        pass

... unclear if that is useful, but perhaps it could be.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2022-09-23 16:04:13 +10:00

70 lines
1.5 KiB
Python

# cmdline: -v -v
# Test constant-related bytecode optimisations
# (constant folding, compile-time if/while evaluation, etc.)
from micropython import const
import sys
try:
sys.settrace
# if MICROPY_PY_SYS_SETTRACE is enabled, compile-time const optimizations
# are disabled so the bytecode output is very different
print("SKIP")
raise SystemExit
except AttributeError:
pass
_STR = const("foo")
_EMPTY_TUPLE = const(())
_TRUE = const(True)
_FALSE = const(False)
_SMALLINT = const(33)
_ZERO = const(0)
# Bytecode generated for these if/while statements should contain no JUMP_IF
# and no instances of string 'Eliminated'
if _STR or _EMPTY_TUPLE:
print("Kept")
if _STR and _EMPTY_TUPLE:
print("Eliminated")
if _TRUE:
print("Kept")
if _SMALLINT:
print("Kept")
if _ZERO and _SMALLINT:
print("Eliminated")
if _FALSE:
print("Eliminated")
while _SMALLINT:
print("Kept")
break
while _ZERO:
print("Eliminated")
while _FALSE:
print("Eliminated")
# These values are stored in variables, and therefore bytecode will contain JUMP_IF
a = _EMPTY_TUPLE or _STR
if a == _STR:
print("Kept")
b = _SMALLINT and _STR
if b == _STR:
print("Kept")
# The compiler is also unable to optimise these expressions, even though the arguments are const,
# so these also contain JUMP_IF
if (_EMPTY_TUPLE or _STR) == _STR:
print("Kept")
if (_EMPTY_TUPLE and _STR) == _STR:
print("Not Eliminated")
if (not _STR) == _FALSE:
print("Kept")
assert True