Skip to content

Commit 3f9a441

Browse files
authored
Fix SIMD12 spills (#102736)
1 parent 7e2e874 commit 3f9a441

File tree

6 files changed

+104
-10
lines changed

6 files changed

+104
-10
lines changed

src/coreclr/jit/codegenlinear.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -937,9 +937,20 @@ void CodeGen::genSpillVar(GenTree* tree)
937937
// but we will kill the var in the reg (below).
938938
if (!varDsc->IsAlwaysAliveInMemory())
939939
{
940-
instruction storeIns = ins_Store(lclType, compiler->isSIMDTypeLocalAligned(varNum));
941940
assert(varDsc->GetRegNum() == tree->GetRegNum());
942-
inst_TT_RV(storeIns, size, tree, tree->GetRegNum());
941+
#if defined(FEATURE_SIMD)
942+
if (lclType == TYP_SIMD12)
943+
{
944+
// Store SIMD12 to stack as 12 bytes
945+
GetEmitter()->emitStoreSimd12ToLclOffset(varNum, tree->AsLclVarCommon()->GetLclOffs(),
946+
tree->GetRegNum(), nullptr);
947+
}
948+
else
949+
#endif
950+
{
951+
instruction storeIns = ins_Store(lclType, compiler->isSIMDTypeLocalAligned(varNum));
952+
inst_TT_RV(storeIns, size, tree, tree->GetRegNum());
953+
}
943954
}
944955

945956
// We should only have both GTF_SPILL (i.e. the flag causing this method to be called) and

src/coreclr/jit/emitarm64.cpp

+21-5
Original file line numberDiff line numberDiff line change
@@ -17064,12 +17064,28 @@ void emitter::emitStoreSimd12ToLclOffset(unsigned varNum, unsigned offset, regNu
1706417064
// store lower 8 bytes
1706517065
emitIns_S_R(INS_str, EA_8BYTE, dataReg, varNum, offset);
1706617066

17067-
// Extract upper 4-bytes from data
17068-
regNumber tmpReg = codeGen->internalRegisters.GetSingle(tmpRegProvider);
17069-
emitIns_R_R_I(INS_mov, EA_4BYTE, tmpReg, dataReg, 2);
17067+
if (codeGen->internalRegisters.Count(tmpRegProvider) == 0)
17068+
{
17069+
// We don't have temp regs - let's do two shuffles then
17070+
17071+
// [0,1,2,3] -> [2,3,0,1]
17072+
emitIns_R_R_R_I(INS_ext, EA_16BYTE, dataReg, dataReg, dataReg, 8, INS_OPTS_16B);
17073+
17074+
// store lower 4 bytes
17075+
emitIns_S_R(INS_str, EA_4BYTE, dataReg, varNum, offset + 8);
17076+
17077+
// Restore dataReg to its previous state: [2,3,0,1] -> [0,1,2,3]
17078+
emitIns_R_R_R_I(INS_ext, EA_16BYTE, dataReg, dataReg, dataReg, 8, INS_OPTS_16B);
17079+
}
17080+
else
17081+
{
17082+
// Extract upper 4-bytes from data
17083+
regNumber tmpReg = codeGen->internalRegisters.GetSingle(tmpRegProvider);
17084+
emitIns_R_R_I(INS_mov, EA_4BYTE, tmpReg, dataReg, 2);
1707017085

17071-
// 4-byte write
17072-
emitIns_S_R(INS_str, EA_4BYTE, tmpReg, varNum, offset + 8);
17086+
// 4-byte write
17087+
emitIns_S_R(INS_str, EA_4BYTE, tmpReg, varNum, offset + 8);
17088+
}
1707317089
}
1707417090
#endif // FEATURE_SIMD
1707517091

src/coreclr/jit/emitxarch.cpp

+15-2
Original file line numberDiff line numberDiff line change
@@ -5620,7 +5620,7 @@ void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
56205620
// varNum - the variable on the stack to use as a base;
56215621
// offset - the offset from the varNum;
56225622
// dataReg - the src reg with SIMD12 value;
5623-
// tmpRegProvider - a tree to grab a tmp reg from if needed.
5623+
// tmpRegProvider - a tree to grab a tmp reg from if needed (can be null).
56245624
//
56255625
void emitter::emitStoreSimd12ToLclOffset(unsigned varNum, unsigned offset, regNumber dataReg, GenTree* tmpRegProvider)
56265626
{
@@ -5635,7 +5635,7 @@ void emitter::emitStoreSimd12ToLclOffset(unsigned varNum, unsigned offset, regNu
56355635
// Extract and store upper 4 bytes
56365636
emitIns_S_R_I(INS_extractps, EA_16BYTE, varNum, offset + 8, dataReg, 2);
56375637
}
5638-
else
5638+
else if (tmpRegProvider != nullptr)
56395639
{
56405640
regNumber tmpReg = codeGen->internalRegisters.GetSingle(tmpRegProvider);
56415641
assert(isFloatReg(tmpReg));
@@ -5646,6 +5646,19 @@ void emitter::emitStoreSimd12ToLclOffset(unsigned varNum, unsigned offset, regNu
56465646
// Store upper 4 bytes
56475647
emitIns_S_R(INS_movss, EA_4BYTE, tmpReg, varNum, offset + 8);
56485648
}
5649+
else
5650+
{
5651+
// We don't have temp regs - let's do two shuffles then
5652+
5653+
// [0,1,2,3] -> [2,3,0,1]
5654+
emitIns_R_R_I(INS_pshufd, EA_16BYTE, dataReg, dataReg, 78);
5655+
5656+
// Store upper 4 bytes
5657+
emitIns_S_R(INS_movss, EA_4BYTE, dataReg, varNum, offset + 8);
5658+
5659+
// Restore dataReg to its previous state: [2,3,0,1] -> [0,1,2,3]
5660+
emitIns_R_R_I(INS_pshufd, EA_16BYTE, dataReg, dataReg, 78);
5661+
}
56495662
}
56505663
#endif // FEATURE_SIMD
56515664

src/coreclr/jit/lsra.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -8596,7 +8596,15 @@ void LinearScan::insertMove(
85968596
// This var can't be marked lvRegister now
85978597
varDsc->SetRegNum(REG_STK);
85988598

8599-
GenTree* src = compiler->gtNewLclvNode(lclNum, varDsc->TypeGet());
8599+
var_types typ = varDsc->TypeGet();
8600+
#if defined(FEATURE_SIMD)
8601+
if ((typ == TYP_SIMD12) && compiler->lvaMapSimd12ToSimd16(varDsc))
8602+
{
8603+
typ = TYP_SIMD16;
8604+
}
8605+
#endif
8606+
8607+
GenTree* src = compiler->gtNewLclvNode(lclNum, typ);
86008608
SetLsraAdded(src);
86018609

86028610
// There are three cases we need to handle:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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 System;
5+
using System.Numerics;
6+
using System.Runtime.CompilerServices;
7+
using Xunit;
8+
9+
public unsafe class Runtime_95043
10+
{
11+
[MethodImpl(MethodImplOptions.NoInlining)]
12+
private static void Sweep(int ecx, int* edx, Vector3 stack12)
13+
{
14+
for (int i = 0; i < 5; i++)
15+
{
16+
Console.WriteLine(ecx);
17+
if (ecx == -1)
18+
{
19+
ecx = edx[0];
20+
}
21+
else if (!float.IsNaN(stack12.X))
22+
{
23+
edx[0] = -1;
24+
ecx = -1;
25+
}
26+
}
27+
}
28+
29+
[Fact]
30+
[MethodImpl(MethodImplOptions.NoInlining)]
31+
public static void Test()
32+
{
33+
int x = 42;
34+
Sweep(1, &x, Vector3.Zero);
35+
Assert.Equal(-1, x);
36+
}
37+
}
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+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<Compile Include="$(MSBuildProjectName).cs" />
8+
</ItemGroup>
9+
</Project>

0 commit comments

Comments
 (0)