[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Guido van Rossum
Since this is unrealistic code (why would you have a top-level expression
without any side effects), what does it matter whether this code is
optimized? Did you encounter this in a real use case?

On Sun, Oct 10, 2021 at 9:59 AM Patrick Reader <_...@pxeger.com> wrote:

> Consider sequences of bytecode operations on fast locals like the
> following:
>
> >>> def f(x):  # declare as parameter so that x is a fast local
> ... x
> ...
> >>> dis(f)
>   2   0 LOAD_FAST0 (x)
>   2 POP_TOP
>   4 LOAD_CONST   0 (None)
>   6 RETURN_VALUE
>
> Given the following assumptions:
>
> - a LOAD_FAST cannot possibly have any side-effects outside the
> interpreter stack [1]
>
> - a POP_TOP immediately undoes LOAD_FAST's effects on the interpreter stack
>
> I am wondering: why doesn't the peephole optimiser remove these opcode
> constructs?
>
> Is it maybe because of PEP 626 - an introspection tool needs to know that
> the variable is being used there? Although surely in that case the peephole
> optimiser could just replace it with a single NOP? (c.f.:
> https://bugs.python.org/issue42719)
>
> Or is one of my assumptions wrong?
>
> [1]: global variables are probably supposed to have the same guarantee,
> but in practice this is not the case, which is why I'm focusing on the
> _FAST ones; see for example
> https://ato.pxeger.com/run?1=m72soLIkIz9vwYKlpSVpuhY3JyXnJBYXK_hWumQml2ikAAlNKy4FIEhJTVOIj09PLcksSc2Nj9coTs1J01HITq2EyoNAQVFmXomGUnFmSqpCalpaanKJoqKSJly6KLWktChPobi0ILVIQ1MP2TSQOVxcqRWpyRpKFUo6MPsrbA01NSEugzoQ5lAA
>
> ___
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@python.org
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-dev@python.org/message/767FGRV4ZL5IVBHWSAW5TJGQMGQS244Z/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/WNFD6UCU6AND6TMA5M2LXNAXPXY577AU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Brandt Bucher
I can think of two reasons.

The first reason is that this operation *does* have a side-effect: if a fast 
local is unbound, the load will raise a NameError!

def f():
 x  # This should always raise.
 x = None  # This makes x a fast local.

The second reason is one that Guido already alluded to: the peephole optimizer 
shouldn’t be tasked with “fixing” poorly-written or uncommon code… just 
improving common code.

If anything, we would probably just warn here. But even that seems like too 
much.

Brandt
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/TJKKOVORTSM5QVRV5WXMUUKBUDYN2IQ7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Guido van Rossum
On Sun, Oct 10, 2021 at 10:28 AM Brandt Bucher 
wrote:

> the peephole optimizer shouldn’t be tasked with “fixing” poorly-written or
> uncommon code… just improving common code.
>

As soon as this pattern appears in a benchmark suite we'll optimize it
away. :-) (That is, *if* the optimizer can prove that it can't raise a name
error.)

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/XBUGXARBK476SC5JXK3PXODQQ2LS7KTB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Steven D'Aprano
On Sun, Oct 10, 2021 at 09:15:30AM +, Patrick Reader wrote:

> - a LOAD_FAST cannot possibly have any side-effects outside the 
> interpreter stack [1]

> [1]: global variables are probably supposed to have the same 
> guarantee, but in practice this is not the case

I don't think that lookups are guaranteed to be side-effect free, since 
raising an exception is a side-effect.

def func():
x

can raise NameError if there is no global or builtin "x". So that cannot 
be optimized away. Similarly for locals:

def func(x):
if random.random() > 0.5:
del x
x

Will that raise or not? No way of telling without actually running the 
code.

Now I guess a sufficiently smart optimizer might be able to optimize 
away the lookup of a local variable if it cannot possibly be undefined, 
as in your initial example, but that brings us to how much benefit is 
gained for how much developer effort and code complexity.

If the benefit is small, or negligible, then the developer effort 
had better be even smaller.

In this case, the cost of the lookup is small (it is a *FAST* lookup). 
And furthermore, the likelihood that anyone will actually write that 
code is even smaller.

(There are times that we might test for the existence of a global, by 
looking up the name. There might even be times that we would do the same 
for a local. We might even, under some rare circumstances, do so without 
guarding it in a try...except block. But why on earth would we test for 
the existence of a local that cannot possibly fail to exist, which is 
the only case that is safe to optimize away?)

So the benefit is correspondingly tiny, and optimizing it away had 
better be effectively free in both developer effort and ongoing code 
complexity to make it worthwhile.


-- 
Steve
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/HWSHZLW64Q26EIUPX4S3TME5QXYBRLPY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Patrick Reader
On 10/10/2021 18:26, Brandt Bucher wrote:
> The first reason is that this operation *does* have a side-effect: if a fast 
> local is unbound, the load will raise a NameError!
>
> def f():
>  x  # This should always raise.
>  x = None  # This makes x a fast local.
Ah, ok, that certainly explains it - thanks!
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/GLQ4LXLZZMRLDQQJTDM2CZOFNJ62I6JE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Patrick Reader
On 10/10/2021 18:33, Guido van Rossum wrote:
> On Sun, Oct 10, 2021 at 10:28 AM Brandt Bucher  wrote:
>
> the peephole optimizer shouldn’t be tasked with “fixing” poorly-written 
> or uncommon code… just improving common code.
>
Good point.
>
> As soon as this pattern appears in a benchmark suite we'll optimize it away. 
> :-) (That is, *if* the optimizer can prove that it can't raise a name error.)
Perhaps a more realistic case that definitely doesn't require a check to 
prevent NameErrors would be optimising `STORE_FAST x LOAD_FAST x` for same x. 
But as Steven D'Aprano has just pointed out, they're FAST lookups anyway, so 
the benefit may well be minimal anyway.___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/JNDLOPUWPELH55WL4B5YFDGRIMHOIF2P/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Guido van Rossum
On Sun, Oct 10, 2021 at 12:27 PM Patrick Reader <_...@pxeger.com> wrote:

> On 10/10/2021 18:33, Guido van Rossum wrote:
>
> On Sun, Oct 10, 2021 at 10:28 AM Brandt Bucher 
> wrote:
>
>> the peephole optimizer shouldn’t be tasked with “fixing” poorly-written
>> or uncommon code… just improving common code.
>>
> Good point.
>
>
> As soon as this pattern appears in a benchmark suite we'll optimize it
> away. :-) (That is, *if* the optimizer can prove that it can't raise a name
> error.)
>
> Perhaps a more realistic case that definitely doesn't require a check to
> prevent NameErrors would be optimising `STORE_FAST x LOAD_FAST x` for same
> x. But as Steven D'Aprano has just pointed out, they're FAST lookups
> anyway, so the benefit may well be minimal anyway.
>

