Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 28 additions & 46 deletions src/coreclr/jit/lsraarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1944,7 +1944,8 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou
GenTreeHWIntrinsic* embOp2Node = intrin.op2->AsHWIntrinsic();
size_t numArgs = embOp2Node->GetOperandCount();
const HWIntrinsic intrinEmb(embOp2Node);
numArgs = embOp2Node->GetOperandCount();
numArgs = embOp2Node->GetOperandCount();
GenTree* prefUseNode = nullptr;

if (HWIntrinsicInfo::IsFmaIntrinsic(intrinEmb.id))
{
Expand All @@ -1961,44 +1962,15 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou
unsigned resultOpNum =
embOp2Node->GetResultOpNumForRmwIntrinsic(user, intrinEmb.op1, intrinEmb.op2, intrinEmb.op3);

GenTree* emitOp1 = intrinEmb.op1;
GenTree* emitOp2 = intrinEmb.op2;
GenTree* emitOp3 = intrinEmb.op3;

if (resultOpNum == 2)
{
// op2 = op1 + (op2 * op3)
std::swap(emitOp1, emitOp3);
std::swap(emitOp1, emitOp2);
// op1 = (op1 * op2) + op3
}
else if (resultOpNum == 3)
if (resultOpNum == 0)
{
// op3 = op1 + (op2 * op3)
std::swap(emitOp1, emitOp3);
// op1 = (op1 * op2) + op3
prefUseNode = embOp2Node->Op(1);
}
else
{
// op1 = op1 + (op2 * op3)
// Nothing needs to be done
assert(resultOpNum >= 1 && resultOpNum <= 3);
prefUseNode = embOp2Node->Op(resultOpNum);
}

GenTree* ops[] = {intrinEmb.op1, intrinEmb.op2, intrinEmb.op3};
for (GenTree* op : ops)
{
if (op == emitOp1)
{
tgtPrefUse = BuildUse(op);
srcCount++;
}
else if (op == emitOp2 || op == emitOp3)
{
srcCount += BuildDelayFreeUses(op, emitOp1);
}
}

srcCount += BuildDelayFreeUses(intrin.op3, emitOp1);
}
else
{
Expand Down Expand Up @@ -2045,22 +2017,32 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou
{
prefUseOpNum = 2;
}
GenTree* prefUseNode = embOp2Node->Op(prefUseOpNum);
for (size_t argNum = 1; argNum <= numArgs; argNum++)
prefUseNode = embOp2Node->Op(prefUseOpNum);
}

for (size_t argNum = 1; argNum <= numArgs; argNum++)
{
GenTree* node = embOp2Node->Op(argNum);

if (node == prefUseNode)
{
if (argNum == prefUseOpNum)
{
tgtPrefUse = BuildUse(prefUseNode);
srcCount += 1;
}
else
{
srcCount += BuildDelayFreeUses(embOp2Node->Op(argNum), prefUseNode);
}
tgtPrefUse = BuildUse(node);
srcCount++;
}
else
{
RefPosition* useRefPosition = nullptr;

srcCount += BuildDelayFreeUses(intrin.op3, prefUseNode);
int uses = BuildDelayFreeUses(node, nullptr, RBM_NONE, &useRefPosition);
srcCount += uses;

// It is a hard requirement that these are not allocated to the same register as the destination,
// so verify no optimizations kicked in to skip setting the delay-free.
assert((useRefPosition != nullptr && useRefPosition->delayRegFree) || (uses == 0));
}
}

