[Python-Dev] JUMP_IF_X opcodes (original) (raw)

Neal Norwitz neal@metaslash.com
Mon, 03 Mar 2003 21:56:26 -0500


On Mon, Mar 03, 2003 at 06:55:47PM -0500, Damien Morton wrote:

I have been reviewing the compile.c module with respect to the use of JUMPIFXXX opcodes, and the frequency with which these opcodes are followed by a POPTOP instruction.

It seems to me that there are two kinds of uses cases for these opcodes, The first use case could be expressed as POPTHENJUMPIFXXXX The second use case could be expressed as JUMPIFXXXELSEPOP Comments, suggestions, etc, appreciated.

I think you won't get much of a benefit by adding the 2+ instructions necessary for this scheme. I think it would be best to have JUMP_IF_XXX always do a POP_TOP and never jump to a jump. Below is an example of some code and the disassembly.

    >>> def f(a, b):
    ...   if a and b:
    ...     print 'nope'
    ... 
    >>> dis.dis(f)
      2           0 LOAD_FAST                0 (a)
                  3 JUMP_IF_FALSE            4 (to 10)
                  6 POP_TOP             
                  7 LOAD_FAST                1 (b)
            >>   10 JUMP_IF_FALSE            9 (to 22)
                 13 POP_TOP             

      3          14 LOAD_CONST               1 ('no')
                 17 PRINT_ITEM          
                 18 PRINT_NEWLINE       
                 19 JUMP_FORWARD             1 (to 23)
            >>   22 POP_TOP             
            >>   23 LOAD_CONST               0 (None)
                 26 RETURN_VALUE        

Note the first JUMP_IF_FALSE jumps to the second JUMP_IF_FALSE which then jumps to POP_TOP. An optimized version of this code where the POP is performed as part of the JUMP_IF_XXX could be:

    >>> dis.dis(f)
      2           0 LOAD_FAST                0 (a)
                  3 JUMP_IF_FALSE           11 (to 17)
                  6 LOAD_FAST                1 (b)
            >>    9 JUMP_IF_FALSE            5 (to 17)

      3          12 LOAD_CONST               1 ('no')
                 15 PRINT_ITEM          
                 16 PRINT_NEWLINE       
            >>   17 LOAD_CONST               0 (None)
                 20 RETURN_VALUE        

In the optimized version, there are at least 2 less iterations around the eval_frame loop (when a is false). 1 POP_TOP, 1 JUMP_IF_FALSE. If both a and b are true, the if body is executed and there are 3 iterations less. 2 POP_TOPs, 1 JUMP_FORWARD. With more conditions, the savings should be better.

The problem is that it's difficult to get the compiler to output this code AFAIK. I believe Skip's peephole optimizer did the transformation to prevent a jump to a jump, but that was another pass. The new compiler Jeremy is working on should make these sorts of transformations easier.

All that said, the scheme you propose could provide a decent speed up. The only way to know is to try. :-)

Neal