What's exasperating to me about this whole discussion is that nobody has
shown any reason why this kind of code would be occurring in user code.
STORE_FAST x LOAD_FAST x seems that it must come from a user writing

x = x

But why would they write that? Are we just a solution (a clever peephole
trick) looking for a problem?

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/UH4B3J7UHPWETBZYZFDMPSOKHRSRY372/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Brandt Bucher
Guido van Rossum wrote:
> What's exasperating to me about this whole discussion is that nobody has
> shown any reason why this kind of code would be occurring in user code.
> STORE_FAST x LOAD_FAST x seems that it must come from a user writing
> x = x

I think that would be LOAD_FAST(x) STORE_FAST(x). STORE_FAST(x) LOAD_FAST(x) 
could be caused by something like this:
 
def f():
x = …
y = x

Presumably this could be replaced with DUP_TOP() STORE_FAST(x)? But I don’t 
know if that’s any faster. It does require more stack space…

> Are we just a solution (a clever peephole
> trick) looking for a problem?

It seems so.

Brandt
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/XGFBCVDIEXEBKFGUOHSXJD3GKO7IAYLM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Dennis Sweeney
STORE_FAST can also be caused by the assignment to a loop variable, so 
STORE/LOAD pairs can come about with things like this:

>>> def f():
... for x in stuff:
... x.work()
... 
... 
>>> from dis import dis
>>> dis(f)
2   0 LOAD_GLOBAL  0 (stuff)
2 GET_ITER
>>4 FOR_ITER 6 (to 18)
6 STORE_FAST   0 (x)