srcCount += BuildDelayFreeUses(intrin.op3, prefUseNode);
}
else if (intrin.op2 != nullptr)
{
Expand Down
40 changes: 40 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_106864/Runtime_106864.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

Comment thread
a74nh marked this conversation as resolved.
using Xunit;

// Generated by Fuzzlyn v2.3 on 2024-08-23 09:12:06
// Run on Arm64 Windows
// Seed: 9639718980642677114-vectort,vector64,vector128,armsve
// Reduced from 52.6 KiB to 0.4 KiB in 00:00:26
// Hits JIT assert in Release:
// Assertion failed 'targetReg != embMaskOp2Reg' in 'Program:Main(Fuzzlyn.ExecutionServer.IRuntime)' during 'Generate code' (IL size 32; hash 0xade6b36b; FullOpts)
//
// File: C:\dev\dotnet\runtime2\src\coreclr\jit\hwintrinsiccodegenarm64.cpp Line: 818
//
using System;
using System.Numerics;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;

public class C1
{
public Vector<short> F1;
}

public class Runtime_106864
{
public static C1 s_2 = new C1();

[Fact]
public static void TestEntryPoint()
{
if (Sve.IsSupported)
{
C1 vr2 = s_2;
var vr3 = vr2.F1;
var vr4 = vr2.F1;
vr2.F1 = Sve.Max(vr3, vr4);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Optimize>True</Optimize>
<NoWarn>$(NoWarn),SYSLIB5003</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>
54 changes: 54 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_106867/Runtime_106867.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Xunit;

// Generated by Fuzzlyn v2.3 on 2024-08-23 10:10:06
// Run on Arm64 Windows
// Seed: 13584223539078280353-vectort,vector64,vector128,armsve
// Reduced from 87.4 KiB to 0.8 KiB in 00:00:52
// Hits JIT assert in Release:
// Assertion failed 'secondId->idReg1() != secondId->idReg4()' in 'S0:M6(ubyte,double):this' during 'Emit code' (IL size 81; hash 0x596acd7c; FullOpts)
//
// File: C:\dev\dotnet\runtime2\src\coreclr\jit\emitarm64sve.cpp Line: 18601
//
using System;
using System.Numerics;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;

public struct S0
{
public void M6(byte arg0, double arg1)
{
var vr0 = Vector128.CreateScalar(119.12962f).AsVector();
Comment thread
a74nh marked this conversation as resolved.
var vr3 = Runtime_106867.s_2;
var vr4 = Vector128.CreateScalar(1f).AsVector();
var vr5 = Runtime_106867.s_2;
var vr2 = Sve.FusedMultiplySubtractNegated(vr3, vr4, vr5);
if ((Sve.ConditionalExtractLastActiveElement(vr0, 0, vr2) < 0))
{
this = this;
}
}
}

public class Runtime_106867
{
public static Vector<float> s_2;
public static double[] s_5 = new double[]
{
0
};
public static byte s_16;

[Fact]
public static void TestEntryPoint()
{
if (Sve.IsSupported)
{
var vr6 = s_5[0];
new S0().M6(s_16, vr6);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Optimize>True</Optimize>
<NoWarn>$(NoWarn),SYSLIB5003</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Xunit;
using System.Runtime.CompilerServices;

// Generated by Fuzzlyn v2.3 on 2024-08-23 10:12:51
// Run on Arm64 Windows
// Seed: 4576767951799510057-vectort,vector64,vector128,armsve
// Reduced from 32.2 KiB to 0.5 KiB in 00:00:25
// Hits JIT assert in Release:
// Assertion failed 'secondId->idReg1() != secondId->idReg3()' in 'Program:Main(Fuzzlyn.ExecutionServer.IRuntime)' during 'Emit code' (IL size 55; hash 0xade6b36b; FullOpts)
//
// File: C:\dev\dotnet\runtime2\src\coreclr\jit\emitarm64sve.cpp Line: 18600
//
using System;
using System.Numerics;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;

public class Runtime_106866_2
{
[Fact]
public static void TestEntryPoint()
{
if (Sve.IsSupported)
{
Vector<short> vr4 = default(Vector<short>);
vr4 = Sve.MultiplyAdd(vr4, vr4, vr4);
var vr5 = (short)0;
var vr6 = Vector128.CreateScalar(vr5).AsVector();
var vr7 = (short)0;
var vr8 = Sve.ConditionalExtractLastActiveElement(vr6, vr7, vr4);
Consume(vr8);
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void Consume<T>(T val)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Optimize>True</Optimize>
<NoWarn>$(NoWarn),SYSLIB5003</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>