Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Andreenko <seandree@microsoft.com>2021-06-29 01:33:32 +0300
committerGitHub <noreply@github.com>2021-06-29 01:33:32 +0300
commit94f3355d90d8b5db1848957351a6b3585dee13a4 (patch)
tree36cdc67daef188edef8f6d1ab2850e4e9489f762 /src/coreclr/jit
parent1c383a27ce2c83d41b135cc149e422d15cfeb4e5 (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.h2
-rw-r--r--src/coreclr/jit/gentree.cpp1
-rw-r--r--src/coreclr/jit/lclvars.cpp1
-rw-r--r--src/coreclr/jit/lower.cpp68
-rw-r--r--src/coreclr/jit/lowerarmarch.cpp4
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);