faster-cpython / ideas

1.67k stars 49 forks source link

Can super-instructions be rewritten as macros in the instruction definition DSL? #507

Closed gvanrossum closed 1 year ago

gvanrossum commented 1 year ago

Currently our DSL has two separate but similar bits of syntax for super- and macro instructions:

super(X) = A + B;
macro(X) = A + B;

These differ in that super() inserts some code between components:

<prologue>
{
    <code for A>
}
NEXTOPARG();
next_instr++;
{
    <code for B>
}
<epilogue>

whereas macro() doesn't (omitting NEXTOPARG(); next_instr++;).

(There are some other differences, in particular macros allow interspersing cache effects between the components.)

It turns out it is possible to rewrite any super-instruction of this form as a macro:

macro(X) = A + JOIN + B;

where JOIN is a micro-op defined roughly like this:

        op(JOIN, (word/1 --)) {
            oparg = _Py_OPARG(word);
        }

Given the limited use we have for super-instructions and the code duplication in the code generator to handle both, this seems a nice win.

Note: Eventually we may need to bring super() back into the DSL, but for a different use case.

gvanrossum commented 1 year ago

There is a concern though. If the second opcode uses ERROR_IF(), we'll reach the error label with next_instr still pointing just past the first component. So far none of the super-instructions have a second component that uses ERROR_IF(), and it's not clear that the consequences will be momentous, but we should think this through. For example, if a super-instruction spans two source lines, presumably this will erroneously attribute the error to the first line. (This may be the only thing that goes wrong, and maybe we can accept it.)

markshannon commented 1 year ago

Why not keep super(X) = A + B; and implement it as syntactic sugar for macro(X) = A + JOIN + B;?

gvanrossum commented 1 year ago

If you really want to keep the super(X) syntax then we should just stick with what we have, there's some code duplication but I doubt that internally translating it to macro(X) will reduce the code size enough to bother. (@brandtbucher ?)

gvanrossum commented 1 year ago

Off-line we discussed this and decided not to do this. super(X) and macro(X) will continue to co-exist.