-
Notifications
You must be signed in to change notification settings - Fork 5.2k
JIT: Make effect handling in lowering less conservative #92710
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
Conversation
The interference checking in lowering bases some of its checks on GenTree::gtFlags. This is conservative since it includes effect flags of operands. For LIR this does not really make sense and ends up being conservative. This PR replaces the relevant uses of gtFlags with a new GenTree::OperEffects() that computes the relevant effect flags for the node, excluding operands. We already know how to recompute effect flags other than GTF_GLOB_REF and GTF_ORDER_SIDEEFF. This PR adds functions for these as well (the GTF_GLOB_REF version GenTree::OperRequiresGlobRefFlag is courtesy of @SingleAccretion). For GTF_ORDER_SIDEEFF we add a GenTree::OperSupportsOrderingSideEffect which captures explicitly (and conservatively) the current cases where we are setting the flag, and only allows these cases to support the flag. Setting the flag for other cases may result in the flag being removed or ignored. Fix dotnet#92699
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsThe interference checking in lowering bases some of its checks on GenTree::gtFlags. This is conservative since it includes effect flags of operands. For LIR this does not really make sense and ends up being conservative. This PR replaces the relevant uses of gtFlags with a new GenTree::OperEffects() that computes the relevant effect flags for the node, excluding operands. We already know how to recompute effect flags other than GTF_GLOB_REF and GTF_ORDER_SIDEEFF. This PR adds functions for these as well (the GTF_GLOB_REF version For GTF_ORDER_SIDEEFF we add a GenTree::OperSupportsOrderingSideEffect which captures explicitly (and conservatively) the current cases where we are setting the flag, and only allows these cases to support the flag. Setting the flag for other cases may result in the flag being removed or ignored. Fix #92699
|
/azp run runtime-coreclr superpmi-diffs, runtime-coreclr superpmi-replay |
Azure Pipelines successfully started running 2 pipeline(s). |
cc @dotnet/jit-contrib PTAL @BruceForstall @kunalspathak Diffs, mainly from new containment opportunities and |
/azp run Fuzzlyn, runtime-coreclr jitstress, runtime-coreclr libraries-jitstress |
Azure Pipelines successfully started running 3 pipeline(s). |
src/coreclr/jit/gentree.h
Outdated
// True if this indirection is invariant. | ||
bool IsInvariantLoad() const | ||
{ | ||
return (gtFlags & GTF_IND_INVARIANT) != 0; |
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 also had an assert(!isInvariant || OperIs(GT_IND, GT_BLK));
here to exclude stores. Worth adding?
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.
Added it
//------------------------------------------------------------------------------ | ||
// OperRequiresGlobRefFlag : Check whether the operation requires GTF_GLOB_REF | ||
// flag regardless of the children's flags. | ||
// |
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.
// | |
// | |
// Globally visible stores and loads, as well as some equivalently modeled | |
// operations, require the GLOB_REF flag to be set on the node. | |
// |
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.
Expanded on this a bit in the remarks.
// parent may be ok as long as it does not break ordering dependencies of the | ||
// operand. | ||
// | ||
bool GenTree::OperSupportsOrderingSideEffect() const |
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.
Do you have ideas on how to make sure that this method does not silently drop ordering effects when we start using it for new nodes?
For example, say someone is implementing non-null assertion propagation for GT_ARR_LENGTH
family of operators. They will set the flag, just as current code does for indirs, and it will show up in dumps and all, but the effect will be silently dropped.
Perhaps add a setter for GTF_ORDER_SIDEEFF
with an assert (there is SetAllEffectsFlags
& Co already, but they are used to propagate flags upwards, so, not very suitable)?
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 can add assert in fgdiagnostic to ensure that GTF_ORDER_SIDEEFF
implies that OperSupportsOrderingSideEffect() || (any operand has the flag)
.
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.
Doing this requires making sure we propagate/unset these flags in all the same places as the other flags... That's probably a good thing to do down the road, but I think for now I will skip it and think about doing that separately.
Let me add something like SetHasOrderingSideEffect()
with the assert in it for this PR.
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.
Doing this did make me notice that I missed GT_NULLCHECK
in OperSupportsOrderingSideEffect
though, so definitely worth to have something.
case GT_CALL: | ||
return AsCall()->HasSideEffects(comp, /* ignoreExceptions */ true); |
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 was apparently in my second commit - GT_ALLOCOBJ
should be here as well with return AsAllocObj()->gtHelperHasSideEffects;
The failures are known according to build analysis. The Fuzzlyn failures look like #92537 |
The interference checking in lowering bases some of its checks on GenTree::gtFlags. This is conservative since it includes effect flags of operands, which does not make much sense for LIR.
This PR replaces the relevant uses of gtFlags with a new GenTree::OperEffects() that computes the relevant effect flags for the node, excluding operands. We already know how to recompute effect flags other than GTF_GLOB_REF and GTF_ORDER_SIDEEFF. This PR adds functions for these as well (the GTF_GLOB_REF version
GenTree::OperRequiresGlobRefFlag is courtesy of @SingleAccretion).
For GTF_ORDER_SIDEEFF we add a GenTree::OperSupportsOrderingSideEffect which captures explicitly (and conservatively) the current cases where we are setting the flag, and only allows these cases to support the flag. Setting the flag for other cases may result in the flag being removed or ignored.
Fix #92699
Example:
Codegen before:
Codegen after: