This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Fix lowering's containment analysis. #7410
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This fixes a silent bad code generation issue that arose during internal
testing. The original repro is a test failure under COMPlus_JitStress=2.
Due to explicit null check insertion, we (eventually) end up with the
following LIR:
During lowering, we attempt to form an RMW add rooted at the final
storeIndir. The pattern matching that attempts to form RMW operations,
however, does not consider whether or not it is safe to perform the
code motion involved in making the destination and source addresses
for the operator contained. In this case, lowering moves the evaluation
of the address (i.e. the dataflow tree rooted at the add that produces
t2735) into the storeIndir. This moves a use of tmp29 across a def of
the same and causes the program to store a value to an incorrect
address.
There are many variations on this pattern. For example, given the
following C#:
The evaluation of a.Length (including the necessary null check) should
occur before the call to c.M(). The lack of correct checks for safe
code motion that caused the original repro, however, cause the JIT to
generate bad code in this case as well: the null check for a is folded
into the load of a.Length, which is then made contained by the compare.
This results in the call to c.M() executing before the null check, which
causes the program to behave incorrectly in the case that a is null.
In order to fix the code motion analysis, this change introduces a new
type,
SideEffectSet
, that can be used to summarize the side effectsof a set of nodes and check whether or not they interfere with another
set of side effects. This change then uses the new type to ensure that
it is safe to perform the code motion necessary to make an operand
contained before doing so.
This is a port of commit d857d37 from coreclr/master.