Skip to content

Commit 74c608d

Browse files
JIT: Add out-of-bounds fallback for AdvSimd.ShiftRightLogical (#105777)
Fixes #105621. When its immediate is out-of-bounds, AdvSimd.ShiftRightLogical can be transformed into AdvSimd.ShiftLogical, which takes the immediate in a register. This means AdvSimd.ShiftRightLogical will no longer throw ArgumentOutOfRangeException in Debug or Release; when optimizing, we'd previously fold the intrinsic away, thus creating behavioral discrepancies.
1 parent 71d8ae6 commit 74c608d

File tree

4 files changed

+84
-2
lines changed

4 files changed

+84
-2
lines changed

src/coreclr/jit/hwintrinsic.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1660,7 +1660,24 @@ bool Compiler::CheckHWIntrinsicImmRange(NamedIntrinsic intrinsic,
16601660
{
16611661
assert(!mustExpand);
16621662
// The imm-HWintrinsics that do not accept all imm8 values may throw
1663-
// ArgumentOutOfRangeException when the imm argument is not in the valid range
1663+
// ArgumentOutOfRangeException when the imm argument is not in the valid range,
1664+
// unless the intrinsic can be transformed into one that does accept all imm8 values
1665+
1666+
#ifdef TARGET_ARM64
1667+
switch (intrinsic)
1668+
{
1669+
case NI_AdvSimd_ShiftRightLogical:
1670+
*useFallback = true;
1671+
break;
1672+
1673+
// TODO: Implement more AdvSimd fallbacks in Compiler::impNonConstFallback
1674+
1675+
default:
1676+
assert(*useFallback == false);
1677+
break;
1678+
}
1679+
#endif // TARGET_ARM64
1680+
16641681
return false;
16651682
}
16661683
}

src/coreclr/jit/hwintrinsicarm64.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,26 @@ void HWIntrinsicInfo::lookupImmBounds(
564564
//
565565
GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, CorInfoType simdBaseJitType)
566566
{
567-
return nullptr;
567+
switch (intrinsic)
568+
{
569+
case NI_AdvSimd_ShiftRightLogical:
570+
{
571+
// AdvSimd.ShiftRightLogical be replaced with AdvSimd.ShiftLogical, which takes op2 in a simd register
572+
573+
GenTree* op2 = impPopStack().val;
574+
GenTree* op1 = impSIMDPopStack();
575+
576+
// AdvSimd.ShiftLogical does right-shifts with negative immediates, hence the negation
577+
GenTree* tmpOp =
578+
gtNewSimdCreateBroadcastNode(simdType, gtNewOperNode(GT_NEG, genActualType(op2->TypeGet()), op2),
579+
simdBaseJitType, genTypeSize(simdType));
580+
return gtNewSimdHWIntrinsicNode(simdType, op1, tmpOp, NI_AdvSimd_ShiftLogical, simdBaseJitType,
581+
genTypeSize(simdType));
582+
}
583+
584+
default:
585+
return nullptr;
586+
}
568587
}
569588

570589
//------------------------------------------------------------------------
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
// Generated by Fuzzlyn v2.1 on 2024-07-28 20:49:49
5+
// Run on Arm64 Linux
6+
// Seed: 14204794442367797079-vectort,vector64,vector128,armadvsimd,armadvsimdarm64,armaes,armarmbase,armarmbasearm64,armcrc32,armcrc32arm64,armdp,armrdm,armrdmarm64,armsha1,armsha256
7+
// Reduced from 12.6 KiB to 0.4 KiB in 00:00:17
8+
// Debug: Throws 'System.ArgumentOutOfRangeException'
9+
// Release: Runs successfully
10+
using System;
11+
using System.Runtime.Intrinsics;
12+
using System.Runtime.Intrinsics.Arm;
13+
using Xunit;
14+
15+
public class Runtime_105621
16+
{
17+
[Fact]
18+
public static void TestShiftByZero()
19+
{
20+
if (AdvSimd.IsSupported)
21+
{
22+
var vr3 = Vector64.Create<byte>(0);
23+
var vr4 = AdvSimd.ShiftRightLogical(vr3, 0);
24+
Assert.Equal(vr3, vr4);
25+
}
26+
}
27+
28+
[Fact]
29+
public static void TestShiftToZero()
30+
{
31+
if (AdvSimd.IsSupported)
32+
{
33+
var vr3 = Vector64.Create<byte>(128);
34+
var vr4 = AdvSimd.ShiftRightLogical(vr3, 9);
35+
Assert.Equal(vr4, Vector64<byte>.Zero);
36+
}
37+
}
38+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<Optimize>False</Optimize>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<Compile Include="$(MSBuildProjectName).cs" />
7+
</ItemGroup>
8+
</Project>

0 commit comments

Comments
 (0)