constant folding - why not more
Terry Reedy
tjreedy at udel.edu
Tue Nov 10 15:03:40 EST 2020
On 11/10/2020 1:03 PM, Barry Scott wrote:
>
>
>> On 10 Nov 2020, at 14:45, David Kolovratník <david at kolovratnik.net> wrote:
>>
>> Dear all,
>>
>> I would like to learn about constant folding optimisation in Python. It seems
>> to be implemented in Python/ast_opt.c. In order to get impression I used
>> python3 and dis module:
>>
>> $ python3 -V
>> Python 3.7.3
>
> I do not have answers to your questions, but I would suggest that you look at 3.9
> or even 3.10a2 to see if this is still the case.
Checking with 3.10...
>> Arithmetics expression is folded as expected:
>>
>>>>> dis.dis(compile('1 * 2', filename='<string>', mode='eval',
>>>>> optimize=2))
>> 1 0 LOAD_CONST 0 (2)
>> 2 RETURN_VALUE
>>
>> On the contrary, comparison remains for runtime:
>>>>> dis.dis(compile('1 < 2', filename='<string>', mode='eval',
>>>>> optimize=2))
>> 1 0 LOAD_CONST 0 (1)
>> 2 LOAD_CONST 1 (2)
>> 4 COMPARE_OP 0 (<)
>> 6 RETURN_VALUE
Same.
>> In function fold_unaryop (though comparison is a binary operation) in
>> Python/ast_opt.c is remark: /* Fold not into comparison */
Use git blame to find out who and when made that remark.
>> Is there a reason why comparison (== != < > <= >=) is not folded? I would
>> expect it handled in fold_binop.
>>
>> Besides comparison there are other expressions that might be optimized out
>> due to constant expression. Ternary operator with constant condition True
>> has IF optimized out (just some dead code remains):
>>>>> dis.dis(compile('"a" if True else "b"', filename='<string>',
>>>>> mode='eval', optimize=2))
>> 1 0 LOAD_CONST 1 ('a')
>> 2 RETURN_VALUE
Remains.
>> 4 LOAD_CONST 2 ('b')
>> 6 RETURN_VALUE
Gone.
>> On the contrary, the same ternary operator with constant condition False
>> still loads the constat and contains POP_JUMP_IF_FALSE:
>>>>> dis.dis(compile('"a" if False else "b"', filename='<string>',
>>>>> mode='eval', optimize=2))
>> 1 0 LOAD_CONST 0 (False)
>> 2 POP_JUMP_IF_FALSE 8
>> 4 LOAD_CONST 1 ('a')
>> 6 RETURN_VALUE
>> >> 8 LOAD_CONST 2 ('b')
>> 10 RETURN_VALUE
Same. You could file issue for this, but one guess is that else clause
might spill over to another line, and current decision is that for
tracing, every line of code that naively should be executed is executed
rather than optimized away. But I would first try to find the file that
produces bytecode and then use git blame to find issue where the True
else part was removed.
--
Terry Jan Reedy
More information about the Python-list
mailing list