-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
JIT: Use faster mod for uint16 values #111535
base: main
Are you sure you want to change the base?
Conversation
@@ -540,6 +540,8 @@ enum GenTreeFlags : unsigned int | |||
|
|||
GTF_DIV_MOD_NO_OVERFLOW = 0x40000000, // GT_DIV, GT_MOD -- Div or mod definitely does not overflow. | |||
|
|||
GTF_UMOD_UINT16_OPERANDS = 0x80000000, // UMOD -- Both operands to a mod are in uint16 range. |
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.
This flag needs to be checked by GenTree::Compare
(reason N+1 that flags changing IR semantics is unfortunate IR design)
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.
I don't think we can just avoid it (not here, but in general). But perhaps we can introduce a separate Enum with changing-semantics flags or something like that
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.
I don't see why this would need to be taken into account in GenTree::Compare
. This flag, similar to GTF_IND_NONFAULTING
, only records an optimization fact.
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.
Ideally operations with different semantics should have different gtOper
, like e.g. BSWAP
and BSWAP16
do. That might not be as convenient to do in some cases, but ideally we should optimize the process of adding new types of nodes to be as painless as possible.
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.
I don't see why this would need to be taken into account in GenTree::Compare. This flag, similar to GTF_IND_NONFAULTING, only records an optimization fact.
For example head-merging a 16-bit division with a non-16-bit division would not be a legal transformation.
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.
I don't disagree that a better way to handle this would be to introduce a GT_UMOD16
that would perform true 16-bit division, ignoring the upper bits of the operands.
But in this flags model, there is no true 16 division, only 32 bit division "for which we know the operands fit into a certain range". It would be invalid IR for a node tagged with the flag to appear where the dynamic range of the operands does not actually fit. Hence, Compare
ought not to care.
What needs to care is all the places that reuse UMOD
nodes.
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.
It would be invalid IR for a node tagged with the flag to appear where the dynamic range of the operands does not actually fit.
Yes, and this can happen in head-merging if it merges a 16-bit division and a non-16-bit division and moves them across a guard on the divisor range. I view that as changing the semantics of the node (the domain of the operands is TYP_INT
, yet the value computed is different for a divisor outside [0..0xffff]).
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.
I do not think we can model this as an optimization fact. It requires us to set GTF_ORDER_SIDEEFF
on both this node and its guarding condition IR node, similar to other unmodelled control-flow dependencies we have.
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.
Hmm, I see what you are saying (that this flag should mean "a kind of true 16 bit division"). Perhaps it could use a better name then.
/azp run Fuzzlyn |
Azure Pipelines successfully started running 1 pipeline(s). |
Closes #111492
GTF_UMOD_UINT16_OPERANDS
flag during assertion propdividend % constDivisor
to(ulong)(dividend * (uint.MaxValue / divisor + 1)) * divisor) >> 32
during loweringThere aren't many diffs, but they look along the lines of
runtime/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs
Lines 2330 to 2331 in 9aa8cbf
Example use case that this makes simpler