Repository navigation
[JIT] Rationalize: Re-run pre-order processing on identity shuffle rewrite in PreOrderVisit - #134910
adamperlin wants to merge 8 commits into
Conversation
…ionalize::PreOrderVisit
The replacement loop exits only after node and *use are equal, so the ARM64-specific reload is unnecessary. Also remove trailing whitespace from the adjacent comment. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: Successfully started running 5 pipeline(s). 11 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
|
@dotnet/jit-contrib PTAL |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The reported Checked-build regression needs a targeted test to prevent recurrence.
Review effort: Balanced
Findings: 1
What changed in this PR
Fixes JIT rationalization so replacement intrinsic nodes receive pre-order processing.
Changes:
- Repeats intrinsic rewriting until the node remains unchanged.
- Ensures nested deferred hardware intrinsics are converted to user calls.
| File | Description |
|---|---|
src/coreclr/jit/rationalize.cpp |
Reprocesses rewritten intrinsic nodes during rationalization. |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
| // The below is a loop, because rewriting an intrinsic or HW intrinsic as a user call | ||
| // may replace the node with another node which also needs the same pre-order processing. | ||
| // Continue until no replacement is made. | ||
| do |
There was a problem hiding this comment.
Is this a potential algorithmic complexity problem? Can we reduce the amount of looping/walking we need to do somehow as presumably this is uncommon and doesn't need everything to rewalk?
There was a problem hiding this comment.
I agree, can the transformation which does this instead ensure that it does the necessary processing before returning?
There was a problem hiding this comment.
I believe there is a potential algorithmic complexity problem for a parent-child chain of identity-shuffle's that are eliminated:
SHUFFLE_1 identity [deferred user call]
|____ SHUFFLE_2 identity
...
|___SHUFFLE_N identity
|__ T
Each iteration of RewriteHWIntrinsicAsUserCall strips one level away and re-runs fgSetTreeSeq over the child (unchanged) sub-tree chain at each iteration, leading to O(n^2) behavior where n is the chain length. Moving the re-processing down into RewriteHWIntrinsicAsUserCall doesn't necessarily fix the complexity issue in this worst case, but we could maybe optimize specifically the identity shuffle case to avoid re-processing unchanged sub-trees?
There was a problem hiding this comment.
@tannergooding I believe the issue should be addressed now; I added an optimized path for when we have an identity shuffle that returns one of its operands unchanged.
There was a problem hiding this comment.
Can the path that creates the new operand or moves it into a position where it won't be visited naturally just call the walk recursively on it?
Modifying the root visit seems like a big hammer and it also has non trivial TP costs.
There was a problem hiding this comment.
Got it, that makes sense. I updated this PR to pass the visitor through to RewriteHWIntrinsicAsUserCall so that we can re-invoke the PreOrderVisit on the path that moves the operand!
There was a problem hiding this comment.
@tannergooding can you take another look here?
…reOrderVisit in identity shuffle case
…rewrite-hw-intrinsic-user-call
PreOrderVisitPreOrderVisit

Resolves #133787; This case comes up with IR that looks like the following:
The outer shuffle is the identity, so it is folded away as part of RewriteHwIntrinsicAsUserCall during PreOrderVisit. The inner
ShiftRightLogical128BitLane-- which needs to be re-written back to a GT_CALL since it has a non-constant arg -- is the replacement node, but it is never processed by the preorder visitor. If we get back a different node fromRewrite*Intrinsic, we should re-do the processing logic on that new node.