Improve struct inits. (#52292)
authorSergey Andreenko <seandree@microsoft.com>
Sat, 8 May 2021 00:34:52 +0000 (17:34 -0700)
committerGitHub <noreply@github.com>
Sat, 8 May 2021 00:34:52 +0000 (17:34 -0700)
* Support STORE_LCL_VAR(0) after lowering.

* fix a nice catch from Tanner

src/coreclr/jit/codegenarm64.cpp
src/coreclr/jit/gentree.h
src/coreclr/jit/lower.cpp
src/coreclr/jit/rationalize.cpp
src/coreclr/jit/simdcodegenxarch.cpp

index d306c3d..d20e538 100644 (file)
@@ -3846,20 +3846,9 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
 void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode)
 {
     // NYI for unsupported base types
-    if (simdNode->GetSimdBaseType() != TYP_INT && simdNode->GetSimdBaseType() != TYP_LONG &&
-        simdNode->GetSimdBaseType() != TYP_FLOAT && simdNode->GetSimdBaseType() != TYP_DOUBLE &&
-        simdNode->GetSimdBaseType() != TYP_USHORT && simdNode->GetSimdBaseType() != TYP_UBYTE &&
-        simdNode->GetSimdBaseType() != TYP_SHORT && simdNode->GetSimdBaseType() != TYP_BYTE &&
-        simdNode->GetSimdBaseType() != TYP_UINT && simdNode->GetSimdBaseType() != TYP_ULONG)
-    {
-        // We don't need a base type for the Upper Save & Restore intrinsics, and we may find
-        // these implemented over lclVars created by CSE without full handle information (and
-        // therefore potentially without a base type).
-        if ((simdNode->gtSIMDIntrinsicID != SIMDIntrinsicUpperSave) &&
-            (simdNode->gtSIMDIntrinsicID != SIMDIntrinsicUpperRestore))
-        {
-            noway_assert(!"SIMD intrinsic with unsupported base type.");
-        }
+    if (!varTypeIsArithmetic(simdNode->GetSimdBaseType()))
+    {
+        noway_assert(!"SIMD intrinsic with unsupported base type.");
     }
 
     switch (simdNode->gtSIMDIntrinsicID)
index c751c7f..0946c88 100644 (file)
@@ -1688,10 +1688,10 @@ public:
     bool IsValidCallArgument();
 #endif // DEBUG
 
-    inline bool IsFPZero();
-    inline bool IsIntegralConst(ssize_t constVal);
-    inline bool IsIntegralConstVector(ssize_t constVal);
-    inline bool IsSIMDZero();
+    inline bool IsFPZero() const;
+    inline bool IsIntegralConst(ssize_t constVal) const;
+    inline bool IsIntegralConstVector(ssize_t constVal) const;
+    inline bool IsSIMDZero() const;
 
     inline bool IsBoxedValue();
 
@@ -2922,11 +2922,11 @@ struct GenTreeVal : public GenTree
 
 struct GenTreeIntConCommon : public GenTree
 {
-    inline INT64 LngValue();
+    inline INT64 LngValue() const;
     inline void SetLngValue(INT64 val);
-    inline ssize_t IconValue();
+    inline ssize_t IconValue() const;
     inline void SetIconValue(ssize_t val);
-    inline INT64 IntegralValue();
+    inline INT64 IntegralValue() const;
 
     GenTreeIntConCommon(genTreeOps oper, var_types type DEBUGARG(bool largeNode = false))
         : GenTree(oper, type DEBUGARG(largeNode))
@@ -3090,7 +3090,7 @@ struct GenTreeLngCon : public GenTreeIntConCommon
 #endif
 };
 
-inline INT64 GenTreeIntConCommon::LngValue()
+inline INT64 GenTreeIntConCommon::LngValue() const
 {
 #ifndef TARGET_64BIT
     assert(gtOper == GT_CNS_LNG);
@@ -3114,7 +3114,7 @@ inline void GenTreeIntConCommon::SetLngValue(INT64 val)
 #endif
 }
 
-inline ssize_t GenTreeIntConCommon::IconValue()
+inline ssize_t GenTreeIntConCommon::IconValue() const
 {
     assert(gtOper == GT_CNS_INT); //  We should never see a GT_CNS_LNG for a 64-bit target!
     return AsIntCon()->gtIconVal;
@@ -3126,7 +3126,7 @@ inline void GenTreeIntConCommon::SetIconValue(ssize_t val)
     AsIntCon()->gtIconVal = val;
 }
 
-inline INT64 GenTreeIntConCommon::IntegralValue()
+inline INT64 GenTreeIntConCommon::IntegralValue() const
 {
 #ifdef TARGET_64BIT
     return LngValue();
@@ -6942,7 +6942,7 @@ inline bool GenTree::OperIsCopyBlkOp()
 // Return Value:
 //    Returns true iff the tree is an GT_CNS_DBL, with value of 0.0.
 
-inline bool GenTree::IsFPZero()
+inline bool GenTree::IsFPZero() const
 {
     if ((gtOper == GT_CNS_DBL) && (AsDblCon()->gtDconVal == 0.0))
     {
@@ -6965,7 +6965,7 @@ inline bool GenTree::IsFPZero()
 //    Like gtIconVal, the argument is of ssize_t, so cannot check for
 //    long constants in a target-independent way.
 
-inline bool GenTree::IsIntegralConst(ssize_t constVal)
+inline bool GenTree::IsIntegralConst(ssize_t constVal) const
 
 {
     if ((gtOper == GT_CNS_INT) && (AsIntConCommon()->IconValue() == constVal))
@@ -6991,7 +6991,7 @@ inline bool GenTree::IsIntegralConst(ssize_t constVal)
 // Returns:
 //     True if this represents an integral const SIMD vector.
 //
-inline bool GenTree::IsIntegralConstVector(ssize_t constVal)
+inline bool GenTree::IsIntegralConstVector(ssize_t constVal) const
 {
 #ifdef FEATURE_SIMD
     // SIMDIntrinsicInit intrinsic with a const value as initializer
@@ -7008,7 +7008,7 @@ inline bool GenTree::IsIntegralConstVector(ssize_t constVal)
 #ifdef FEATURE_HW_INTRINSICS
     if (gtOper == GT_HWINTRINSIC)
     {
-        GenTreeHWIntrinsic* node = AsHWIntrinsic();
+        const GenTreeHWIntrinsic* node = AsHWIntrinsic();
 
         if (!varTypeIsIntegral(node->GetSimdBaseType()))
         {
@@ -7058,7 +7058,7 @@ inline bool GenTree::IsIntegralConstVector(ssize_t constVal)
 // Returns:
 //     True if this represents an integral const SIMD vector.
 //
-inline bool GenTree::IsSIMDZero()
+inline bool GenTree::IsSIMDZero() const
 {
 #ifdef FEATURE_SIMD
     if ((gtOper == GT_SIMD) && (AsSIMD()->gtSIMDIntrinsicID == SIMDIntrinsicInit))
index f72943b..1a48600 100644 (file)
@@ -3120,6 +3120,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
     }
     if ((lclStore->TypeGet() == TYP_STRUCT) && !srcIsMultiReg && (src->OperGet() != GT_PHI))
     {
+        bool convertToStoreObj;
         if (src->OperGet() == GT_CALL)
         {
             GenTreeCall*       call    = src->AsCall();
@@ -3165,8 +3166,50 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
                 return;
             }
 #endif // !WINDOWS_AMD64_ABI
+            convertToStoreObj = false;
         }
-        else if (!src->OperIs(GT_LCL_VAR) || (varDsc->GetLayout()->GetRegisterType() == TYP_UNDEF))
+        else if (!varDsc->IsEnregisterable())
+        {
+            convertToStoreObj = true;
+        }
+        else if (src->OperIs(GT_CNS_INT))
+        {
+            assert(src->IsIntegralConst(0) && "expected an INIT_VAL for non-zero init.");
+            var_types regType = varDsc->GetRegisterType();
+#ifdef FEATURE_SIMD
+            if (varTypeIsSIMD(regType))
+            {
+                CorInfoType simdBaseJitType = comp->getBaseJitTypeOfSIMDLocal(lclStore);
+                if (simdBaseJitType == CORINFO_TYPE_UNDEF)
+                {
+                    // Lie about the type if we don't know/have it.
+                    simdBaseJitType = CORINFO_TYPE_FLOAT;
+                }
+                GenTreeSIMD* simdTree =
+                    comp->gtNewSIMDNode(regType, src, SIMDIntrinsicInit, simdBaseJitType, varDsc->lvExactSize);
+                BlockRange().InsertAfter(src, simdTree);
+                LowerSIMD(simdTree);
+                src               = simdTree;
+                lclStore->gtOp1   = src;
+                convertToStoreObj = false;
+            }
+            else
+#endif // FEATURE_SIMD
+            {
+                convertToStoreObj = false;
+            }
+        }
+        else if (!src->OperIs(GT_LCL_VAR))
+        {
+            convertToStoreObj = true;
+        }
+        else
+        {
+            assert(src->OperIs(GT_LCL_VAR));
+            convertToStoreObj = false;
+        }
+
+        if (convertToStoreObj)
         {
             GenTreeLclVar* addr = comp->gtNewLclVarAddrNode(lclStore->GetLclNum(), TYP_BYREF);
 
index e15bc54..52f1cd4 100644 (file)
@@ -398,23 +398,25 @@ void Rationalizer::RewriteAssignment(LIR::Use& use)
 #ifdef FEATURE_SIMD
         if (varTypeIsSIMD(location) && assignment->OperIsInitBlkOp())
         {
-            if (location->OperGet() == GT_LCL_VAR)
+            if (location->OperIs(GT_LCL_VAR))
             {
                 var_types   simdType        = location->TypeGet();
                 GenTree*    initVal         = assignment->AsOp()->gtOp2;
                 CorInfoType simdBaseJitType = comp->getBaseJitTypeOfSIMDLocal(location);
-                if (simdBaseJitType != CORINFO_TYPE_UNDEF)
+                if (simdBaseJitType == CORINFO_TYPE_UNDEF)
                 {
-                    GenTreeSIMD* simdTree = new (comp, GT_SIMD)
-                        GenTreeSIMD(simdType, initVal, SIMDIntrinsicInit, simdBaseJitType, genTypeSize(simdType));
-                    assignment->AsOp()->gtOp2 = simdTree;
-                    value                     = simdTree;
-                    initVal->gtNext           = simdTree;
-                    simdTree->gtPrev          = initVal;
-
-                    simdTree->gtNext = location;
-                    location->gtPrev = simdTree;
+                    // Lie about the type if we don't know/have it.
+                    simdBaseJitType = CORINFO_TYPE_FLOAT;
                 }
+                GenTreeSIMD* simdTree =
+                    comp->gtNewSIMDNode(simdType, initVal, SIMDIntrinsicInit, simdBaseJitType, genTypeSize(simdType));
+                assignment->AsOp()->gtOp2 = simdTree;
+                value                     = simdTree;
+                initVal->gtNext           = simdTree;
+                simdTree->gtPrev          = initVal;
+
+                simdTree->gtNext = location;
+                location->gtPrev = simdTree;
             }
         }
 #endif // FEATURE_SIMD
index 13c3674..0ceac8c 100644 (file)
@@ -2353,11 +2353,7 @@ void CodeGen::genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode)
 void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode)
 {
     // NYI for unsupported base types
-    if (simdNode->GetSimdBaseType() != TYP_INT && simdNode->GetSimdBaseType() != TYP_LONG &&
-        simdNode->GetSimdBaseType() != TYP_FLOAT && simdNode->GetSimdBaseType() != TYP_DOUBLE &&
-        simdNode->GetSimdBaseType() != TYP_USHORT && simdNode->GetSimdBaseType() != TYP_UBYTE &&
-        simdNode->GetSimdBaseType() != TYP_SHORT && simdNode->GetSimdBaseType() != TYP_BYTE &&
-        simdNode->GetSimdBaseType() != TYP_UINT && simdNode->GetSimdBaseType() != TYP_ULONG)
+    if (!varTypeIsArithmetic(simdNode->GetSimdBaseType()))
     {
         noway_assert(!"SIMD intrinsic with unsupported base type.");
     }