[Python-Dev] pyc files, constant folding and borderline portability issues

Cesare Di Mauro cesare.dimauro at a-tono.com
Mon Apr 6 16:28:45 CEST 2009

On Mar 29, 2009 at 05:36PM, Guido van Rossum <guido at python.org> wrote:

>> - Issue #5593: code like 1e16+2.9999 is optimized away and its result stored as
>> a constant (again), but the result can vary slightly depending on the internal
>> FPU precision.
> I would just not bother constant folding involving FP, or only if the
> values involved have an exact representation in IEEE binary FP format.

The Language Reference says nothing about the effects of code optimizations.
I think it's a very good thing, because we can do some work here with constant

If someone wants to preserve precision with floats, it can always use a temporary
variable, like in many other languages.

>> These problems have probably been there for a long time and almost no one seems
>> to complain, but I thought I'd report them here just in case.
> I would expect that constant folding isn't nearly effective in Python
> as in other (less dynamic) languages because it doesn't do anything
> for NAMED constants. E.g.
> MINUTE = 60
> def half_hour():
>     return MINUTE*30
> This should be folded to "return 1800" but doesn't because the
> compiler doesn't know that MINUTE is a constant.

I completely agree. We can't say nothing about MINUTE at the time half_hour
will be executed. The code here must never been changed.

> Has anyone ever profiled the effectiveness of constant folding on
> real-world code? The only kind of constant folding that I expect to be
> making a diference is things like unary operators, since e.g. "x = -2"
> is technically an expression involving a unary minus.

At this time with Python 2.6.1 we have these results:
def f(): return 1 + 2 * 3 + 4j

  1           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               5 (6)
              6 BINARY_ADD
              7 LOAD_CONST               4 (4j)
             10 BINARY_ADD
             11 RETURN_VALUE

def f(): return ['a', ('b', 'c')] * (1 + 2 * 3)

  1           0 LOAD_CONST               1 ('a')
              3 LOAD_CONST               7 (('b', 'c'))
              6 BUILD_LIST               2
              9 LOAD_CONST               4 (1)
             12 LOAD_CONST               8 (6)
             15 BINARY_ADD
             16 BINARY_MULTIPLY
             17 RETURN_VALUE

With proper constant folding code, both functions can be reduced
to a single LOAD_CONST and a RETURN_VALUE (or, definitely, by
a single instruction at all with an advanced peephole optimizer).

I'll show you it at PyCon in Florence, next month.

> ISTM that historically, almost every time we attempted some new form
> of constant folding, we introduced a bug.

I found a very rich test battery with Python, which helped me a lot in my
work of changing the ast, compiler, peephole, and VM.
If they aren't enough, we can expand them to add more test cases.

But, again, the Language Reference says nothing about optimizations.


More information about the Python-Dev mailing list