3   8 LOAD_FAST0 (x)
10 LOAD_METHOD  1 (work)
12 CALL_METHOD  0
14 POP_TOP
16 JUMP_ABSOLUTE2 (to 4)

2 >>   18 LOAD_CONST   0 (None)
20 RETURN_VALUE

I'd guess that they'd be somewhat common in comprehensions too:

>>> dis(x**2 for x in range(1000))
0 GEN_START0

1   2 LOAD_FAST0 (.0)
>>4 FOR_ITER 7 (to 20)
6 STORE_FAST   1 (x)
8 LOAD_FAST1 (x)
10 LOAD_CONST   0 (2)
12 BINARY_POWER
14 YIELD_VALUE
16 POP_TOP
18 JUMP_ABSOLUTE2 (to 4)
>>   20 LOAD_CONST   1 (None)
22 RETURN_VALUE


In fact, there's already a bpo issue from 2019: 
https://bugs.python.org/issue38381
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/73BMYW3TY7PJB7KRQ3Q3OROGU5UJVJAW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-10 Thread Guido van Rossum
Sorry for the brainfart earlier. We've got a discussion in our "ideas"
database already about this, start reading here:
https://github.com/faster-cpython/ideas/issues/16#issuecomment-881439738

On Sun, Oct 10, 2021 at 2:55 PM Dennis Sweeney 
wrote:

> STORE_FAST can also be caused by the assignment to a loop variable, so
> STORE/LOAD pairs can come about with things like this:
>
> >>> def f():
> ... for x in stuff:
> ... x.work()
> ...
> ...
> >>> from dis import dis
> >>> dis(f)
> 2   0 LOAD_GLOBAL  0 (stuff)
> 2 GET_ITER
> >>4 FOR_ITER 6 (to 18)
> 6 STORE_FAST   0 (x)
>
> 3   8 LOAD_FAST0 (x)
> 10 LOAD_METHOD  1 (work)
> 12 CALL_METHOD  0
> 14 POP_TOP
> 16 JUMP_ABSOLUTE2 (to 4)
>
> 2 >>   18 LOAD_CONST   0 (None)
> 20 RETURN_VALUE
>
> I'd guess that they'd be somewhat common in comprehensions too:
>
> >>> dis(x**2 for x in range(1000))
> 0 GEN_START0
>
> 1   2 LOAD_FAST0 (.0)
> >>4 FOR_ITER 7 (to 20)
> 6 STORE_FAST   1 (x)
> 8 LOAD_FAST1 (x)
> 10 LOAD_CONST   0 (2)
> 12 BINARY_POWER
> 14 YIELD_VALUE
> 16 POP_TOP
> 18 JUMP_ABSOLUTE2 (to 4)
> >>   20 LOAD_CONST   1 (None)
> 22 RETURN_VALUE
>
>
> In fact, there's already a bpo issue from 2019:
> https://bugs.python.org/issue38381
> ___
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@python.org
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-dev@python.org/message/73BMYW3TY7PJB7KRQ3Q3OROGU5UJVJAW/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/BPDXGJYAMI7UCIDECB5XXQ6VQ4LGH7OG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Why doesn't peephole optimise away operations with fast locals?

2021-10-11 Thread Serhiy Storchaka
10.10.21 23:38, Guido van Rossum пише:
> What's exasperating to me about this whole discussion is that nobody has
> shown any reason why this kind of code would be occurring in user code.
> STORE_FAST x LOAD_FAST x seems that it must come from a user writing
> 
>     x = x

No, it comes from pretty common code:

   for x in a:
   y = x**2

   with open() as f:
   for x in f:
   ...

   x = get():
   if x:
   ...

But there is nothing to optimize here. This sequence is already fast. It
can be replaced with "DUP_TOP; STORE_FAST x", but it would not be
faster. Even if we introduce a new combined opcode, it would not be
significantly faster, and it can slow down the eval loop.

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/EUYIABPM3QKP34ZG3YTHWDRYGQL2EY4P/
Code of Conduct: http://python.org/psf/codeofconduct/