-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Closed
Labels
arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone
Description
While reviewing changes in dotnet/coreclr#23675, I noticed that the code added to EEClass::CheckForHFA does not handle wrapped Vector64, Vector128, and Vector256 intrinsic types correctly. For instance, it does not distinguish a wrapped Vector64 and a double. Moreover, the elemSize check is skipped for wrapped Vector128 and Vector256 types. As a result, the HFA/HVA property may be calculated incorrectly. For instance (here { } denotes a struct):
{{Vector64}, Vector64}is incorrectly treated as non-HVA.{{Vector64}, double}is incorrectly treated as HFA(double).{Vector128, {Vector256}}is incorrectly treated as HVA(simd16).
The code in question:
runtime/src/coreclr/src/vm/class.cpp
Lines 1345 to 1381 in ce416f4
| case ELEMENT_TYPE_VALUETYPE: | |
| { | |
| #ifdef TARGET_ARM64 | |
| // hfa/hva types are unique by size, except for Vector64 which we can conveniently | |
| // treat as if it were a double for ABI purposes. However, it only qualifies as | |
| // an HVA if all fields are the same type. This will ensure that we only | |
| // consider it an HVA if all the fields are ELEMENT_TYPE_VALUETYPE (which have been | |
| // determined above to be vectors) of the same size. | |
| MethodTable* pMT; | |
| #if defined(FEATURE_HFA) | |
| pMT = pByValueClassCache[i]; | |
| #else | |
| pMT = pFD->LookupApproxFieldTypeHandle().AsMethodTable(); | |
| #endif | |
| int thisElemSize = pMT->GetVectorSize(); | |
| if (thisElemSize != 0) | |
| { | |
| if (elemSize == 0) | |
| { | |
| elemSize = thisElemSize; | |
| } | |
| else if ((thisElemSize != elemSize) || (hfaType != ELEMENT_TYPE_VALUETYPE)) | |
| { | |
| return false; | |
| } | |
| } | |
| else | |
| #endif // TARGET_ARM64 | |
| { | |
| #if defined(FEATURE_HFA) | |
| fieldType = pByValueClassCache[i]->GetHFAType(); | |
| #else | |
| fieldType = pFD->LookupApproxFieldTypeHandle().AsMethodTable()->GetHFAType(); | |
| #endif | |
| } | |
| } | |
| break; |
The repro program (set COMPlus_JITDisasm=C::* to see HFA/HVA properties and registers used):
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
#pragma warning disable 0169 // warning CS0169: The field '{0}' is never used
struct WrappedVector64 { Vector64<byte> _; }
struct WrappedVector128 { Vector128<byte> _; }
struct WrappedVector256 { Vector256<byte> _; }
// Incorrectly treated as non-HVA: passed in x0, x1
struct S1 { WrappedVector64 x; Vector64<byte> y; }
// Incorrectly treated as HFA(double): passed in d0, d1
struct S2 { WrappedVector64 x; double y; }
// Incorrectly treated as HVA(simd16): passed in q0, q1, q2
struct S3 { Vector128<byte> x; WrappedVector256 y; }
static class C
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void Foo<T>(T x) { }
static void Main()
{
Foo(new S1());
Foo(new S2());
Foo(new S3());
}
}@CarolEidt @echesakovMSFT @sdmaclea
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI