This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: missed peephole optimization
Type: performance Stage: resolved
Components: Versions: Python 3.4
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: Neal.Norwitz, Winterflower, benjamin.peterson, ezio.melotti, pitrou, rhettinger, serhiy.storchaka, vstinner
Priority: normal Keywords:

Created on 2013-03-15 18:38 by Neal.Norwitz, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (6)
msg184245 - (view) Author: Neal Norwitz (Neal.Norwitz) Date: 2013-03-15 18:38
>>> def fo():
...   if a:
...     if b:
...      if c:
...        print
... 
>>> dis.dis(fo)
  2           0 LOAD_GLOBAL              0 (a)
              3 POP_JUMP_IF_FALSE       28

  3           6 LOAD_GLOBAL              1 (b)
              9 POP_JUMP_IF_FALSE       28

  4          12 LOAD_GLOBAL              2 (c)
             15 POP_JUMP_IF_FALSE       25

  5          18 PRINT_NEWLINE       
             19 JUMP_ABSOLUTE           25
             22 JUMP_ABSOLUTE           28
        >>   25 JUMP_FORWARD             0 (to 28)
        >>   28 LOAD_CONST               0 (None)
             31 RETURN_VALUE        

The 2 JUMP_ABSOLUTEs should be optimized away since the code is equivalent to: if a and b and c: as in:

>>> dis.dis(fo)
  2           0 LOAD_GLOBAL              0 (a)
              3 POP_JUMP_IF_FALSE       22
              6 LOAD_GLOBAL              1 (b)
              9 POP_JUMP_IF_FALSE       22
             12 LOAD_GLOBAL              2 (c)
             15 POP_JUMP_IF_FALSE       22

  3          18 PRINT_NEWLINE       
             19 JUMP_FORWARD             0 (to 22)
        >>   22 LOAD_CONST               0 (None)
             25 RETURN_VALUE
msg184307 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-03-16 11:17
See my astoptimizer project which allow to implement optimizations in Python rather than in C, and using the AST rather than the bytecode.
https://bitbucket.org/haypo/astoptimizer/

I plan to add something in Python 3.4 to be able to plug arbitrary AST hook, including astoptimizer.
msg184311 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-03-16 13:34
> The 2 JUMP_ABSOLUTEs should be optimized away since the code is equivalent to: if a and b and c: as in:

Oh, I misread this sentence. I read that you would like to replace "if a: if b:" with "if a and b:". But it can be optimized differently: the useless jump can be removed during the bytecode generation.

I implemented replace "if a: if b:" with "if a and b:" in astoptimizer:

https://bitbucket.org/haypo/astoptimizer/commits/195df21d1dc30a21d0330e84794186488f266c29#chg-astoptimizer/optimizer.py

I already implemented removal of useless jumps in my second project, registervm:

http://hg.python.org/sandbox/registervm/file/f720340910ea/Lib/registervm.py#l1756

Read this file to learn more about my registervm project:
http://hg.python.org/sandbox/registervm/file/tip/REGISTERVM.txt
msg186498 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2013-04-10 14:37
ISTM that we were trying to moving towards an AST optimizer and away from the peephole, so I'm not sure it's a good idea to add more optimization to it.  #11549 has patches about the AST optimizer.
msg186554 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-04-11 10:02
The migration to an AST optimizer is a bit of a pie-in-the-sky project. Functionally, it doesn't have many benefits since the scope of legal static optimizations in Python is very narrow (due to the dynamic nature of the language). Therefore, the main benefit it would bring would be (presumably) easier maintenance.
msg283141 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-12-13 20:42
FYI this optimization is already implemented in 3.5+.

>>> def fo():
...   if a:
...     if b:
...      if c:
...        print()
... 
>>> import dis
>>> dis.dis(fo)
  2           0 LOAD_GLOBAL              0 (a)
              2 POP_JUMP_IF_FALSE       18

  3           4 LOAD_GLOBAL              1 (b)
              6 POP_JUMP_IF_FALSE       18

  4           8 LOAD_GLOBAL              2 (c)
             10 POP_JUMP_IF_FALSE       18

  5          12 LOAD_GLOBAL              3 (print)
             14 CALL_FUNCTION            0
             16 POP_TOP
        >>   18 LOAD_CONST               0 (None)
             20 RETURN_VALUE
History
Date User Action Args
2022-04-11 14:57:42adminsetgithub: 61632
2016-12-13 20:42:48serhiy.storchakasetstatus: open -> closed

nosy: + serhiy.storchaka
messages: + msg283141

resolution: out of date
stage: resolved
2016-12-13 20:16:22Winterflowersetnosy: + Winterflower
2013-04-11 10:02:43pitrousetnosy: + pitrou
messages: + msg186554
2013-04-10 14:37:26ezio.melottisetnosy: + rhettinger, benjamin.peterson
messages: + msg186498
2013-03-23 14:02:34ezio.melottisetnosy: + ezio.melotti

versions: + Python 3.4, - Python 2.7
2013-03-16 13:34:16vstinnersetmessages: + msg184311
2013-03-16 11:17:55vstinnersetnosy: + vstinner
messages: + msg184307
2013-03-15 18:38:41Neal.Norwitzcreate