From f06134ed869442f28cb0ab47ef2372d539a7e5af Mon Sep 17 00:00:00 2001 From: Carol Eidt Date: Fri, 30 Nov 2018 15:02:00 -0800 Subject: Don't struct-promote opaque vectors The hardware vector types: `Vector64`, `Vector128` and `Vector256` are declared as having one or more fields of `ulong`. However, the JIT shouldn't be promoting these fields to local variables. It is almost never the right type, and the intrinsics in any case are not designed to cooperate with promoted fields (i.e. an index of a `Vector` won't map to the promoted lclVar). Most importantly, it causes all copies of the vector to be done as 64-bit integer loads and stores. Finally, it will be important, as we support vector ABIs, to distinguish the handling of the fixed-size vectors (`Vector2`, `Vector3` and `Vector4`) which *are* considered to be normal structs of N floats, from the opaque types which will be passed in vector registers. --- src/jit/compiler.h | 26 ++++++++++++++++++++++++++ src/jit/morph.cpp | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 986f0ab6ca..1a381ab2f2 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -7640,6 +7640,17 @@ private: return NO_CLASS_HANDLE; } + // Returns true if this is a SIMD type that should be considered an opaque + // vector type (i.e. do not analyze or promote its fields). + // Note that all but the fixed vector types are opaque, even though they may + // actually be declared as having fields. + bool isOpaqueSIMDType(CORINFO_CLASS_HANDLE structHandle) + { + return ((m_simdHandleCache != nullptr) && (structHandle != m_simdHandleCache->SIMDVector2Handle) && + (structHandle != m_simdHandleCache->SIMDVector3Handle) && + (structHandle != m_simdHandleCache->SIMDVector4Handle)); + } + // Returns true if the tree corresponds to a TYP_SIMD lcl var. // Note that both SIMD vector args and locals are mared as lvSIMDType = true, but // type of an arg node is TYP_BYREF and a local node is TYP_SIMD or TYP_STRUCT. @@ -7648,6 +7659,16 @@ private: return tree->OperIsLocal() && lvaTable[tree->AsLclVarCommon()->gtLclNum].lvSIMDType; } + // Returns true if the lclVar is an opaque SIMD type. + bool isOpaqueSIMDLclVar(LclVarDsc* varDsc) + { + if (!varDsc->lvSIMDType) + { + return false; + } + return isOpaqueSIMDType(varDsc->lvVerTypeInfo.GetClassHandle()); + } + // Returns true if the type of the tree is a byref of TYP_SIMD bool isAddrOfSIMDType(GenTree* tree) { @@ -7987,6 +8008,11 @@ private: return lvaSIMDInitTempVarNum; } +#else // !FEATURE_SIMD + bool isOpaqueSIMDLclVar(LclVarDsc* varDsc) + { + return false; + } #endif // FEATURE_SIMD public: diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 20e378ed16..83704cb5ae 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -16973,7 +16973,7 @@ void Compiler::fgPromoteStructs() // If we have marked this as lvUsedInSIMDIntrinsic, then we do not want to promote // its fields. Instead, we will attempt to enregister the entire struct. - if (varDsc->lvIsSIMDType() && varDsc->lvIsUsedInSIMDIntrinsic()) + if (varDsc->lvIsSIMDType() && (varDsc->lvIsUsedInSIMDIntrinsic() || isOpaqueSIMDLclVar(varDsc))) { varDsc->lvRegStruct = true; } -- cgit v1.2.3