From 15adc7829f141ca63288a6128f4a1f728d381c4c Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Tue, 28 Jun 2022 20:06:00 +0300 Subject: [PATCH 1/6] Enable a test on Unix x64 --- src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.cs b/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.cs index 2f83aa0685b7da..b5bfbb0b5f0dca 100644 --- a/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.cs +++ b/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.cs @@ -25,8 +25,7 @@ static bool ProblemWithOutOfBoundsLoads(out int result) { result = 100; - // TODO: enable for x64 once https://github.com/dotnet/runtime/issues/65937 has been fixed. - if (!OperatingSystem.IsLinux() || (RuntimeInformation.ProcessArchitecture == Architecture.X64)) + if (!OperatingSystem.IsLinux()) { return false; } From b40ac2bf41ba45076c77f72866892233c494dbdb Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Tue, 28 Jun 2022 20:14:53 +0300 Subject: [PATCH 2/6] Handle mis-sized structs in LA PUTARG_STK codegen --- src/coreclr/jit/codegenloongarch64.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index 7f85403db40171..a5031af1140e2c 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -6015,8 +6015,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) while (remainingSize > 0) { - var_types type; + nextIndex = structOffset / TARGET_POINTER_SIZE; + var_types type; if (remainingSize >= TARGET_POINTER_SIZE) { type = layout->GetGCPtrType(nextIndex); @@ -6026,20 +6027,21 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // the left over size is smaller than a pointer and thus can never be a GC type assert(!layout->IsGCPtr(nextIndex)); - if (remainingSize == 1) + if (remainingSize >= 4) { - type = TYP_UBYTE; + type = TYP_INT; } - else if (remainingSize == 2) + else if (remainingSize >= 2) { type = TYP_USHORT; } else { - assert(remainingSize == 4); - type = TYP_UINT; + assert(remainingSize == 1); + type = TYP_UBYTE; } } + const emitAttr attr = emitTypeSize(type); const unsigned moveSize = genTypeSize(type); assert(EA_SIZE_IN_BYTES(attr) == moveSize); @@ -6066,7 +6068,6 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) assert(argOffsetOut <= argOffsetMax); // We can't write beyond the outgoing arg area structOffset += moveSize; - nextIndex++; } } } From 5270df67a42857af80bd51937964af2aa9794cb8 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Tue, 28 Jun 2022 20:23:20 +0300 Subject: [PATCH 3/6] Handle mis-sized structs in LA PUTARG_SPLIT codegen --- src/coreclr/jit/codegenloongarch64.cpp | 58 ++++++++++++++++---------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index a5031af1140e2c..cb68bb33dd72f1 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -6226,11 +6226,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) } else // addrNode is used { - assert(addrNode != nullptr); - // TODO-Cleanup: `Lowering::NewPutArg` marks only `LCL_VAR_ADDR` as contained nowadays, - // Generate code to load the address that we need into a register - genConsumeAddress(addrNode); - addrReg = addrNode->GetRegNum(); + addrReg = genConsumeReg(addrNode); // If addrReg equal to baseReg, we use the last target register as alternative baseReg. // Because the candidate mask for the internal baseReg does not include any of the target register, @@ -6244,21 +6240,40 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) ClassLayout* layout = source->AsObj()->GetLayout(); // Put on stack first - unsigned nextIndex = treeNode->gtNumRegs; - unsigned structOffset = nextIndex * TARGET_POINTER_SIZE; - int remainingSize = treeNode->GetStackByteSize(); + unsigned structOffset = treeNode->gtNumRegs * TARGET_POINTER_SIZE; + unsigned remainingSize = layout->GetSize() - structOffset; unsigned argOffsetOut = treeNode->getArgOffset(); - // remainingSize is always multiple of TARGET_POINTER_SIZE - assert(remainingSize % TARGET_POINTER_SIZE == 0); + assert((remainingSize > 0) && (roundUp(remainingSize, TARGET_POINTER_SIZE) == treeNode->GetStackByteSize())); while (remainingSize > 0) { - var_types type = layout->GetGCPtrType(nextIndex); + var_types type; + if (remainingSize >= TARGET_POINTER_SIZE) + { + type = layout->GetGCPtrType(structOffset / TARGET_POINTER_SIZE); + } + else if (remainingSize >= 4) + { + type = TYP_INT; + } + else if (remainingSize >= 2) + { + type = TYP_USHORT; + } + else + { + assert(remainingSize == 1); + type = TYP_UBYTE; + } + emitAttr attr = emitActualTypeSize(type); + unsigned moveSize = genTypeSize(type); + + instruction loadIns = ins_Load(type); if (varNode != nullptr) { - // Load from our varNumImp source - emit->emitIns_R_S(INS_ld_d, emitTypeSize(type), baseReg, srcVarNum, structOffset); + // Load from our local source + emit->emitIns_R_S(loadIns, attr, baseReg, srcVarNum, structOffset); } else { @@ -6266,17 +6281,16 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) assert(baseReg != addrReg); // Load from our address expression source - emit->emitIns_R_R_I(INS_ld_d, emitTypeSize(type), baseReg, addrReg, structOffset); + emit->emitIns_R_R_I(loadIns, attr, baseReg, addrReg, structOffset); } - // Emit str instruction to store the register into the outgoing argument area - emit->emitIns_S_R(INS_st_d, emitTypeSize(type), baseReg, varNumOut, argOffsetOut); + // Emit the instruction to store the register into the outgoing argument area + emit->emitIns_S_R(ins_Store(type), attr, baseReg, varNumOut, argOffsetOut); + argOffsetOut += moveSize; + assert(argOffsetOut <= argOffsetMax); - argOffsetOut += TARGET_POINTER_SIZE; // We stored 4-bytes of the struct - assert(argOffsetOut <= argOffsetMax); // We can't write beyond the outgoing arg area - remainingSize -= TARGET_POINTER_SIZE; // We loaded 4-bytes of the struct - structOffset += TARGET_POINTER_SIZE; - nextIndex += 1; + remainingSize -= moveSize; + structOffset += moveSize; } // We set up the registers in order, so that we assign the last target register `baseReg` is no longer in use, @@ -6289,7 +6303,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) if (varNode != nullptr) { - // Load from our varNumImp source + // Load from our local source emit->emitIns_R_S(ins_Load(type), emitTypeSize(type), targetReg, srcVarNum, structOffset); } else From 3feddc5297dbcb615293d32337f44cf12f9737fe Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Tue, 28 Jun 2022 22:01:46 +0300 Subject: [PATCH 4/6] MisSizedStructs_ArmSplit -> MisSizedStructs_ArmArch --- .../{MisSizedStructs_ArmSplit.cs => MisSizedStructs_ArmArch.cs} | 0 ...izedStructs_ArmSplit.csproj => MisSizedStructs_ArmArch.csproj} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/tests/JIT/Directed/StructABI/{MisSizedStructs_ArmSplit.cs => MisSizedStructs_ArmArch.cs} (100%) rename src/tests/JIT/Directed/StructABI/{MisSizedStructs_ArmSplit.csproj => MisSizedStructs_ArmArch.csproj} (100%) diff --git a/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.cs b/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmArch.cs similarity index 100% rename from src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.cs rename to src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmArch.cs diff --git a/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.csproj b/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmArch.csproj similarity index 100% rename from src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.csproj rename to src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmArch.csproj From 2142a94d2b449b73476f2120972243eacac95600 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Tue, 28 Jun 2022 22:41:21 +0300 Subject: [PATCH 5/6] Add tests --- .../StructABI/MisSizedStructs_ArmArch.cs | 232 +++++++++++++++++- 1 file changed, 220 insertions(+), 12 deletions(-) diff --git a/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmArch.cs b/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmArch.cs index b5bfbb0b5f0dca..6cd2367b327286 100644 --- a/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmArch.cs +++ b/src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmArch.cs @@ -54,24 +54,109 @@ static bool ProblemWithOutOfBoundsLoads(out int result) pages[PAGE_SIZE - 1] = ByteValue; - if (CallForSplitStructWithSixteenBytes(0, *(StructWithSixteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithSixteenBytes))) != ByteValue) + // Split args on ARM. + // + if (CallForSplitStructWithSixteenBytes_Arm(0, *(StructWithSixteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithSixteenBytes))) != ByteValue) { - result = 200; + result = 216; return true; } - if (CallForSplitStructWithSeventeenBytes(0, *(StructWithSeventeenBytes*)(pages + PAGE_SIZE - sizeof(StructWithSeventeenBytes))) != ByteValue) + if (CallForSplitStructWithSeventeenBytes_Arm(0, *(StructWithSeventeenBytes*)(pages + PAGE_SIZE - sizeof(StructWithSeventeenBytes))) != ByteValue) { - result = 201; + result = 217; return true; } - if (CallForSplitStructWithEighteenBytes(0, *(StructWithEighteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithEighteenBytes))) != ByteValue) + if (CallForSplitStructWithEighteenBytes_Arm(0, *(StructWithEighteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithEighteenBytes))) != ByteValue) { - result = 202; + result = 218; return true; } - if (CallForSplitStructWithNineteenBytes(0, *(StructWithNineteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithNineteenBytes))) != ByteValue) + if (CallForSplitStructWithNineteenBytes_Arm(0, *(StructWithNineteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithNineteenBytes))) != ByteValue) { - result = 203; + result = 219; + return true; + } + + // Stack args on ARM64. + // + if (CallForStkStructWithOneByte_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithOneByte*)(pages + PAGE_SIZE - sizeof(StructWithOneByte))) != ByteValue) + { + result = 301; + return true; + } + if (CallForStkStructWithTwoBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithTwoBytes*)(pages + PAGE_SIZE - sizeof(StructWithTwoBytes))) != ByteValue) + { + result = 302; + return true; + } + if (CallForStkStructWithThreeBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithThreeBytes*)(pages + PAGE_SIZE - sizeof(StructWithThreeBytes))) != ByteValue) + { + result = 303; + return true; + } + if (CallForStkStructWithFourBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithFourBytes*)(pages + PAGE_SIZE - sizeof(StructWithFourBytes))) != ByteValue) + { + result = 304; + return true; + } + if (CallForStkStructWithFiveBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithFiveBytes*)(pages + PAGE_SIZE - sizeof(StructWithFiveBytes))) != ByteValue) + { + result = 305; + return true; + } + if (CallForStkStructWithSixBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithSixBytes*)(pages + PAGE_SIZE - sizeof(StructWithSixBytes))) != ByteValue) + { + result = 306; + return true; + } + if (CallForStkStructWithSevenBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithSevenBytes*)(pages + PAGE_SIZE - sizeof(StructWithSevenBytes))) != ByteValue) + { + result = 307; + return true; + } + if (CallForStkStructWithEightBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithEightBytes*)(pages + PAGE_SIZE - sizeof(StructWithEightBytes))) != ByteValue) + { + result = 308; + return true; + } + if (CallForStkStructWithNineBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithNineBytes*)(pages + PAGE_SIZE - sizeof(StructWithNineBytes))) != ByteValue) + { + result = 309; + return true; + } + if (CallForStkStructWithTenBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithTenBytes*)(pages + PAGE_SIZE - sizeof(StructWithTenBytes))) != ByteValue) + { + result = 310; + return true; + } + if (CallForStkStructWithElevenBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithElevenBytes*)(pages + PAGE_SIZE - sizeof(StructWithElevenBytes))) != ByteValue) + { + result = 311; + return true; + } + if (CallForStkStructWithTwelveBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithTwelveBytes*)(pages + PAGE_SIZE - sizeof(StructWithTwelveBytes))) != ByteValue) + { + result = 312; + return true; + } + if (CallForStkStructWithThirteenBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithThirteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithThirteenBytes))) != ByteValue) + { + result = 313; + return true; + } + if (CallForStkStructWithFourteenBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithFourteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithFourteenBytes))) != ByteValue) + { + result = 314; + return true; + } + if (CallForStkStructWithFifteenBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithFifteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithFifteenBytes))) != ByteValue) + { + result = 315; + return true; + } + if (CallForStkStructWithSixteenBytes_Arm64(0, 0, 0, 0, 0, 0, 0, *(StructWithSixteenBytes*)(pages + PAGE_SIZE - sizeof(StructWithSixteenBytes))) != ByteValue) + { + result = 316; return true; } @@ -81,16 +166,64 @@ static bool ProblemWithOutOfBoundsLoads(out int result) } [MethodImpl(MethodImplOptions.NoInlining)] - private static byte CallForSplitStructWithSixteenBytes(long arg0, StructWithSixteenBytes splitArg) => splitArg.Bytes[15]; + private static byte CallForSplitStructWithSixteenBytes_Arm(long arg0, StructWithSixteenBytes splitArg) => splitArg.Bytes[15]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForSplitStructWithSeventeenBytes_Arm(long arg0, StructWithSeventeenBytes splitArg) => splitArg.Bytes[16]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForSplitStructWithEighteenBytes_Arm(long arg0, StructWithEighteenBytes splitArg) => splitArg.Bytes[17]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForSplitStructWithNineteenBytes_Arm(long arg0, StructWithNineteenBytes splitArg) => splitArg.Bytes[18]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithOneByte_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithOneByte stkArg) => stkArg.Bytes[0]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithTwoBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithTwoBytes stkArg) => stkArg.Bytes[1]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithThreeBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithThreeBytes stkArg) => stkArg.Bytes[2]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithFourBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithFourBytes stkArg) => stkArg.Bytes[3]; [MethodImpl(MethodImplOptions.NoInlining)] - private static byte CallForSplitStructWithSeventeenBytes(long arg0, StructWithSeventeenBytes splitArg) => splitArg.Bytes[16]; + private static byte CallForStkStructWithFiveBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithFiveBytes stkArg) => stkArg.Bytes[4]; [MethodImpl(MethodImplOptions.NoInlining)] - private static byte CallForSplitStructWithEighteenBytes(long arg0, StructWithEighteenBytes splitArg) => splitArg.Bytes[17]; + private static byte CallForStkStructWithSixBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithSixBytes stkArg) => stkArg.Bytes[5]; [MethodImpl(MethodImplOptions.NoInlining)] - private static byte CallForSplitStructWithNineteenBytes(long arg0, StructWithNineteenBytes splitArg) => splitArg.Bytes[18]; + private static byte CallForStkStructWithSevenBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithSevenBytes stkArg) => stkArg.Bytes[6]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithEightBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithEightBytes stkArg) => stkArg.Bytes[7]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithNineBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithNineBytes stkArg) => stkArg.Bytes[8]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithTenBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithTenBytes stkArg) => stkArg.Bytes[9]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithElevenBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithElevenBytes stkArg) => stkArg.Bytes[10]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithTwelveBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithTwelveBytes stkArg) => stkArg.Bytes[11]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithThirteenBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithThirteenBytes stkArg) => stkArg.Bytes[12]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithFourteenBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithFourteenBytes stkArg) => stkArg.Bytes[13]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithFifteenBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithFifteenBytes stkArg) => stkArg.Bytes[14]; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static byte CallForStkStructWithSixteenBytes_Arm64(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, StructWithSixteenBytes stkArg) => stkArg.Bytes[15]; [DllImport("libc")] private static extern void* mmap(void* addr, nuint length, int prot, int flags, int fd, nuint offset); @@ -101,6 +234,81 @@ static bool ProblemWithOutOfBoundsLoads(out int result) [DllImport("libc")] private static extern int munmap(void* addr, nuint length); + struct StructWithOneByte + { + public fixed byte Bytes[1]; + } + + struct StructWithTwoBytes + { + public fixed byte Bytes[2]; + } + + struct StructWithThreeBytes + { + public fixed byte Bytes[3]; + } + + struct StructWithFourBytes + { + public fixed byte Bytes[4]; + } + + struct StructWithFiveBytes + { + public fixed byte Bytes[5]; + } + + struct StructWithSixBytes + { + public fixed byte Bytes[6]; + } + + struct StructWithSevenBytes + { + public fixed byte Bytes[7]; + } + + struct StructWithEightBytes + { + public fixed byte Bytes[8]; + } + + struct StructWithNineBytes + { + public fixed byte Bytes[9]; + } + + struct StructWithTenBytes + { + public fixed byte Bytes[10]; + } + + struct StructWithElevenBytes + { + public fixed byte Bytes[11]; + } + + struct StructWithTwelveBytes + { + public fixed byte Bytes[12]; + } + + struct StructWithThirteenBytes + { + public fixed byte Bytes[13]; + } + + struct StructWithFourteenBytes + { + public fixed byte Bytes[14]; + } + + struct StructWithFifteenBytes + { + public fixed byte Bytes[15]; + } + struct StructWithSixteenBytes { public fixed byte Bytes[16]; From bd1ead0381b8222a764688c54d4b38a9542633e1 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Tue, 28 Jun 2022 20:29:09 +0300 Subject: [PATCH 6/6] Do not spill mis-sized stack args All backends support them. --- src/coreclr/jit/morph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 07901100d18e19..06dd575b43983d 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -1022,7 +1022,7 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) // TODO-Arm: This optimization is not implemented for ARM32 // so we skip this for ARM32 until it is ported to use RyuJIT backend // - if (argx->OperGet() == GT_OBJ) + if (argx->OperIs(GT_OBJ) && (arg.AbiInfo.GetRegNum() != REG_STK)) { GenTreeObj* argObj = argx->AsObj(); unsigned structSize = argObj->GetLayout()->GetSize();