Skip to content

JIT: Fix loop memory dependence recording for memory defined in sibling loops#106076

Merged
jakobbotsch merged 1 commit into
dotnet:mainfrom
jakobbotsch:fix-105413
Aug 7, 2024
Merged

JIT: Fix loop memory dependence recording for memory defined in sibling loops#106076
jakobbotsch merged 1 commit into
dotnet:mainfrom
jakobbotsch:fix-105413

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

During map selection VN will keep track of memory VNs that the result depends on. This is used so that we can know whether the value computed by a tree inside a loop depends on any previous memory that was defined inside the loop; if so, we cannot allow hoisting for it.

It was possible for the previous memory to be defined inside a more nested loop. Take the following example:

for (int i = 0; i < n; i++)
{
  int j = 0;
  do
  {
    s_otherField = [1];
  } while (j < n);

  s_field = true;
  Use(s_field);
}

In this case the memory dependence of the load of s_field ends up being a memory definition inside the nested loop. (One could think the dependency would come from the s_field = true block, but we do not track the memory definitions on a fine-grained basis; rather we get it from the previous memory phi def, which is good enough for hoisting.)

The logic did not properly handle this case; if the memory definition is in a more nested loop, we need to walk the ancestor loops to figure out if the definition is actually happening inside one of them. If so there is still a dependency.

Fix #105413

During map selection VN will keep track of memory VNs that the result
depends on. This is used so that we can know whether the value computed
by a tree inside a loop depends on any previous memory that was defined
inside the loop; if so, we cannot allow hoisting for it.

It was possible for the previous memory to be defined inside a more
nested loop. Take the following example:

```csharp
for (int i = 0; i < n; i++)
{
  int j = 0;
  do
  {
    s_otherField = [1];
  } while (j < n);

  s_field = true;
  Use(s_field);
}
```

In this case the memory dependence of the load of `s_field` ends up
being a memory definition inside the nested loop. (One could think the
dependency would come from the `s_field = true` block, but we do not
track the memory definitions on a fine-grained basis; rather we get it
from the previous memory phi def, which is good enough for hoisting.)

The logic did not properly handle this case; if the memory definition is
in a more nested loop, we need to walk the ancestor loops to figure out
if the definition is actually happening inside one of them. If so there
is still a dependency.

Fix dotnet#105413
@ghost ghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 7, 2024
@jakobbotsch jakobbotsch added this to the 9.0.0 milestone Aug 7, 2024
@jakobbotsch jakobbotsch marked this pull request as ready for review August 7, 2024 18:48
@jakobbotsch

Copy link
Copy Markdown
Member Author

cc @dotnet/jit-contrib PTAL @AndyAyersMS

No diffs

@jakobbotsch jakobbotsch requested a review from AndyAyersMS August 7, 2024 18:48
@jakobbotsch jakobbotsch merged commit 194fec5 into dotnet:main Aug 7, 2024
@jakobbotsch jakobbotsch deleted the fix-105413 branch August 7, 2024 21:46
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ARM64: Fuzzlyn example Debug outputs False and Release outputs True

2 participants