Skip to content

Commit

Permalink
Delete dead code from and fix getSIMDStructFromField (dotnet#71226)
Browse files Browse the repository at this point in the history
* Clean out dead code from "getSIMDStructFromField"

The only pattern possible here is "FIELD(ADDR(LCL_VAR))".

* Fix the field type issue

* Fix the field offset issue

* Add tests
  • Loading branch information
SingleAccretion authored Jul 25, 2022
1 parent c9d7854 commit 9a461ad
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 66 deletions.
87 changes: 21 additions & 66 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9333,95 +9333,50 @@ GenTree* Compiler::fgMorphForRegisterFP(GenTree* tree)
// ignoreUsedInSIMDIntrinsic - bool. If this is set to true, then this function will ignore
// the UsedInSIMDIntrinsic check.
//
// return value:
// Return Value:
// A GenTree* which points the simd lclvar tree belongs to. If the tree is not the simd
// instrinic related field, return nullptr.
//

GenTree* Compiler::getSIMDStructFromField(GenTree* tree,
CorInfoType* simdBaseJitTypeOut,
unsigned* indexOut,
unsigned* simdSizeOut,
bool ignoreUsedInSIMDIntrinsic /*false*/)
{
GenTree* ret = nullptr;
if (tree->OperGet() == GT_FIELD)
if (tree->OperIs(GT_FIELD))
{
GenTree* objRef = tree->AsField()->GetFldObj();
if (objRef != nullptr)
if ((objRef != nullptr) && objRef->OperIs(GT_ADDR))
{
GenTree* obj = nullptr;
if (objRef->gtOper == GT_ADDR)
{
obj = objRef->AsOp()->gtOp1;
}
else if (ignoreUsedInSIMDIntrinsic)
{
obj = objRef;
}
else
{
return nullptr;
}
GenTree* obj = objRef->AsOp()->gtOp1;

if (isSIMDTypeLocal(obj))
{
LclVarDsc* varDsc = lvaGetDesc(obj->AsLclVarCommon());
if (varDsc->lvIsUsedInSIMDIntrinsic() || ignoreUsedInSIMDIntrinsic)
{
*simdSizeOut = varDsc->lvExactSize;
*simdBaseJitTypeOut = getBaseJitTypeOfSIMDLocal(obj);
ret = obj;
CorInfoType simdBaseJitType = varDsc->GetSimdBaseJitType();
var_types simdBaseType = JITtype2varType(simdBaseJitType);
unsigned fieldOffset = tree->AsField()->gtFldOffset;
unsigned baseTypeSize = genTypeSize(simdBaseType);

// Below condition is convervative. We don't actually need the two types to
// match (only the tree type is relevant), but we don't have a convenient way
// to turn the tree type into "CorInfoType".
if ((tree->TypeGet() == simdBaseType) && ((fieldOffset % baseTypeSize) == 0))
{
*simdSizeOut = varDsc->lvExactSize;
*simdBaseJitTypeOut = simdBaseJitType;
*indexOut = fieldOffset / baseTypeSize;

return obj;
}
}
}
else if (obj->OperGet() == GT_SIMD)
{
ret = obj;
GenTreeSIMD* simdNode = obj->AsSIMD();
*simdSizeOut = simdNode->GetSimdSize();
*simdBaseJitTypeOut = simdNode->GetSimdBaseJitType();
}
#ifdef FEATURE_HW_INTRINSICS
else if (obj->OperIsHWIntrinsic())
{
ret = obj;
GenTreeHWIntrinsic* simdNode = obj->AsHWIntrinsic();
*simdSizeOut = simdNode->GetSimdSize();
*simdBaseJitTypeOut = simdNode->GetSimdBaseJitType();
}
#endif // FEATURE_HW_INTRINSICS
else if (obj->IsCnsVec())
{
ret = obj;
GenTreeVecCon* vecCon = obj->AsVecCon();
*simdSizeOut = genTypeSize(vecCon);
*simdBaseJitTypeOut = vecCon->GetSimdBaseJitType();
}
}
}
if (ret != nullptr)
{
var_types fieldType = tree->TypeGet();
if (fieldType == TYP_LONG)
{
// Vector2/3/4 expose public float fields while Vector<T>
// and Vector64/128/256<T> have internal ulong fields. So
// we should only ever encounter accesses for TYP_FLOAT or
// TYP_LONG and in the case of the latter we don't want the
// generic type since we are executing some algorithm on the
// raw underlying bits instead.

*simdBaseJitTypeOut = CORINFO_TYPE_ULONG;
}
else
{
assert(fieldType == TYP_FLOAT);
}

unsigned baseTypeSize = genTypeSize(JITtype2varType(*simdBaseJitTypeOut));
*indexOut = tree->AsField()->gtFldOffset / baseTypeSize;
}
return ret;
return nullptr;
}

/*****************************************************************************
Expand Down
56 changes: 56 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_71219/Runtime_71219.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Numerics;
using System.Runtime.Intrinsics;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

public class Runtime_71219
{
public static int Main()
{
Vector4 vtor = new Vector4(1, 2, 3, 4);

if (ProblemWithNonFloatField(vtor))
{
return 101;
}

if (ProblemWithMisalignedField(vtor.AsVector128().AsInt64()))
{
return 102;
}

return 100;
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static bool ProblemWithNonFloatField(Vector4 vtor)
{
vtor += vtor;
return Unsafe.As<Vector4, StructWithIndex>(ref vtor).Value != Unsafe.As<float, int>(ref vtor.Y);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static bool ProblemWithMisalignedField(Vector128<long> vtor)
{
vtor += vtor;
return
Unsafe.As<Vector128<long>, StructWithLng>(ref vtor).Long !=
Unsafe.As<byte, long>(ref Unsafe.Add(ref Unsafe.As<Vector128<long>, byte>(ref vtor), 4));
}

struct StructWithIndex
{
public int Index;
public int Value;
}

[StructLayout(LayoutKind.Explicit)]
struct StructWithLng
{
[FieldOffset(4)]
public long Long;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>

0 comments on commit 9a461ad

Please sign in to comment.