Skip to content

JIT: Don't assume unsigned division always produces non-negative result in value numbering#109384

Merged
amanasifkhalid merged 6 commits intodotnet:mainfrom
amanasifkhalid:fix-udiv-valuenum
Oct 31, 2024
Merged

JIT: Don't assume unsigned division always produces non-negative result in value numbering#109384
amanasifkhalid merged 6 commits intodotnet:mainfrom
amanasifkhalid:fix-udiv-valuenum

Conversation

@amanasifkhalid
Copy link
Contributor

Fixes #109337. This pessimized relatively few methods locally, and the underlying optimization was expanded with #105593 in .NET 10, so this churn seems tolerable.

cc @dotnet/jit-contrib, @jakobbotsch PTAL. Thanks!

@ghost ghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Oct 30, 2024
case VNF_EQ:
case VNF_NE:
case VNF_UMOD:
case VNF_UDIV:
Copy link
Member

Choose a reason for hiding this comment

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

Is this the "right" thing? The result remains unsigned, it just has the most significant bit set.

Does IsVNNeverNegative actually behavior more like IsMsbNeverSet and should a comment be added?


It isn't clear why UDIV is problematic but VNF_ADD_UN_OVF is not, considering that say Int.MaxValue + 1 would produce 0x8000_0000 (a positive unsigned value, but equivalent to int.MinValue if interpreted as a signed value).

The same question would also apply to UMOD where 2147483648u % 2147483649u would still produce 2147483648u (0x8000_0000)

Copy link
Member

Choose a reason for hiding this comment

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

Indeed IsVNNeverNegative should be taken to mean whether the value is non-negative when considered as a signed value. Since signedness/unsignedness is a property of operations in the JIT it doesn't really make sense to talk about signed/unsigned values.

I agree it looks like more operations need to be removed from this list.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The same question would also apply to UMOD where 2147483648u % 2147483649u would still produce 2147483648u (0x8000_0000)

I can readily repro bad codegen for this scenario. I can't get the right code shape for the arithmetic overflow scenarios to produce bad codegen, though based on your explanation, I agree they should be removed, too.

Copy link
Member

Choose a reason for hiding this comment

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

Indeed IsVNNeverNegative should be taken to mean whether the value is non-negative when considered as a signed value. Since signedness/unsignedness is a property of operations in the JIT it doesn't really make sense to talk about signed/unsigned values.

👍

This seems like something that is very easy to get wrong given the current naming of the flag/query. It might be beneficial to consider whether a better name exists as part of a follow up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This seems like something that is very easy to get wrong given the current naming of the flag/query. It might be beneficial to consider whether a better name exists as part of a follow up.

The comment I added reaffirms your suggestion of IsMsbNeverSet -- I can switch over to that now, since we're here.

Copy link
Member

Choose a reason for hiding this comment

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

There's a number of other places using the "NeverNegative" terminology. If we rename one we should rename all of them, otherwise I think it's better to be consistent.

Copy link
Member

Choose a reason for hiding this comment

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

Agree, IsMsbNeverSet doesn't sound great/easy to discover. I think a more generic solution is to return "bits used" with additional helpers on top (that's how it's done in LLVM), till that is implement I propose we stick to IsVNNeverNegative.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, reverted.

Copy link
Member

Choose a reason for hiding this comment

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

If we rename one we should rename all of them
IsMsbNeverSet doesn't sound great/easy to discover.

Agreed on both points. That's why I had suggested considering other names as a follow up. Something like ISVNNeverNegativeWhenSigned might be clearer and just makes the existing name more verbose, for example.

I'm sure between all of use we can get some good suggestions and come up with a decent name

@amanasifkhalid
Copy link
Contributor Author

Diffs show small regressions as expected.

@amanasifkhalid amanasifkhalid merged commit a3b617e into dotnet:main Oct 31, 2024
@amanasifkhalid amanasifkhalid deleted the fix-udiv-valuenum branch October 31, 2024 15:12
@github-actions github-actions bot locked and limited conversation to collaborators Dec 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JIT: Bad codegen on arm64 with comparison involving division

4 participants