-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Fix phase order problem with throw helper blocks #97201
Conversation
Throw helper blocks are created in morph, then possibly removed if unnecessary in StackLevelSetter (under optimization). However, there was a case where StackLevelSetter removed an OVERFLOW throw helper block after optimization proved it unnecessary because of a constant zero dividend, but between StackLevelSetter and codegen, LSRA introduced a RELOAD node above the constant zero that `GenTree::CanDivOrModPossiblyOverflow()` didn't understand, thus causing it to think that overflow was possible. Codegen looked for the OVERFLOW throw helper block and couldn't find it. There are multiple fixes here, somewhat "defense in depth": - If `StackLevelSetter::SetThrowHelperBlocks()` determines a node can't throw divide-by-zero or ArithmeticException (overflow), it marks the node GTF_DIV_MOD_NO_BY_ZERO / GTF_DIV_MOD_NO_OVERFLOW, respectively. This is what morph does earlier in compilation. - `genMarkLabelsForCodegen()` does not mark throw helper blocks where `acdUsed` is false, to avoid marking deleted blocks. - More asserts are added that `acdUsed` is true when codegen goes to generate a branch to a throw helper. - `GenTree::OperExceptions` / `CanDivOrModPossiblyOverflow` are changed to skip COPY/RELOAD nodes. Fixes dotnet#96224
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsThrow helper blocks are created in morph, then possibly removed if unnecessary in StackLevelSetter (under optimization). However, there was a case where StackLevelSetter removed an OVERFLOW throw helper block after optimization proved it unnecessary because of a constant zero dividend, but between StackLevelSetter and codegen, LSRA introduced a RELOAD node above the constant zero that There are multiple fixes here, somewhat "defense in depth":
Fixes #96224
|
This is presumably fallout from #95379 |
@AndyAyersMS PTAL |
Throw helper blocks are created in morph, then possibly removed if unnecessary in StackLevelSetter (under optimization). However, there was a case where StackLevelSetter removed an OVERFLOW throw helper block after optimization proved it unnecessary because of a constant zero dividend, but between StackLevelSetter and codegen, LSRA introduced a RELOAD node above the constant zero that `GenTree::CanDivOrModPossiblyOverflow()` didn't understand, thus causing it to think that overflow was possible. Codegen looked for the OVERFLOW throw helper block and couldn't find it. There are multiple fixes here, somewhat "defense in depth": - If `StackLevelSetter::SetThrowHelperBlocks()` determines a node can't throw divide-by-zero or ArithmeticException (overflow), it marks the node GTF_DIV_MOD_NO_BY_ZERO / GTF_DIV_MOD_NO_OVERFLOW, respectively. This is what morph does earlier in compilation. - `genMarkLabelsForCodegen()` does not mark throw helper blocks where `acdUsed` is false, to avoid marking deleted blocks. - More asserts are added that `acdUsed` is true when codegen goes to generate a branch to a throw helper. - `GenTree::OperExceptions` / `CanDivOrModPossiblyOverflow` are changed to skip COPY/RELOAD nodes. Fixes dotnet#96224
Throw helper blocks are created in morph, then possibly removed if unnecessary in StackLevelSetter (under optimization). However, there was a case where StackLevelSetter removed an OVERFLOW throw helper block after optimization proved it unnecessary because of a constant zero dividend, but between StackLevelSetter and codegen, LSRA introduced a RELOAD node above the constant zero that
GenTree::CanDivOrModPossiblyOverflow()
didn't understand, thus causing it to think that overflow was possible. Codegen looked for the OVERFLOW throw helper block and couldn't find it.There are multiple fixes here, somewhat "defense in depth":
StackLevelSetter::SetThrowHelperBlocks()
determines a node can't throw divide-by-zero or ArithmeticException (overflow), it marks the node GTF_DIV_MOD_NO_BY_ZERO / GTF_DIV_MOD_NO_OVERFLOW, respectively. This is what morph does earlier in compilation.genMarkLabelsForCodegen()
does not mark throw helper blocks whereacdUsed
is false, to avoid marking deleted blocks.acdUsed
is true when codegen goes to generate a branch to a throw helper.GenTree::OperExceptions
/CanDivOrModPossiblyOverflow
are changed to skip COPY/RELOAD nodes.Fixes #96224