diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index f5ac76f6c50067..ba92d14b234ea4 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -2151,17 +2151,18 @@ void CodeGen::instGen_Set_Reg_To_Base_Plus_Imm(emitAttr size, insFlags flags DEBUGARG(size_t targetHandle) DEBUGARG(GenTreeFlags gtFlags)) { - // If the imm values < 12 bits, we can use a single "add rsvd, reg2, #imm". - // Otherwise, use "mov rsvd, #imm", followed up "add rsvd, reg2, rsvd". + // If the immediate can be encoded by add/sub, use a single instruction. + // Otherwise, use "mov dstReg, #imm", followed by "add dstReg, baseReg, dstReg". + // Keep baseReg as the second operand in the fallback since it can be SP. - if (imm < 4096) + if (emitter::emitIns_valid_imm_for_add(imm, size)) { - GetEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, dstReg, baseReg, imm); + GetEmitter()->emitIns_R_R_I(INS_add, size, dstReg, baseReg, imm); } else { instGen_Set_Reg_To_Imm(size, dstReg, imm); - GetEmitter()->emitIns_R_R_R(INS_add, size, dstReg, dstReg, baseReg); + GetEmitter()->emitIns_R_R_R(INS_add, size, dstReg, baseReg, dstReg); } } diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 49a836ed881ae5..a02a0285dce107 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -15017,8 +15017,8 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR // First load/store tmpReg with the large offset constant codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); // Then add the base register - // rd = rd + base - emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->GetRegNum()); + // rd = base + rd + emitIns_R_R_R(INS_add, addType, tmpReg, memBase->GetRegNum(), tmpReg); noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg)); noway_assert(tmpReg != index->GetRegNum()); diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_130437/GitHub_130437.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_130437/GitHub_130437.csproj new file mode 100644 index 00000000000000..8f66634434cd1a --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/GitHub_130437/GitHub_130437.csproj @@ -0,0 +1,14 @@ + + + $(RepoRoot)src/coreclr/.nuget/Microsoft.NET.Sdk.IL/Microsoft.NET.Sdk.IL.targets.template + True + true + true + + + + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_130437/GitHub_130437.il b/src/tests/JIT/Regression/JitBlue/GitHub_130437/GitHub_130437.il new file mode 100644 index 00000000000000..fe7732cccd3393 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/GitHub_130437/GitHub_130437.il @@ -0,0 +1,207 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern mscorlib {} +.assembly extern System.Numerics.Vectors {} +.assembly extern System.Runtime.Intrinsics {} + +.assembly GitHub_130437 {} +.module GitHub_130437.dll + +.class private explicit ansi sealed beforefieldinit LargeFrame + extends [mscorlib]System.ValueType +{ + .pack 1 + .size 8192 +} + +.class private auto ansi beforefieldinit GitHub_130437 + extends [mscorlib]System.Object +{ + .method public hidebysig static int32 + Main() cil managed + { + .entrypoint + .maxstack 2 + + call bool [System.Runtime.Intrinsics]System.Runtime.Intrinsics.Arm.Sve2::get_IsSupported() + brtrue.s SVE_SUPPORTED + + ldc.i4.s 100 + ret + + SVE_SUPPORTED: + call int64 GitHub_130437::RunBasicScenario_UnsafeRead() + ldc.i4.s 44 + conv.i8 + ceq + brfalse.s FAIL + + ldc.i4.s 100 + ret + + FAIL: + ldc.i4.m1 + ret + } + + .method private hidebysig static int64 + RunBasicScenario_UnsafeRead() cil managed noinlining + { + .maxstack 4 + .locals init ( + // The mask local must be allocated above the large frame local so the + // SP-based predicate spill/reload uses a large positive offset. + [0] valuetype [System.Numerics.Vectors]System.Numerics.Vector`1 mask, + [1] valuetype LargeFrame largeFrame, + [2] uint32[] baseArray, + [3] int64[] maskArray, + [4] int64[] offsetsArray, + [5] uint32* pinned basePinned, + [6] int64* pinned maskPinned, + [7] int64* pinned offsetsPinned, + [8] valuetype [System.Numerics.Vectors]System.Numerics.Vector`1 result1, + [9] valuetype [System.Numerics.Vectors]System.Numerics.Vector`1 result2, + [10] int32 index) + + ldc.i4 1024 + newarr [mscorlib]System.UInt32 + stloc.2 + + ldloc.2 + ldc.i4.0 + ldc.i4.s 20 + stelem.i4 + + ldc.i4.s 64 + newarr [mscorlib]System.Int64 + stloc.3 + + ldc.i4.0 + stloc.s index + + FILL_MASK: + ldloc.s index + ldc.i4.s 64 + bge.s FILL_MASK_DONE + + ldloc.3 + ldloc.s index + ldc.i4.1 + conv.i8 + stelem.i8 + + ldloc.s index + ldc.i4.1 + add + stloc.s index + br.s FILL_MASK + + FILL_MASK_DONE: + ldc.i4.s 64 + newarr [mscorlib]System.Int64 + stloc.s offsetsArray + + ldloc.2 + ldc.i4.0 + ldelema [mscorlib]System.UInt32 + stloc.s basePinned + + ldloc.3 + ldc.i4.0 + ldelema [mscorlib]System.Int64 + stloc.s maskPinned + + ldloc.s offsetsArray + ldc.i4.0 + ldelema [mscorlib]System.Int64 + stloc.s offsetsPinned + + ldloc.s maskPinned + ldobj valuetype [System.Numerics.Vectors]System.Numerics.Vector`1 + stloc.0 + + ldloca.s largeFrame + call void GitHub_130437::TouchLargeFrame(valuetype LargeFrame&) + + ldloc.0 + ldloc.s basePinned + ldloc.s offsetsPinned + ldobj valuetype [System.Numerics.Vectors]System.Numerics.Vector`1 + call valuetype [System.Numerics.Vectors]System.Numerics.Vector`1 [System.Runtime.Intrinsics]System.Runtime.Intrinsics.Arm.Sve2::GatherVectorUInt32WithByteOffsetsZeroExtendNonTemporal(valuetype [System.Numerics.Vectors]System.Numerics.Vector`1, uint32*, valuetype [System.Numerics.Vectors]System.Numerics.Vector`1) + stloc.s result1 + + ldloc.0 + ldloc.s basePinned + ldloc.s offsetsPinned + ldobj valuetype [System.Numerics.Vectors]System.Numerics.Vector`1 + call valuetype [System.Numerics.Vectors]System.Numerics.Vector`1 [System.Runtime.Intrinsics]System.Runtime.Intrinsics.Arm.Sve2::GatherVectorUInt32WithByteOffsetsZeroExtendNonTemporal(valuetype [System.Numerics.Vectors]System.Numerics.Vector`1, uint32*, valuetype [System.Numerics.Vectors]System.Numerics.Vector`1) + stloc.s result2 + + ldloca.s result1 + ldc.i4.0 + call instance !0 valuetype [System.Numerics.Vectors]System.Numerics.Vector`1::get_Item(int32) + + ldloca.s result2 + ldc.i4.0 + call instance !0 valuetype [System.Numerics.Vectors]System.Numerics.Vector`1::get_Item(int32) + add + + ldloca.s largeFrame + call int64 GitHub_130437::SumLargeFrame(valuetype LargeFrame&) + add + ret + } + + .method private hidebysig static void + TouchLargeFrame(valuetype LargeFrame& frame) cil managed noinlining + { + .maxstack 3 + + ldarg.0 + conv.u + ldc.i4.0 + add + ldc.i4.1 + stind.i1 + + ldarg.0 + conv.u + ldc.i4 4096 + add + ldc.i4.2 + stind.i1 + + ldarg.0 + conv.u + ldc.i4 8191 + add + ldc.i4.3 + stind.i1 + + ret + } + + .method private hidebysig static int64 + SumLargeFrame(valuetype LargeFrame& frame) cil managed noinlining + { + .maxstack 3 + + ldarg.0 + conv.u + ldc.i4.0 + add + ldind.u1 + conv.i8 + + ldarg.0 + conv.u + ldc.i4 8191 + add + ldind.u1 + conv.i8 + add + + ret + } +}