JIT: contain shifts into byref ADD on arm64 - #132221
Conversation
|
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. |
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
There was a problem hiding this comment.
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_BYREFparents inLowering::IsContainableUnaryOrBinaryOpon ARM64. - Relax ARM64 codegen debug assertions for contained
MUL/SHIFT/ROR/CASTcases to permitTYP_BYREFresults.
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). |
| if (parentNode->isContained()) | ||
| return false; | ||
|
|
||
| if (!varTypeIsIntegral(parentNode)) | ||
| if (!varTypeIsIntegral(parentNode) && !parentNode->TypeIs(TYP_BYREF)) | ||
| return false; |
|
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 🙂 |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0d35d524-d3e6-4da0-85a3-75a5d07d9143
dce9393 to
91e1409
Compare
There was a problem hiding this comment.
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_BYREFparents 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;
Ah got it, for .NET 12 then! 🚀 |
|
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. |
There was a problem hiding this comment.
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)); |
Experiment to get the SPMI diffs. On arm64
IsContainableUnaryOrBinaryOpbails out for any byref-producing parent (TYP_BYREFhas noVTF_INT), so shifts are never folded intoref-based address arithmetic:Some noticeable diffs