#if defined(TARGET_X86)
if (isStructArg)
{
- GenTree* lclNode = argx->OperIs(GT_LCL_VAR) ? argx : fgIsIndirOfAddrOfLocal(argx);
- if ((lclNode != nullptr) &&
- (lvaGetPromotionType(lclNode->AsLclVarCommon()->GetLclNum()) == Compiler::PROMOTION_TYPE_INDEPENDENT))
- {
- // Make a GT_FIELD_LIST of the field lclVars.
- GenTreeLclVarCommon* lcl = lclNode->AsLclVarCommon();
- LclVarDsc* varDsc = lvaGetDesc(lcl);
- GenTreeFieldList* fieldList = new (this, GT_FIELD_LIST) GenTreeFieldList();
- arg.SetEarlyNode(fieldList);
-
- for (unsigned fieldLclNum = varDsc->lvFieldLclStart;
- fieldLclNum < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++fieldLclNum)
- {
- LclVarDsc* fieldVarDsc = lvaGetDesc(fieldLclNum);
- GenTree* fieldLcl;
+ GenTreeLclVar* lcl = nullptr;
- if (fieldLclNum == varDsc->lvFieldLclStart)
- {
- lcl->SetLclNum(fieldLclNum);
- lcl->SetOperResetFlags(GT_LCL_VAR);
- lcl->gtType = fieldVarDsc->TypeGet();
- fieldLcl = lcl;
- }
- else
- {
- fieldLcl = gtNewLclvNode(fieldLclNum, fieldVarDsc->TypeGet());
- }
-
- fieldList->AddField(this, fieldLcl, fieldVarDsc->lvFldOffset, fieldVarDsc->TypeGet());
+ // TODO-ADDR: always perform "OBJ(ADDR(LCL)) => LCL" transformation in local morph and delete this code.
+ if (argx->OperGet() == GT_OBJ)
+ {
+ if (argx->gtGetOp1()->OperIs(GT_ADDR) && argx->gtGetOp1()->gtGetOp1()->OperIs(GT_LCL_VAR))
+ {
+ lcl = argx->gtGetOp1()->gtGetOp1()->AsLclVar();
+ }
+ }
+ else if (argx->OperGet() == GT_LCL_VAR)
+ {
+ lcl = argx->AsLclVar();
+ }
+ if ((lcl != nullptr) && (lvaGetPromotionType(lcl->GetLclNum()) == PROMOTION_TYPE_INDEPENDENT))
+ {
+ if (argx->OperIs(GT_LCL_VAR) ||
+ ClassLayout::AreCompatible(argx->AsObj()->GetLayout(), lvaGetDesc(lcl)->GetLayout()))
+ {
+ argx = fgMorphLclArgToFieldlist(lcl);
+ arg.SetEarlyNode(argx);
+ }
+ else
+ {
+ // Set DNER to block independent promotion.
+ lvaSetVarDoNotEnregister(lcl->GetLclNum() DEBUGARG(DoNotEnregisterReason::IsStructArg));
}
}
}
if (arg->AbiInfo.GetRegNum() == REG_STK)
#endif
{
- GenTreeLclVarCommon* lcl = nullptr;
- GenTree* actualArg = argNode->gtEffectiveVal();
+ GenTreeLclVar* lcl = nullptr;
+ GenTree* actualArg = argNode->gtEffectiveVal();
+ // TODO-ADDR: always perform "OBJ(ADDR(LCL)) => LCL" transformation in local morph and delete this code.
if (actualArg->OperGet() == GT_OBJ)
{
if (actualArg->gtGetOp1()->OperIs(GT_ADDR) && actualArg->gtGetOp1()->gtGetOp1()->OperIs(GT_LCL_VAR))
{
- lcl = actualArg->gtGetOp1()->gtGetOp1()->AsLclVarCommon();
+ lcl = actualArg->gtGetOp1()->gtGetOp1()->AsLclVar();
}
}
else if (actualArg->OperGet() == GT_LCL_VAR)
{
- lcl = actualArg->AsLclVarCommon();
+ lcl = actualArg->AsLclVar();
}
if (lcl != nullptr)
{
if (lvaGetPromotionType(lcl->GetLclNum()) == PROMOTION_TYPE_INDEPENDENT)
{
- argNode = fgMorphLclArgToFieldlist(lcl);
+ if (argNode->OperIs(GT_LCL_VAR) ||
+ ClassLayout::AreCompatible(argNode->AsObj()->GetLayout(), lvaGetDesc(lcl)->GetLayout()))
+ {
+ argNode = fgMorphLclArgToFieldlist(lcl);
+ }
+ else
+ {
+ // Set DNER to block independent promotion.
+ lvaSetVarDoNotEnregister(lcl->GetLclNum() DEBUGARG(DoNotEnregisterReason::IsStructArg));
+ }
}
#ifdef TARGET_LOONGARCH64
else if (argNode->TypeGet() == TYP_STRUCT)
return 106;
}
+ if (ProblemWithPromotedStruct_Unix_x64(new StructWithFourLongs { LongOne = 1, LongTwo = 2, LongThree = 3, LongFour = 4 }))
+ {
+ return 107;
+ }
+
+ if (ProblemWithPromotedStruct_x86(new DblLngStruct { FirstLngValue = 1, SecondLngValue = 2 }))
+ {
+ return 108;
+ }
+
return 100;
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool ProblemWithPromotedStruct_Unix_x64(StructWithFourLongs b)
+ {
+ var c = b;
+
+ return CallForDblStructs(default, default, default, default, *(DblLngStruct*)&c) != c.LongTwo;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool ProblemWithPromotedStruct_x86(DblLngStruct a)
+ {
+ var b = a;
+
+ return CallForStructWithIndex(*(StructWithIndex*)&b) != (int)(b.FirstLngValue >> 32);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
private static float CallForVector4(Vector4 value) => value.X;
[MethodImpl(MethodImplOptions.NoInlining)]
[MethodImpl(MethodImplOptions.NoInlining)]
private static float CallForFltStruct(FltStruct value) => value.Flt;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static long CallForDblStructs(DblLngStruct arg0, DblLngStruct arg1, DblLngStruct arg2, DblLngStruct arg3, DblLngStruct stkArg) => stkArg.SecondLngValue;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int CallForStructWithIndex(StructWithIndex value) => value.Value;
}
[StructLayout(LayoutKind.Explicit)]
{
public float Flt;
}
+
+struct StructWithIndex
+{
+ public int Index;
+ public int Value;
+}