Skip to content

WIP: Extend the interpreter DSL to assist in optimization passes and even codegen #611

@Fidget-Spinner

Description

@Fidget-Spinner

The current rough proposal for optimization passes is to use abstract interpretation on tier 2 uops. This makes the interpreter DSL a natural way of describing the abstract interpretation. We could extend the interpreter DSL to do two additional things:

  1. Feed information to our optimization passes. This reduces maintenance burden for the analysis phase.
  2. Help the optimization passes make sound decisions. This reduces maintenance burden for the codegen phase.

1
Here's the _BINARY_OP_MULTIPLY_INT uop, annotated with type annotation information for the output:

        op(_BINARY_OP_MULTIPLY_INT, (unused/1, left, right -- res: &PyLong_Type)) {
            STAT_INC(BINARY_OP, hit);
            res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
            ERROR_IF(res == NULL, error);
        }

Which would potentially generate the following target for type propagation:

        TARGET(_BINARY_OP_MULTIPLY_INT) {
            _Py_TYPENODE_t *left = TYPESTACK_PEEK(2); // int
            STACK_SHRINK(1);
            TYPE_SET(left, TYPESTACK_PEEK(1), false); // int
            break;
        }

We plan to further experiment with this to see if we can feed information required for partial evaluation. E.g.

        // @pure
        op(_BINARY_OP_MULTIPLY_INT, (unused/1, left, right -- res: &PyLong_Type)) {
            ...
        }

Would mark that this operation is "pure", and that it does not affect the static/dynamic split during partial evaluation.

2 The conversion from BINARY_OP to _BINARY_OP_MULTIPLY_INT is fairly simple. The predicate is that oparg=NB_MULTIPLY and type(left)=type(right)=int. This could be how we can annotate that in the DSL:

        // @autocodegen
        // @codegen_predicate(oparg=NB_MULTIPLY)
        // @pure
        op(_BINARY_OP_MULTIPLY_INT, (unused/1, left: &PyLong_Type, right: &PyLong_Type -- res: &PyLong_Type)) {
        }

Note that we have type annotated the input types. This tells the type propagator what types we expect the stack variables to be. Note that the code generator already knows that BINARY_OP maps to BINARY_OP_ADD_INT thanks to the family tag in the DSL!

Metadata

Metadata

Assignees

No one assigned

    Labels

    epic-tier2-optimizerLinear code region optimizer for 3.13 and beyond.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions