Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mypyc] low-level integer operations: integer equal #9116

Merged
merged 6 commits into from
Jul 10, 2020
Merged

[mypyc] low-level integer operations: integer equal #9116

merged 6 commits into from
Jul 10, 2020

Conversation

TH3CHARLie
Copy link
Collaborator

@TH3CHARLie TH3CHARLie marked this pull request as draft July 9, 2020 07:47
mypyc/irbuild/expression.py Outdated Show resolved Hide resolved
@TH3CHARLie
Copy link
Collaborator Author

def foo(x: int, y: int) -> bool:
     return x == y

before:

char CPyDef_foo(CPyTagged cpy_r_x, CPyTagged cpy_r_y) {
    char cpy_r_r0;
CPyL0: ;
    cpy_r_r0 = CPyTagged_IsEq(cpy_r_x, cpy_r_y);
    return cpy_r_r0;
}

after:

char CPyDef_foo(CPyTagged cpy_r_x, CPyTagged cpy_r_y) {
    char cpy_r_r0;
    int64_t cpy_r_r1;
    int64_t cpy_r_r2;
    int64_t cpy_r_r3;
    char cpy_r_r4;
    char cpy_r_r5;
    char cpy_r_r6;
CPyL0: ;
    cpy_r_r1 = 1;
    cpy_r_r2 = cpy_r_x & cpy_r_r1;
    cpy_r_r3 = 0;
    cpy_r_r4 = cpy_r_r2 == cpy_r_r3;
    if (cpy_r_r4) {
        goto CPyL1;
    } else
        goto CPyL2;
CPyL1: ;
    cpy_r_r5 = cpy_r_x == cpy_r_y;
    cpy_r_r0 = cpy_r_r5;
    goto CPyL3;
CPyL2: ;
    cpy_r_r6 = CPyTagged_IsEq_(cpy_r_x, cpy_r_y);
    cpy_r_r0 = cpy_r_r6;
    goto CPyL3;
CPyL3: ;
    return cpy_r_r0;
}

@TH3CHARLie TH3CHARLie marked this pull request as ready for review July 9, 2020 12:29
@JukkaL
Copy link
Collaborator

JukkaL commented Jul 9, 2020

The code looks good to me. It's kind of verbose, but that's to be expected.

If we implement the optimizations discussed in mypyc/mypyc#749, the generated code would look like this:

char CPyDef_foo(CPyTagged cpy_r_x, CPyTagged cpy_r_y) {
    char cpy_r_r0;
CPyL0: ;
    if (cpy_r_x & 1 == 0) {
        goto CPyL1;
    } else
        goto CPyL2;
CPyL1: ;
    cpy_r_r0 = cpy_r_x == cpy_r_y;
    goto CPyL3;
CPyL2: ;
    cpy_r_r0 = CPyTagged_IsEq_(cpy_r_x, cpy_r_y);
    goto CPyL3;
CPyL3: ;
    return cpy_r_r0;
}

If we'd also simplify redundant gotos and labels, it could look like this:

char CPyDef_foo(CPyTagged cpy_r_x, CPyTagged cpy_r_y) {
    char cpy_r_r0;
    if (cpy_r_x & 1 != 0)
        goto CPyL2;
    cpy_r_r0 = cpy_r_x == cpy_r_y;
    goto CPyL3;
CPyL2: ;
    cpy_r_r0 = CPyTagged_IsEq_(cpy_r_x, cpy_r_y);
CPyL3: ;
    return cpy_r_r0;

For now, the verbose generated code is fine. We can look at simplifying it in later PRs.

@TH3CHARLie
Copy link
Collaborator Author

TH3CHARLie commented Jul 9, 2020

If we implement the optimizations discussed in mypyc/mypyc#749

Yes this would be an interesting next step.

I've updated this PR with some dispatch logic to abstract the verbose logic and make the generalization of more ops easier.
That is, to add new binary op in this new form, we'd only need to modify int_ops.py just like we are adding new registry.

@TH3CHARLie TH3CHARLie requested a review from JukkaL July 9, 2020 14:11
Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I only have a few minor things.

mypyc/irbuild/builder.py Outdated Show resolved Hide resolved
mypyc/primitives/int_ops.py Outdated Show resolved Hide resolved

int_logical_op_mapping = {
'==': (BinaryIntOp.EQ, int_equal)
} # type: Dict[str, Tuple[int, CFunctionDescription]]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment saying that these are not complete implementations, but assume that one of operands is a long integer.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually there's no such assumption I think, the first item of the tuple provides op variant for the case when lhs of the operands is short, therefore not assume at least one of them is long.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah, you are correct.

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updated! Looks good!

@JukkaL JukkaL merged commit f73834e into python:master Jul 10, 2020
@TH3CHARLie TH3CHARLie deleted the int-op-expression branch July 22, 2020 10:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants