Skip to content

Commit 2ed43b6

Browse files
authored
ARM64-SVE: Allow op inside conditionalselect to be non HWintrinsic (dotnet#107180)
* ARM64-SVE: Allow op inside conditionselect to be non HWintrinsic * Add Sve.IsSupported check to test
1 parent ac4b7c6 commit 2ed43b6

File tree

3 files changed

+103
-33
lines changed

3 files changed

+103
-33
lines changed

src/coreclr/jit/lowerarmarch.cpp

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4050,47 +4050,49 @@ GenTree* Lowering::LowerHWIntrinsicCndSel(GenTreeHWIntrinsic* cndSelNode)
40504050
GenTree* nestedOp1 = nestedCndSel->Op(1);
40514051
GenTree* nestedOp2 = nestedCndSel->Op(2);
40524052
assert(varTypeIsMask(nestedOp1));
4053-
assert(nestedOp2->OperIsHWIntrinsic());
40544053

4055-
NamedIntrinsic nestedOp2Id = nestedOp2->AsHWIntrinsic()->GetHWIntrinsicId();
4056-
4057-
// If the nested op uses Pg/Z, then inactive lanes will result in zeros, so can only transform if
4058-
// op3 is all zeros. Such a Csel operation is absorbed into the instruction when emitted. Skip this optimisation
4059-
// when the nestedOp is a reduce operation.
4060-
4061-
if (nestedOp1->IsMaskAllBitsSet() && !HWIntrinsicInfo::IsReduceOperation(nestedOp2Id) &&
4062-
(!HWIntrinsicInfo::IsZeroingMaskedOperation(nestedOp2Id) || op3->IsVectorZero()))
4054+
if (nestedOp2->OperIsHWIntrinsic())
40634055
{
4064-
GenTree* nestedOp2 = nestedCndSel->Op(2);
4065-
GenTree* nestedOp3 = nestedCndSel->Op(3);
4056+
NamedIntrinsic nestedOp2Id = nestedOp2->AsHWIntrinsic()->GetHWIntrinsicId();
40664057

4067-
JITDUMP("lowering nested ConditionalSelect HWIntrinisic (before):\n");
4068-
DISPTREERANGE(BlockRange(), cndSelNode);
4069-
JITDUMP("\n");
4058+
// If the nested op uses Pg/Z, then inactive lanes will result in zeros, so can only transform if
4059+
// op3 is all zeros. Such a Csel operation is absorbed into the instruction when emitted. Skip this
4060+
// optimisation when the nestedOp is a reduce operation.
40704061

4071-
// Transform:
4072-
//
4073-
// CndSel(mask, CndSel(AllTrue, embeddedMask(trueValOp2), trueValOp3), op3) to
4074-
// CndSel(mask, embedded(trueValOp2), op3)
4075-
//
4076-
cndSelNode->Op(2) = nestedCndSel->Op(2);
4077-
if (nestedOp3->IsMaskZero())
4078-
{
4079-
BlockRange().Remove(nestedOp3);
4080-
}
4081-
else
4062+
if (nestedOp1->IsMaskAllBitsSet() && !HWIntrinsicInfo::IsReduceOperation(nestedOp2Id) &&
4063+
(!HWIntrinsicInfo::IsZeroingMaskedOperation(nestedOp2Id) || op3->IsVectorZero()))
40824064
{
4083-
nestedOp3->SetUnusedValue();
4084-
}
4065+
GenTree* nestedOp2 = nestedCndSel->Op(2);
4066+
GenTree* nestedOp3 = nestedCndSel->Op(3);
4067+
4068+
JITDUMP("lowering nested ConditionalSelect HWIntrinisic (before):\n");
4069+
DISPTREERANGE(BlockRange(), cndSelNode);
4070+
JITDUMP("\n");
4071+
4072+
// Transform:
4073+
//
4074+
// CndSel(mask, CndSel(AllTrue, embeddedMask(trueValOp2), trueValOp3), op3) to
4075+
// CndSel(mask, embedded(trueValOp2), op3)
4076+
//
4077+
cndSelNode->Op(2) = nestedCndSel->Op(2);
4078+
if (nestedOp3->IsMaskZero())
4079+
{
4080+
BlockRange().Remove(nestedOp3);
4081+
}
4082+
else
4083+
{
4084+
nestedOp3->SetUnusedValue();
4085+
}
40854086

4086-
BlockRange().Remove(nestedOp1);
4087-
BlockRange().Remove(nestedCndSel);
4087+
BlockRange().Remove(nestedOp1);
4088+
BlockRange().Remove(nestedCndSel);
40884089

4089-
JITDUMP("lowering nested ConditionalSelect HWIntrinisic (after):\n");
4090-
DISPTREERANGE(BlockRange(), cndSelNode);
4091-
JITDUMP("\n");
4090+
JITDUMP("lowering nested ConditionalSelect HWIntrinisic (after):\n");
4091+
DISPTREERANGE(BlockRange(), cndSelNode);
4092+
JITDUMP("\n");
40924093

4093-
return cndSelNode;
4094+
return cndSelNode;
4095+
}
40944096
}
40954097
}
40964098
else if (op1->IsMaskAllBitsSet())
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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+
using Xunit;
5+
using System.Runtime.CompilerServices;
6+
7+
// Generated by Fuzzlyn v2.3 on 2024-08-23 10:25:51
8+
// Run on Arm64 Windows
9+
// Seed: 13938901376337307772-vectort,vector64,vector128,armsve
10+
// Reduced from 210.5 KiB to 1.1 KiB in 00:02:19
11+
// Hits JIT assert in Release:
12+
// Assertion failed 'nestedOp2->OperIsHWIntrinsic()' in 'Program:Main(Fuzzlyn.ExecutionServer.IRuntime)' during 'Lowering nodeinfo' (IL size 119; hash 0xade6b36b; FullOpts)
13+
//
14+
// File: C:\dev\dotnet\runtime2\src\coreclr\jit\lowerarmarch.cpp Line: 4062
15+
//
16+
using System;
17+
using System.Numerics;
18+
using System.Runtime.Intrinsics;
19+
using System.Runtime.Intrinsics.Arm;
20+
21+
public struct S0
22+
{
23+
public ulong F5;
24+
}
25+
26+
public class C0
27+
{
28+
public int F1;
29+
}
30+
31+
public class Runtime_1068867
32+
{
33+
public static S0 s_7;
34+
public static byte s_14;
35+
36+
[Fact]
37+
public static void TestEntryPoint()
38+
{
39+
if (Sve.IsSupported)
40+
{
41+
var vr12 = new C0();
42+
var vr14 = vr12.F1;
43+
var vr15 = Vector128.CreateScalar(vr14).AsVector();
44+
var vr16 = Vector128.CreateScalar(0).AsVector();
45+
var vr17 = Vector128.CreateScalar(0).AsVector();
46+
var vr18 = Vector128.CreateScalar(0).AsVector();
47+
var vr19 = Vector128.CreateScalar(1).AsVector();
48+
var vr20 = Sve.ConditionalSelect(vr17, vr18, vr19);
49+
var vr21 = Vector128.CreateScalar(0).AsVector();
50+
var vr22 = Sve.ConditionalSelect(vr16, vr20, vr21);
51+
Consume(vr22);
52+
}
53+
}
54+
55+
[MethodImpl(MethodImplOptions.NoInlining)]
56+
static void Consume<T>(T val)
57+
{
58+
}
59+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<Optimize>True</Optimize>
4+
<NoWarn>$(NoWarn),SYSLIB5003</NoWarn>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<Compile Include="$(MSBuildProjectName).cs" />
8+
</ItemGroup>
9+
</Project>

0 commit comments

Comments
 (0)