diff options
author | Sergey Andreenko <seandree@microsoft.com> | 2021-06-29 01:33:32 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-29 01:33:32 +0300 |
commit | 94f3355d90d8b5db1848957351a6b3585dee13a4 (patch) | |
tree | 36cdc67daef188edef8f6d1ab2850e4e9489f762 /src/coreclr/jit | |
parent | 1c383a27ce2c83d41b135cc149e422d15cfeb4e5 (diff) |
Fix lowering usage of an unset LSRA field. (#54731)
* Add repro.
* fix the issue.
* delete a dead condition
* add a todo.
* Fix the failures.
Diffstat (limited to 'src/coreclr/jit')
-rw-r--r-- | src/coreclr/jit/codegen.h | 2 | ||||
-rw-r--r-- | src/coreclr/jit/gentree.cpp | 1 | ||||
-rw-r--r-- | src/coreclr/jit/lclvars.cpp | 1 | ||||
-rw-r--r-- | src/coreclr/jit/lower.cpp | 68 | ||||
-rw-r--r-- | src/coreclr/jit/lowerarmarch.cpp | 4 |
5 files changed, 42 insertions, 34 deletions
diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 02971fbde2b..ae862974158 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -863,8 +863,10 @@ protected: // Generate code for a GT_BITCAST that is not contained. void genCodeForBitCast(GenTreeOp* treeNode); +#if defined(TARGET_XARCH) // Generate the instruction to move a value between register files void genBitCast(var_types targetType, regNumber targetReg, var_types srcType, regNumber srcReg); +#endif // TARGET_XARCH struct GenIntCastDesc { diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index a10afeb758b..955a7bba1e9 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -7396,6 +7396,7 @@ GenTree* Compiler::gtNewPutArgReg(var_types type, GenTree* arg, regNumber argReg GenTree* Compiler::gtNewBitCastNode(var_types type, GenTree* arg) { assert(arg != nullptr); + assert(type != TYP_STRUCT); GenTree* node = nullptr; #if defined(TARGET_ARM) diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 916cb93e187..f7c67808bdd 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -3779,6 +3779,7 @@ var_types LclVarDsc::GetRegisterType(const GenTreeLclVarCommon* tree) const { if (lclVarType == TYP_STRUCT) { + assert(!tree->OperIsLocalField() && "do not expect struct local fields."); lclVarType = GetLayout()->GetRegisterType(); } targetType = lclVarType; diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 389c29f7643..8cbef1709fa 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -3073,10 +3073,11 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) DISPTREERANGE(BlockRange(), lclStore); JITDUMP("\n"); - GenTree* src = lclStore->gtGetOp1(); - LclVarDsc* varDsc = comp->lvaGetDesc(lclStore); - bool srcIsMultiReg = src->IsMultiRegNode(); - bool dstIsMultiReg = lclStore->IsMultiRegLclVar(); + GenTree* src = lclStore->gtGetOp1(); + LclVarDsc* varDsc = comp->lvaGetDesc(lclStore); + + const bool srcIsMultiReg = src->IsMultiRegNode(); + const bool dstIsMultiReg = lclStore->IsMultiRegLclVar(); if (!dstIsMultiReg && varTypeIsStruct(varDsc)) { @@ -3098,25 +3099,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) } } - if ((varTypeUsesFloatReg(lclStore) != varTypeUsesFloatReg(src)) && !lclStore->IsPhiDefn() && - (src->TypeGet() != TYP_STRUCT)) - { - if (m_lsra->isRegCandidate(varDsc)) - { - GenTree* bitcast = comp->gtNewBitCastNode(lclStore->TypeGet(), src); - lclStore->gtOp1 = bitcast; - src = lclStore->gtGetOp1(); - BlockRange().InsertBefore(lclStore, bitcast); - ContainCheckBitCast(bitcast); - } - else - { - // This is an actual store, we'll just retype it. - lclStore->gtType = src->TypeGet(); - } - } - - if (srcIsMultiReg || lclStore->IsMultiRegLclVar()) + if (srcIsMultiReg || dstIsMultiReg) { const ReturnTypeDesc* retTypeDesc = nullptr; if (src->OperIs(GT_CALL)) @@ -3125,14 +3108,16 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) } CheckMultiRegLclVar(lclStore->AsLclVar(), retTypeDesc); } + + const var_types lclRegType = varDsc->GetRegisterType(lclStore); + if ((lclStore->TypeGet() == TYP_STRUCT) && !srcIsMultiReg) { bool convertToStoreObj; if (src->OperGet() == GT_CALL) { - GenTreeCall* call = src->AsCall(); - const ClassLayout* layout = varDsc->GetLayout(); - const var_types regType = layout->GetRegisterType(); + GenTreeCall* call = src->AsCall(); + const ClassLayout* layout = varDsc->GetLayout(); #ifdef DEBUG const unsigned slotCount = layout->GetSlotCount(); @@ -3140,7 +3125,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) // Windows x64 doesn't have multireg returns, // x86 uses it only for long return type, not for structs. assert(slotCount == 1); - assert(regType != TYP_UNDEF); + assert(lclRegType != TYP_UNDEF); #else // !TARGET_XARCH || UNIX_AMD64_ABI if (!varDsc->lvIsHfa()) { @@ -3153,7 +3138,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) unsigned size = layout->GetSize(); assert((size <= 8) || (size == 16)); bool isPowerOf2 = (((size - 1) & size) == 0); - bool isTypeDefined = (regType != TYP_UNDEF); + bool isTypeDefined = (lclRegType != TYP_UNDEF); assert(isPowerOf2 == isTypeDefined); } } @@ -3161,7 +3146,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) #endif // DEBUG #if !defined(WINDOWS_AMD64_ABI) - if (!call->HasMultiRegRetVal() && (regType == TYP_UNDEF)) + if (!call->HasMultiRegRetVal() && (lclRegType == TYP_UNDEF)) { // If we have a single return register, // but we can't retype it as a primitive type, we must spill it. @@ -3182,9 +3167,8 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) 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)) + if (varTypeIsSIMD(lclRegType)) { CorInfoType simdBaseJitType = comp->getBaseJitTypeOfSIMDLocal(lclStore); if (simdBaseJitType == CORINFO_TYPE_UNDEF) @@ -3193,7 +3177,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) simdBaseJitType = CORINFO_TYPE_FLOAT; } GenTreeSIMD* simdTree = - comp->gtNewSIMDNode(regType, src, SIMDIntrinsicInit, simdBaseJitType, varDsc->lvExactSize); + comp->gtNewSIMDNode(lclRegType, src, SIMDIntrinsicInit, simdBaseJitType, varDsc->lvExactSize); BlockRange().InsertAfter(src, simdTree); LowerSIMD(simdTree); src = simdTree; @@ -3245,6 +3229,20 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) } } + // src and dst can be in registers, check if we need a bitcast. + if (!src->TypeIs(TYP_STRUCT) && (varTypeUsesFloatReg(lclRegType) != varTypeUsesFloatReg(src))) + { + assert(!srcIsMultiReg && !dstIsMultiReg); + assert(lclStore->OperIsLocalStore()); + assert(lclRegType != TYP_UNDEF); + + GenTree* bitcast = comp->gtNewBitCastNode(lclRegType, src); + lclStore->gtOp1 = bitcast; + src = lclStore->gtGetOp1(); + BlockRange().InsertBefore(lclStore, bitcast); + ContainCheckBitCast(bitcast); + } + LowerStoreLoc(lclStore); JITDUMP("lowering store lcl var/field (after):\n"); DISPTREERANGE(BlockRange(), lclStore); @@ -6571,8 +6569,10 @@ void Lowering::ContainCheckBitCast(GenTree* node) { op1->SetContained(); } - LclVarDsc* varDsc = &comp->lvaTable[op1->AsLclVar()->GetLclNum()]; - if (!m_lsra->isRegCandidate(varDsc)) + const LclVarDsc* varDsc = comp->lvaGetDesc(op1->AsLclVar()); + // TODO-Cleanup: we want to check if the local is already known not + // to be on reg, for example, because local enreg is disabled. + if (varDsc->lvDoNotEnregister) { op1->SetContained(); } diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 6774a4ef176..7edf8c7103f 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1549,6 +1549,9 @@ void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) const assert(storeLoc->OperIsLocalStore()); GenTree* op1 = storeLoc->gtGetOp1(); +#if 0 + // TODO-ARMARCH-CQ: support contained bitcast under STORE_LCL_VAR/FLD, + // currently codegen does not expect it. if (op1->OperIs(GT_BITCAST)) { // If we know that the source of the bitcast will be in a register, then we can make @@ -1561,6 +1564,7 @@ void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) const return; } } +#endif const LclVarDsc* varDsc = comp->lvaGetDesc(storeLoc); |