Skip to content

Conversation

jakobbotsch
Copy link
Member

  • For string accesses we also produce ARR_ADDR, so we must take care to use GenTreeArrAddr::GetFirstElemOffset instead of hardcoding OFFSETOF__CORINFO_Array__data

  • There are cases where VN is fully able to prove that bound < ARR_LENGTH(vn), specifically when the array is stored in a static readonly field. In those cases everything reduces to constants, so allow VN to try to prove it but fall back to our manual logic otherwise.

  • Rephrase the fallback as a VN test as well. In a standard for (;i < arr.Length;) loop we have a bound on the backedge of the shape ARR_LENGTH(array) - 1. The previous strategy was to syntactically check if the LHS was such an array length on the same array as the base of the add recurrence.

    Instead of doing that, we can ask more generally for any shape x - c whether we know that x <= ARR_LENGTH(array). In the usual case of x == ARR_LENGTH(array) this is trivially true and VN knows that. However, there are other cases where this is provable by RBO due to a dominating compare; particularly loop cloning introduces these dominating compares when cloning loops of the shape for (; i < n;). This fixes JIT: StaysWithinManagedObject should be able to handle more cloned loops patterns #105087.

- For string accesses we also produce `ARR_ADDR`, so we must take care
  to use `GenTreeArrAddr::GetFirstElemOffset` instead of hardcoding
  `OFFSETOF__CORINFO_Array__data`
- There are cases where VN is fully able to prove that bound <
  ARR_LENGTH(vn), specifically when the array is stored in a static
  readonly field. In those cases everything reduces to constants, so
  allow VN to try to prove it but fall back to our manual logic
  otherwise.
- Rephrase the fallback as a VN test as well. In a standard `for (;i <
  arr.Length;)` loop we have a bound on the backedge of the shape
  `ARR_LENGTH(array) - 1`. The previous strategy was to syntactically
  check if the LHS was such an array length on the same array as the
  base of the add recurrence.

  Instead of doing that, we can ask more generally for any shape `x - c`
  whether we know that `x <= ARR_LENGTH(array)`. In the usual case of `x
  == ARR_LENGTH(array)` this is trivially true and VN knows that.
  However, there are other cases where this is provable by RBO due to a
  dominating compare; particularly loop cloning introduces these
  dominating compares when cloning loops of the shape `for (; i < n;)`.
  This fixes dotnet#105087.
@ghost ghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jul 18, 2024
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@jakobbotsch
Copy link
Member Author

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs with strength reduction enabled.

Surprisingly we have significantly fewer hits here for arm64 -- I wonder why that is. Will take a closer look tomorrow, but in any case this PR should be ok as is.

@jakobbotsch jakobbotsch requested a review from AndyAyersMS July 18, 2024 22:25
@jakobbotsch jakobbotsch merged commit 823cd67 into dotnet:main Jul 19, 2024
@jakobbotsch jakobbotsch deleted the StaysWithinManagedObject-improvements branch July 19, 2024 07:51
@jakobbotsch
Copy link
Member Author

Surprisingly we have significantly fewer hits here for arm64 -- I wonder why that is. Will take a closer look tomorrow, but in any case this PR should be ok as is.

The reason is that on arm64 we frequently hoist out the array + 0x10 part of the array indexing, and this inhibits the reasoning of StaysWithinManagedObject. Hopefully shouldn't be too hard to work around.

@github-actions github-actions bot locked and limited conversation to collaborators Aug 19, 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.

JIT: StaysWithinManagedObject should be able to handle more cloned loops patterns
2 participants