Skip to content

JIT: contain shifts into byref ADD on arm64 - #132221

Open
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:arm64-contain-shift-byref
Open

JIT: contain shifts into byref ADD on arm64#132221
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:arm64-contain-shift-byref

Conversation

@EgorBo

@EgorBo EgorBo commented Aug 12, 2026

Copy link
Copy Markdown
Member

Experiment to get the SPMI diffs. On arm64 IsContainableUnaryOrBinaryOp bails out for any byref-producing parent (TYP_BYREF has no VTF_INT), so shifts are never folded into ref-based address arithmetic:

;; base + (index * 24), e.g. CastCache.TryGet

-            add     w5, w3, #1
-            add     x5, x5, x5,  LSL #1
-            lsl     x5, x5, #3
-            add     x5, x5, x0
-            ldar    w6, [x5]
+            add     w5, w3, #1
+            add     x5, x5, x5,  LSL #1
+            add     x5, x0, x5,  LSL #3
+            ldar    w6, [x5]

Some noticeable diffs

Copilot AI lite review requested due to automatic review settings August 12, 2026 17:17
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 12, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 6 pipeline(s).
10 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables ARM64 containment of shift/mul (and related) unary/binary ops under byref-producing parents so address arithmetic like base + (index << cns) can be emitted as a single add ... LSL #imm form instead of separate lsl + add.

Changes:

  • Allow TYP_BYREF parents in Lowering::IsContainableUnaryOrBinaryOp on ARM64.
  • Relax ARM64 codegen debug assertions for contained MUL/SHIFT/ROR/CAST cases to permit TYP_BYREF results.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/coreclr/jit/lowerarmarch.cpp Permits containment decisions for byref-typed parents so shifts/muls can fold into byref address arithmetic.
src/coreclr/jit/codegenarm64.cpp Updates asserts to allow byref-typed binary results when emitting combined ops (e.g., add ... LSL #imm, madd).

Comment on lines 196 to 200
if (parentNode->isContained())
return false;

if (!varTypeIsIntegral(parentNode))
if (!varTypeIsIntegral(parentNode) && !parentNode->TypeIs(TYP_BYREF))
return false;
@adamperlin

Copy link
Copy Markdown
Contributor

Are there any particular downsides here? This seems like a minimal code change for some pretty positive diffs!

@EgorBo

EgorBo commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

Are there any particular downsides here? This seems like a minimal code change for some pretty positive diffs!

Shouldn't be any, just didn't plan to merge it into .NET 11 🙂

@EgorBo EgorBo added this to the 12.0.0 milestone Aug 12, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0d35d524-d3e6-4da0-85a3-75a5d07d9143
Copilot AI review requested due to automatic review settings August 12, 2026 21:56
@EgorBo
EgorBo force-pushed the arm64-contain-shift-byref branch from dce9393 to 91e1409 Compare August 12, 2026 21:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/coreclr/jit/lowerarmarch.cpp:200

  • The comment describing the parent-node type restriction is now slightly inaccurate: TYP_BYREF parents are allowed (for address arithmetic), even though they're not integral. Updating the bullet helps future readers understand why the byref exception exists.
    if (parentNode->isContained())
        return false;

    if (!varTypeIsIntegral(parentNode) && !parentNode->TypeIs(TYP_BYREF))
        return false;

@adamperlin

Copy link
Copy Markdown
Contributor

Are there any particular downsides here? This seems like a minimal code change for some pretty positive diffs!

Shouldn't be any, just didn't plan to merge it into .NET 11 🙂

Ah got it, for .NET 12 then! 🚀

@EgorBo
EgorBo marked this pull request as ready for review August 13, 2026 00:53
Copilot AI review requested due to automatic review settings August 13, 2026 00:53
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 6 pipeline(s).
10 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

src/coreclr/jit/lowerarmarch.cpp:200

  • The comment above this check says the parent must be “operating on an integer”, but this change explicitly allows TYP_BYREF parents as well. Updating the comment avoids future confusion about why BYREF is permitted here.
    if (!varTypeIsIntegral(parentNode) && !parentNode->TypeIs(TYP_BYREF))
        return false;

src/coreclr/jit/codegenarm64.cpp:2802

  • This path can now produce BYREF results (due to the updated asserts). The emitAttr passed to emitIns_R_R_R_I should include EA_BYREF_FLG when tree is TYP_BYREF; otherwise the emitter will treat the destination as non-byref for GC/byref liveness updates.
        // ROR is only contained under AND/OR/XOR parents, which are never TYP_BYREF.

src/coreclr/jit/codegenarm64.cpp:2845

  • Similar to the MUL/shift contained paths, this contained CAST path can now produce a TYP_BYREF result. The emitIns_R_R_R call uses emitActualTypeSize(tree) (size-only), so it won’t mark the instruction as producing a byref in the emitter’s idGCref tracking. The emitted instruction should use an emitAttr with EA_BYREF_FLG when tree->TypeIs(TYP_BYREF).
        assert(varTypeIsIntegral(tree) || tree->TypeIs(TYP_BYREF));

else if (op2->OperIs(GT_LSH, GT_RSH, GT_RSZ) && op2->isContained())
{
assert(varTypeIsIntegral(tree));
assert(varTypeIsIntegral(tree) || tree->TypeIs(TYP_BYREF));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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.

3 participants