faster-cpython / ideas

1.67k stars 49 forks source link

Specialize more tier 1 instructions to feed information to tier 2? #625

Open Fidget-Spinner opened 9 months ago

Fidget-Spinner commented 9 months ago

Currently, tier 2 optimizations depend on information gathered in tier 1.

Previously, we only added optimizations that made sense for tier 1. It might now be time to consider adding instructions for the sole purpose of gathering more data for tier 2 as well.

For example, UNARY_NOT is not specialized at all. This means every UNARY_NOT complicates optimization opportunities, even though something like not x is almost likely always going to be UNARY_NOT_BOOL.

carljm commented 9 months ago

something like not x is almost likely always going to be UNARY_NOT_BOOL.

As an aside, I'm curious how true this is in practice. Anecdotally I feel like I see plenty of not x on other types of x. I guess the way to find out is to implement the specialization and gather some stats.

(I realize that's just one example for this issue.)

tekknolagi commented 9 months ago

Anecdotal, but we saw a lot of not str and not list and not set in the development of Skybison (and specialized on all of them).

brandtbucher commented 9 months ago

For what it's worth, this specific UNARY_NOT example isn't true anymore. UNARY_NOT and the conditional jumps always expect an exact boolean, which is produced by the TO_BOOL family. This is one of my favorite families: check out gems such as TO_BOOL_BOOL, TO_BOOL_NONE, and TO_BOOL_ALWAYS_TRUE. Lists, integers, and strings are also specialized.

brandtbucher commented 9 months ago

You can check out the TO_BOOL stats for other failure kinds (under "Specialization stats" -> "TO_BOOL"): https://github.com/faster-cpython/benchmarking-public/blob/main/results/bm-20230911-3.13.0a0-b88d9e7/bm-20230911-azure-x86_64-python-b88d9e75f68f102aca45-3.13.0a0-b88d9e7-pystats.md

tekknolagi commented 9 months ago

Oh, very nice.

Fidget-Spinner commented 9 months ago

For what it's worth, this specific UNARY_NOT example isn't true anymore. UNARY_NOT and the conditional jumps always expect an exact boolean, which is produced by the TO_BOOL family. This is one of my favorite families: check out gems such as TO_BOOL_BOOL, TO_BOOL_NONE, and TO_BOOL_ALWAYS_TRUE. Lists, integers, and strings are also specialized.

Oh then I guess UNARY_NOT is a pure op then, and need not be specialised. Thanks!