-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Conversation
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;
} |
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. |
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. |
There was a problem hiding this 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.
|
||
int_logical_op_mapping = { | ||
'==': (BinaryIntOp.EQ, int_equal) | ||
} # type: Dict[str, Tuple[int, CFunctionDescription]] |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this 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!
relates mypyc/mypyc#741, mypyc/mypyc#743