[issue2506] Add mechanism to disable optimizations

STINNER Victor report at bugs.python.org
Tue May 28 05:35:53 EDT 2019


STINNER Victor <vstinner at redhat.com> added the comment:

My PR 13600 works as expected.

I simplified attached continue.py: see attached traceme.py.

Output with optimizations
---
$ ./python traceme.py  
  6           0 LOAD_CONST               1 (0)
              2 STORE_FAST               0 (a)

  7           4 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               2 (3)
              8 LOAD_CONST               3 (4)
             10 CALL_FUNCTION            2
             12 GET_ITER
        >>   14 FOR_ITER                30 (to 46)
             16 STORE_FAST               1 (n)

  8          18 LOAD_FAST                1 (n)
             20 LOAD_CONST               4 (2)
             22 BINARY_MODULO
             24 POP_JUMP_IF_FALSE       14

  9          26 LOAD_FAST                1 (n)
             28 LOAD_CONST               2 (3)
             30 BINARY_MODULO
             32 POP_JUMP_IF_FALSE       14

 10          34 LOAD_FAST                0 (a)
             36 LOAD_CONST               5 (1)
             38 INPLACE_ADD
             40 STORE_FAST               0 (a)

 11          42 JUMP_ABSOLUTE           14
             44 JUMP_ABSOLUTE           14
        >>   46 LOAD_CONST               0 (None)
             48 RETURN_VALUE
 --- modulename: traceme, funcname: func
traceme.py(6):     a = 0
traceme.py(7):     for n in range(3, 4):
traceme.py(8):         if n % 2:
traceme.py(9):             if n % 3:
traceme.py(7):     for n in range(3, 4):
---

Output without optimizations (-X noopt):
---
$ ./python -X noopt traceme.py  
  6           0 LOAD_CONST               1 (0)
              2 STORE_FAST               0 (a)

  7           4 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               2 (3)
              8 LOAD_CONST               3 (4)
             10 CALL_FUNCTION            2
             12 GET_ITER
        >>   14 FOR_ITER                30 (to 46)
             16 STORE_FAST               1 (n)

  8          18 LOAD_FAST                1 (n)
             20 LOAD_CONST               4 (2)
             22 BINARY_MODULO
             24 POP_JUMP_IF_FALSE       44

  9          26 LOAD_FAST                1 (n)
             28 LOAD_CONST               2 (3)
             30 BINARY_MODULO
             32 POP_JUMP_IF_FALSE       42

 10          34 LOAD_FAST                0 (a)
             36 LOAD_CONST               5 (1)
             38 INPLACE_ADD
             40 STORE_FAST               0 (a)

 11     >>   42 JUMP_ABSOLUTE           14
        >>   44 JUMP_ABSOLUTE           14
        >>   46 LOAD_CONST               0 (None)
             48 RETURN_VALUE
 --- modulename: traceme, funcname: func
traceme.py(6):     a = 0
traceme.py(7):     for n in range(3, 4):
traceme.py(8):         if n % 2:
traceme.py(9):             if n % 3:
traceme.py(11):             continue
traceme.py(7):     for n in range(3, 4):
---


The difference on the trace is that using -X noopt, "traceme.py(11):             continue" line is traced as expected.

The difference on the bytecode is that jumps are no longer optimized using -X noopt:

* Optimized:

  "32 POP_JUMP_IF_FALSE       14"

* Not optimized:

  "32 POP_JUMP_IF_FALSE       42"
  ">>   42 JUMP_ABSOLUTE           14"

The peephole optimizer replaces a jump to an unconditional jump with a jump directly to the target of the unconditional jump.

I documented peephole optimizations in my reimplementation in pure Python:
https://bytecode.readthedocs.io/en/latest/peephole.html#optimizations
(I'm not sure that it's up to date, but it should give you an idea of which kinds of optimizations are implemented.)

----------
Added file: https://bugs.python.org/file48371/traceme.py

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue2506>
_______________________________________


More information about the Python-bugs-list mailing list