diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index e977b649dc5a2..174637d5be6e2 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -1660,7 +1660,24 @@ bool Compiler::CheckHWIntrinsicImmRange(NamedIntrinsic intrinsic, { assert(!mustExpand); // The imm-HWintrinsics that do not accept all imm8 values may throw - // ArgumentOutOfRangeException when the imm argument is not in the valid range + // ArgumentOutOfRangeException when the imm argument is not in the valid range, + // unless the intrinsic can be transformed into one that does accept all imm8 values + +#ifdef TARGET_ARM64 + switch (intrinsic) + { + case NI_AdvSimd_ShiftRightLogical: + *useFallback = true; + break; + + // TODO: Implement more AdvSimd fallbacks in Compiler::impNonConstFallback + + default: + assert(*useFallback == false); + break; + } +#endif // TARGET_ARM64 + return false; } } diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 384c2fc4f3b1d..9647cc826ca08 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -564,7 +564,26 @@ void HWIntrinsicInfo::lookupImmBounds( // GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, CorInfoType simdBaseJitType) { - return nullptr; + switch (intrinsic) + { + case NI_AdvSimd_ShiftRightLogical: + { + // AdvSimd.ShiftRightLogical be replaced with AdvSimd.ShiftLogical, which takes op2 in a simd register + + GenTree* op2 = impPopStack().val; + GenTree* op1 = impSIMDPopStack(); + + // AdvSimd.ShiftLogical does right-shifts with negative immediates, hence the negation + GenTree* tmpOp = + gtNewSimdCreateBroadcastNode(simdType, gtNewOperNode(GT_NEG, genActualType(op2->TypeGet()), op2), + simdBaseJitType, genTypeSize(simdType)); + return gtNewSimdHWIntrinsicNode(simdType, op1, tmpOp, NI_AdvSimd_ShiftLogical, simdBaseJitType, + genTypeSize(simdType)); + } + + default: + return nullptr; + } } //------------------------------------------------------------------------ diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105621/Runtime_105621.cs b/src/tests/JIT/Regression/JitBlue/Runtime_105621/Runtime_105621.cs new file mode 100644 index 0000000000000..ee772943aef89 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_105621/Runtime_105621.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Generated by Fuzzlyn v2.1 on 2024-07-28 20:49:49 +// Run on Arm64 Linux +// Seed: 14204794442367797079-vectort,vector64,vector128,armadvsimd,armadvsimdarm64,armaes,armarmbase,armarmbasearm64,armcrc32,armcrc32arm64,armdp,armrdm,armrdmarm64,armsha1,armsha256 +// Reduced from 12.6 KiB to 0.4 KiB in 00:00:17 +// Debug: Throws 'System.ArgumentOutOfRangeException' +// Release: Runs successfully +using System; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +public class Runtime_105621 +{ + [Fact] + public static void TestShiftByZero() + { + if (AdvSimd.IsSupported) + { + var vr3 = Vector64.Create(0); + var vr4 = AdvSimd.ShiftRightLogical(vr3, 0); + Assert.Equal(vr3, vr4); + } + } + + [Fact] + public static void TestShiftToZero() + { + if (AdvSimd.IsSupported) + { + var vr3 = Vector64.Create(128); + var vr4 = AdvSimd.ShiftRightLogical(vr3, 9); + Assert.Equal(vr4, Vector64.Zero); + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105621/Runtime_105621.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_105621/Runtime_105621.csproj new file mode 100644 index 0000000000000..eca04c5491840 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_105621/Runtime_105621.csproj @@ -0,0 +1,8 @@ + + + False + + + + + \ No newline at end of file