@@ -3073,10 +3073,11 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
30733073 DISPTREERANGE (BlockRange (), lclStore);
30743074 JITDUMP (" \n " );
30753075
3076- GenTree* src = lclStore->gtGetOp1 ();
3077- LclVarDsc* varDsc = comp->lvaGetDesc (lclStore);
3078- bool srcIsMultiReg = src->IsMultiRegNode ();
3079- bool dstIsMultiReg = lclStore->IsMultiRegLclVar ();
3076+ GenTree* src = lclStore->gtGetOp1 ();
3077+ LclVarDsc* varDsc = comp->lvaGetDesc (lclStore);
3078+
3079+ const bool srcIsMultiReg = src->IsMultiRegNode ();
3080+ const bool dstIsMultiReg = lclStore->IsMultiRegLclVar ();
30803081
30813082 if (!dstIsMultiReg && varTypeIsStruct (varDsc))
30823083 {
@@ -3098,25 +3099,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
30983099 }
30993100 }
31003101
3101- if ((varTypeUsesFloatReg (lclStore) != varTypeUsesFloatReg (src)) && !lclStore->IsPhiDefn () &&
3102- (src->TypeGet () != TYP_STRUCT))
3103- {
3104- if (m_lsra->isRegCandidate (varDsc))
3105- {
3106- GenTree* bitcast = comp->gtNewBitCastNode (lclStore->TypeGet (), src);
3107- lclStore->gtOp1 = bitcast;
3108- src = lclStore->gtGetOp1 ();
3109- BlockRange ().InsertBefore (lclStore, bitcast);
3110- ContainCheckBitCast (bitcast);
3111- }
3112- else
3113- {
3114- // This is an actual store, we'll just retype it.
3115- lclStore->gtType = src->TypeGet ();
3116- }
3117- }
3118-
3119- if (srcIsMultiReg || lclStore->IsMultiRegLclVar ())
3102+ if (srcIsMultiReg || dstIsMultiReg)
31203103 {
31213104 const ReturnTypeDesc* retTypeDesc = nullptr ;
31223105 if (src->OperIs (GT_CALL))
@@ -3125,22 +3108,24 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
31253108 }
31263109 CheckMultiRegLclVar (lclStore->AsLclVar (), retTypeDesc);
31273110 }
3111+
3112+ const var_types lclRegType = varDsc->GetRegisterType (lclStore);
3113+
31283114 if ((lclStore->TypeGet () == TYP_STRUCT) && !srcIsMultiReg)
31293115 {
31303116 bool convertToStoreObj;
31313117 if (src->OperGet () == GT_CALL)
31323118 {
3133- GenTreeCall* call = src->AsCall ();
3134- const ClassLayout* layout = varDsc->GetLayout ();
3135- const var_types regType = layout->GetRegisterType ();
3119+ GenTreeCall* call = src->AsCall ();
3120+ const ClassLayout* layout = varDsc->GetLayout ();
31363121
31373122#ifdef DEBUG
31383123 const unsigned slotCount = layout->GetSlotCount ();
31393124#if defined(TARGET_XARCH) && !defined(UNIX_AMD64_ABI)
31403125 // Windows x64 doesn't have multireg returns,
31413126 // x86 uses it only for long return type, not for structs.
31423127 assert (slotCount == 1 );
3143- assert (regType != TYP_UNDEF);
3128+ assert (lclRegType != TYP_UNDEF);
31443129#else // !TARGET_XARCH || UNIX_AMD64_ABI
31453130 if (!varDsc->lvIsHfa ())
31463131 {
@@ -3153,15 +3138,15 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
31533138 unsigned size = layout->GetSize ();
31543139 assert ((size <= 8 ) || (size == 16 ));
31553140 bool isPowerOf2 = (((size - 1 ) & size) == 0 );
3156- bool isTypeDefined = (regType != TYP_UNDEF);
3141+ bool isTypeDefined = (lclRegType != TYP_UNDEF);
31573142 assert (isPowerOf2 == isTypeDefined);
31583143 }
31593144 }
31603145#endif // !TARGET_XARCH || UNIX_AMD64_ABI
31613146#endif // DEBUG
31623147
31633148#if !defined(WINDOWS_AMD64_ABI)
3164- if (!call->HasMultiRegRetVal () && (regType == TYP_UNDEF))
3149+ if (!call->HasMultiRegRetVal () && (lclRegType == TYP_UNDEF))
31653150 {
31663151 // If we have a single return register,
31673152 // but we can't retype it as a primitive type, we must spill it.
@@ -3182,9 +3167,8 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
31823167 else if (src->OperIs (GT_CNS_INT))
31833168 {
31843169 assert (src->IsIntegralConst (0 ) && " expected an INIT_VAL for non-zero init." );
3185- var_types regType = varDsc->GetRegisterType ();
31863170#ifdef FEATURE_SIMD
3187- if (varTypeIsSIMD (regType ))
3171+ if (varTypeIsSIMD (lclRegType ))
31883172 {
31893173 CorInfoType simdBaseJitType = comp->getBaseJitTypeOfSIMDLocal (lclStore);
31903174 if (simdBaseJitType == CORINFO_TYPE_UNDEF)
@@ -3193,7 +3177,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
31933177 simdBaseJitType = CORINFO_TYPE_FLOAT;
31943178 }
31953179 GenTreeSIMD* simdTree =
3196- comp->gtNewSIMDNode (regType , src, SIMDIntrinsicInit, simdBaseJitType, varDsc->lvExactSize );
3180+ comp->gtNewSIMDNode (lclRegType , src, SIMDIntrinsicInit, simdBaseJitType, varDsc->lvExactSize );
31973181 BlockRange ().InsertAfter (src, simdTree);
31983182 LowerSIMD (simdTree);
31993183 src = simdTree;
@@ -3245,6 +3229,20 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
32453229 }
32463230 }
32473231
3232+ // src and dst can be in registers, check if we need a bitcast.
3233+ if (!src->TypeIs (TYP_STRUCT) && (varTypeUsesFloatReg (lclRegType) != varTypeUsesFloatReg (src)))
3234+ {
3235+ assert (!srcIsMultiReg && !dstIsMultiReg);
3236+ assert (lclStore->OperIsLocalStore ());
3237+ assert (lclRegType != TYP_UNDEF);
3238+
3239+ GenTree* bitcast = comp->gtNewBitCastNode (lclRegType, src);
3240+ lclStore->gtOp1 = bitcast;
3241+ src = lclStore->gtGetOp1 ();
3242+ BlockRange ().InsertBefore (lclStore, bitcast);
3243+ ContainCheckBitCast (bitcast);
3244+ }
3245+
32483246 LowerStoreLoc (lclStore);
32493247 JITDUMP (" lowering store lcl var/field (after):\n " );
32503248 DISPTREERANGE (BlockRange (), lclStore);
@@ -6571,8 +6569,10 @@ void Lowering::ContainCheckBitCast(GenTree* node)
65716569 {
65726570 op1->SetContained ();
65736571 }
6574- LclVarDsc* varDsc = &comp->lvaTable [op1->AsLclVar ()->GetLclNum ()];
6575- if (!m_lsra->isRegCandidate (varDsc))
6572+ const LclVarDsc* varDsc = comp->lvaGetDesc (op1->AsLclVar ());
6573+ // TODO-Cleanup: we want to check if the local is already known not
6574+ // to be on reg, for example, because local enreg is disabled.
6575+ if (varDsc->lvDoNotEnregister )
65766576 {
65776577 op1->SetContained ();
65786578 }
0 commit comments