Skip to content

Commit c9140d6

Browse files
Enable TYP_STRUCT LCL_VAR/LCL_FLD call args on LA (#71327)
* Support "PUTARG_STK/SPLIT(STRUCT LCL_VAR/LCL_FLD)" on LA * LA: [local] morph * Delete now-not-needed "OBJ(ADDR(LCL_VAR))" wrapping
1 parent 6b8d056 commit c9140d6

File tree

3 files changed

+40
-35
lines changed

3 files changed

+40
-35
lines changed

src/coreclr/jit/lclmorph.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
10681068
// | Partial | LCL_FLD | LCL_FLD | LCL_FLD |
10691069
// |------------|---------|---------|---------|
10701070
//
1071-
// * - On XArch/Arm64 only.
1071+
// * - On XArch/Arm64/LA only.
10721072
//
10731073
// |------------|------|------|--------|----------|
10741074
// | SIMD | CALL | ASG | RETURN | HWI/SIMD |
@@ -1086,9 +1086,9 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
10861086

10871087
if (user->IsCall())
10881088
{
1089-
#if !defined(TARGET_XARCH) && !defined(TARGET_ARM64)
1089+
#ifdef TARGET_ARM
10901090
return IndirTransform::None;
1091-
#endif // !defined(TARGET_XARCH) && !defined(TARGET_ARM64)
1091+
#endif // TARGET_ARM
10921092
}
10931093

10941094
if (match == StructMatch::Compatible)

src/coreclr/jit/lowerloongarch64.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,37 @@ void Lowering::LowerPutArgStkOrSplit(GenTreePutArgStk* putArgNode)
431431
// STRUCT args (FIELD_LIST / OBJ) will always be contained.
432432
MakeSrcContained(putArgNode, src);
433433

434-
// Additionally, codegen supports containment of local addresses under OBJs.
434+
// Currently, codegen does not support LCL_VAR/LCL_FLD sources, so we morph them to OBJs.
435+
// TODO-ADDR: support the local nodes in codegen and remove this code.
436+
if (src->OperIsLocalRead())
437+
{
438+
unsigned lclNum = src->AsLclVarCommon()->GetLclNum();
439+
ClassLayout* layout = nullptr;
440+
GenTree* lclAddr = nullptr;
441+
442+
if (src->OperIs(GT_LCL_VAR))
443+
{
444+
layout = comp->lvaGetDesc(lclNum)->GetLayout();
445+
lclAddr = comp->gtNewLclVarAddrNode(lclNum);
446+
447+
comp->lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::IsStructArg));
448+
}
449+
else
450+
{
451+
layout = src->AsLclFld()->GetLayout();
452+
lclAddr = comp->gtNewLclFldAddrNode(lclNum, src->AsLclFld()->GetLclOffs());
453+
}
454+
455+
src->ChangeOper(GT_OBJ);
456+
src->AsObj()->SetAddr(lclAddr);
457+
src->AsObj()->SetLayout(layout);
458+
src->AsObj()->gtBlkOpKind = GenTreeBlk::BlkOpKindInvalid;
459+
src->AsObj()->gtBlkOpGcUnsafe = false;
460+
461+
BlockRange().InsertBefore(src, lclAddr);
462+
}
463+
464+
// Codegen supports containment of local addresses under OBJs.
435465
if (src->OperIs(GT_OBJ) && src->AsObj()->Addr()->OperIs(GT_LCL_VAR_ADDR))
436466
{
437467
// TODO-LOONGARCH64-CQ: support containment of LCL_FLD_ADDR too.

src/coreclr/jit/morph.cpp

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,14 +1500,6 @@ GenTree* CallArgs::MakeTmpArgNode(Compiler* comp, CallArg* arg)
15001500
{
15011501
// We are passing this struct by value in multiple registers and/or on stack.
15021502
argNode = comp->gtNewLclvNode(lclNum, argType);
1503-
1504-
#ifndef TARGET_XARCH
1505-
// ARM/ARM64/LoongArch64 backends do not support LCL_VARs as sources of some stack args.
1506-
// Wrap it in an "OBJ(ADDR(...))". TODO-ADDR: delete this code once all backends support
1507-
// LCL_VAR stack args.
1508-
argNode = comp->gtNewOperNode(GT_ADDR, TYP_BYREF, argNode);
1509-
argNode = comp->gtNewObjNode(varDsc->GetLayout(), argNode);
1510-
#endif // !TARGET_XARCH
15111503
}
15121504
}
15131505
else
@@ -3694,35 +3686,18 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg)
36943686
{
36953687
lcl = actualArg->AsLclVar();
36963688
}
3697-
if (lcl != nullptr)
3689+
if ((lcl != nullptr) && (lvaGetPromotionType(lcl->GetLclNum()) == PROMOTION_TYPE_INDEPENDENT))
36983690
{
3699-
if (lvaGetPromotionType(lcl->GetLclNum()) == PROMOTION_TYPE_INDEPENDENT)
3691+
if (argNode->OperIs(GT_LCL_VAR) ||
3692+
ClassLayout::AreCompatible(argNode->AsObj()->GetLayout(), lvaGetDesc(lcl)->GetLayout()))
37003693
{
3701-
if (argNode->OperIs(GT_LCL_VAR) ||
3702-
ClassLayout::AreCompatible(argNode->AsObj()->GetLayout(), lvaGetDesc(lcl)->GetLayout()))
3703-
{
3704-
argNode = fgMorphLclArgToFieldlist(lcl);
3705-
}
3706-
else
3707-
{
3708-
// Set DNER to block independent promotion.
3709-
lvaSetVarDoNotEnregister(lcl->GetLclNum() DEBUGARG(DoNotEnregisterReason::IsStructArg));
3710-
}
3694+
argNode = fgMorphLclArgToFieldlist(lcl);
37113695
}
3712-
#ifdef TARGET_LOONGARCH64
3713-
else if (argNode->TypeGet() == TYP_STRUCT)
3696+
else
37143697
{
3715-
// LoongArch64 backend does not support local nodes as sources of some stack args.
3716-
if (!actualArg->OperIs(GT_OBJ))
3717-
{
3718-
// Create an Obj of the temp to use it as a call argument.
3719-
argNode = gtNewOperNode(GT_ADDR, TYP_I_IMPL, argNode);
3720-
argNode = gtNewObjNode(lvaGetStruct(lcl->GetLclNum()), argNode);
3721-
}
3722-
// Its fields will need to be accessed by address.
3698+
// Set DNER to block independent promotion.
37233699
lvaSetVarDoNotEnregister(lcl->GetLclNum() DEBUGARG(DoNotEnregisterReason::IsStructArg));
37243700
}
3725-
#endif // TARGET_LOONGARCH64
37263701
}
37273702

37283703
return argNode;

0 commit comments

Comments
 (0)