From c9140d621a97fbb0d74028522b3a048d51ed191a Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Sat, 2 Jul 2022 22:35:06 +0300 Subject: [PATCH] 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 --- src/coreclr/jit/lclmorph.cpp | 6 ++--- src/coreclr/jit/lowerloongarch64.cpp | 32 +++++++++++++++++++++++- src/coreclr/jit/morph.cpp | 37 +++++----------------------- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 108efa1925035b..bc5d4183452455 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1068,7 +1068,7 @@ class LocalAddressVisitor final : public GenTreeVisitor // | Partial | LCL_FLD | LCL_FLD | LCL_FLD | // |------------|---------|---------|---------| // - // * - On XArch/Arm64 only. + // * - On XArch/Arm64/LA only. // // |------------|------|------|--------|----------| // | SIMD | CALL | ASG | RETURN | HWI/SIMD | @@ -1086,9 +1086,9 @@ class LocalAddressVisitor final : public GenTreeVisitor if (user->IsCall()) { -#if !defined(TARGET_XARCH) && !defined(TARGET_ARM64) +#ifdef TARGET_ARM return IndirTransform::None; -#endif // !defined(TARGET_XARCH) && !defined(TARGET_ARM64) +#endif // TARGET_ARM } if (match == StructMatch::Compatible) diff --git a/src/coreclr/jit/lowerloongarch64.cpp b/src/coreclr/jit/lowerloongarch64.cpp index f0d9e5767f7975..3874a04ba122de 100644 --- a/src/coreclr/jit/lowerloongarch64.cpp +++ b/src/coreclr/jit/lowerloongarch64.cpp @@ -431,7 +431,37 @@ void Lowering::LowerPutArgStkOrSplit(GenTreePutArgStk* putArgNode) // STRUCT args (FIELD_LIST / OBJ) will always be contained. MakeSrcContained(putArgNode, src); - // Additionally, codegen supports containment of local addresses under OBJs. + // Currently, codegen does not support LCL_VAR/LCL_FLD sources, so we morph them to OBJs. + // TODO-ADDR: support the local nodes in codegen and remove this code. + if (src->OperIsLocalRead()) + { + unsigned lclNum = src->AsLclVarCommon()->GetLclNum(); + ClassLayout* layout = nullptr; + GenTree* lclAddr = nullptr; + + if (src->OperIs(GT_LCL_VAR)) + { + layout = comp->lvaGetDesc(lclNum)->GetLayout(); + lclAddr = comp->gtNewLclVarAddrNode(lclNum); + + comp->lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::IsStructArg)); + } + else + { + layout = src->AsLclFld()->GetLayout(); + lclAddr = comp->gtNewLclFldAddrNode(lclNum, src->AsLclFld()->GetLclOffs()); + } + + src->ChangeOper(GT_OBJ); + src->AsObj()->SetAddr(lclAddr); + src->AsObj()->SetLayout(layout); + src->AsObj()->gtBlkOpKind = GenTreeBlk::BlkOpKindInvalid; + src->AsObj()->gtBlkOpGcUnsafe = false; + + BlockRange().InsertBefore(src, lclAddr); + } + + // Codegen supports containment of local addresses under OBJs. if (src->OperIs(GT_OBJ) && src->AsObj()->Addr()->OperIs(GT_LCL_VAR_ADDR)) { // TODO-LOONGARCH64-CQ: support containment of LCL_FLD_ADDR too. diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 07901100d18e19..7a366338cc3759 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -1500,14 +1500,6 @@ GenTree* CallArgs::MakeTmpArgNode(Compiler* comp, CallArg* arg) { // We are passing this struct by value in multiple registers and/or on stack. argNode = comp->gtNewLclvNode(lclNum, argType); - -#ifndef TARGET_XARCH - // ARM/ARM64/LoongArch64 backends do not support LCL_VARs as sources of some stack args. - // Wrap it in an "OBJ(ADDR(...))". TODO-ADDR: delete this code once all backends support - // LCL_VAR stack args. - argNode = comp->gtNewOperNode(GT_ADDR, TYP_BYREF, argNode); - argNode = comp->gtNewObjNode(varDsc->GetLayout(), argNode); -#endif // !TARGET_XARCH } } else @@ -3694,35 +3686,18 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) { lcl = actualArg->AsLclVar(); } - if (lcl != nullptr) + if ((lcl != nullptr) && (lvaGetPromotionType(lcl->GetLclNum()) == PROMOTION_TYPE_INDEPENDENT)) { - if (lvaGetPromotionType(lcl->GetLclNum()) == PROMOTION_TYPE_INDEPENDENT) + if (argNode->OperIs(GT_LCL_VAR) || + ClassLayout::AreCompatible(argNode->AsObj()->GetLayout(), lvaGetDesc(lcl)->GetLayout())) { - if (argNode->OperIs(GT_LCL_VAR) || - ClassLayout::AreCompatible(argNode->AsObj()->GetLayout(), lvaGetDesc(lcl)->GetLayout())) - { - argNode = fgMorphLclArgToFieldlist(lcl); - } - else - { - // Set DNER to block independent promotion. - lvaSetVarDoNotEnregister(lcl->GetLclNum() DEBUGARG(DoNotEnregisterReason::IsStructArg)); - } + argNode = fgMorphLclArgToFieldlist(lcl); } -#ifdef TARGET_LOONGARCH64 - else if (argNode->TypeGet() == TYP_STRUCT) + else { - // LoongArch64 backend does not support local nodes as sources of some stack args. - if (!actualArg->OperIs(GT_OBJ)) - { - // Create an Obj of the temp to use it as a call argument. - argNode = gtNewOperNode(GT_ADDR, TYP_I_IMPL, argNode); - argNode = gtNewObjNode(lvaGetStruct(lcl->GetLclNum()), argNode); - } - // Its fields will need to be accessed by address. + // Set DNER to block independent promotion. lvaSetVarDoNotEnregister(lcl->GetLclNum() DEBUGARG(DoNotEnregisterReason::IsStructArg)); } -#endif // TARGET_LOONGARCH64 } return argNode;