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] Fix signed integer comparison #9163

Merged
merged 5 commits into from
Jul 20, 2020
Merged

[mypyc] Fix signed integer comparison #9163

merged 5 commits into from
Jul 20, 2020

Conversation

TH3CHARLie
Copy link
Collaborator

358522e generates inline comparison between short ints, explicit conversion to signed is missing, though, causing negative cases to fail.

This PR add explicit type casts(although the name truncate here is a little bit misleading).

This PR will fix microbenchmark int_list.

lhs_short = self.add(Truncate(lhs, short_int_rprimitive,
c_pyssize_t_rprimitive, line))
rhs_short = self.add(Truncate(rhs, short_int_rprimitive,
c_pyssize_t_rprimitive, line))
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not very principled. The truncate op is redundant, and also confusingly the sizes of source and target types are the same, so there's no truncation actually going on.

Instead, we should generate the correct C code for short int comparison (add the cast to a signed integer type). Maybe you can look at the type attribute of BinaryIntOp to determine whether a signed comparison is needed when emitting C.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, the truncate also looks weird to me. So when we emit a BinaryIntOp, we check if both operands are short_int(and probably check if the op is not EQ or NEQ as well since they do not require casts to have the correct result) to cast them into py_ssize_t

Copy link
Collaborator

Choose a reason for hiding this comment

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

More generally, also plain tagged integers need to use a cast since they are signed.

Probably the cleanest way to check the operand types would be to update every Value to contain the result type, but I'm not sure if this is necessary.

@JukkaL
Copy link
Collaborator

JukkaL commented Jul 17, 2020

Note that there's a merge conflict.

@TH3CHARLie TH3CHARLie requested a review from JukkaL July 17, 2020 13:13
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 updates, looks mostly good now!

There's still the issue that unsigned comparisons aren't fully implemented. It's also okay to leave it out from this PR (only include things like SLT), and they can be added later.

mypyc/codegen/emitfunc.py Show resolved Hide resolved
mypyc/ir/ops.py Show resolved Hide resolved
@TH3CHARLie TH3CHARLie requested a review from JukkaL July 17, 2020 16:45
@@ -245,6 +247,10 @@ def test_dict_contains(self) -> None:
'in', self.b, self.o, self.d,
"""cpy_r_r0 = PyDict_Contains(cpy_r_d, cpy_r_o);""")

def test_binary_int_op(self) -> None:
self.assert_emit(BinaryIntOp(bool_rprimitive, self.s1, self.s2, BinaryIntOp.SLT, 1),
"""cpy_r_r0 = (Py_ssize_t)cpy_r_s1 < (Py_ssize_t)cpy_r_s2;""")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also test unsigned comparison with int64 and int32. These need a cast to the corresponding unsigned type (uint64_t or uint32_t, respectively). Finally, test that unsigned comparison with short_int_rprimitive and signed comparison with int32 or int64 doesn't use a cast.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks! This actually catches a bug in ops.py that constant's definition are overlapped.

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 updates! Looks good now.

@JukkaL JukkaL merged commit 4cf246f into python:master Jul 20, 2020
@TH3CHARLie TH3CHARLie deleted the sign-compare branch July 22, 2020 10:28
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