-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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