@@ -2984,9 +2984,8 @@ void Lowering::LowerRet(GenTreeUnOp* ret)
29842984 // There are two kinds of retyping:
29852985 // - A simple bitcast can be inserted when:
29862986 // - We're returning a floating type as an integral type or vice-versa, or
2987- // - We're returning a struct as a primitive type and using the old form of retyping.
2988- // - If we're returning a struct as a primitive type and *not* using old retying, we change the type of
2989- // 'retval' in 'LowerRetStructLclVar()'
2987+ // - If we're returning a struct as a primitive type, we change the type of
2988+ // 'retval' in 'LowerRetStructLclVar()'
29902989 bool needBitcast =
29912990 (ret->TypeGet () != TYP_VOID) && (varTypeUsesFloatReg (ret) != varTypeUsesFloatReg (ret->gtGetOp1 ()));
29922991 bool doPrimitiveBitcast = false ;
@@ -3408,6 +3407,7 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret)
34083407 unsigned lclNum = lclVar->GetLclNum ();
34093408 LclVarDsc* varDsc = comp->lvaGetDesc (lclNum);
34103409
3410+ bool replacedInLowering = false ;
34113411 if (varDsc->CanBeReplacedWithItsField (comp))
34123412 {
34133413 // We can replace the struct with its only field and keep the field on a register.
@@ -3420,8 +3420,9 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret)
34203420 " [%06u]\n " ,
34213421 lclNum, fieldLclNum, comp->dspTreeID (ret));
34223422 lclVar->ChangeType (fieldDsc->lvType );
3423- lclNum = fieldLclNum;
3424- varDsc = comp->lvaGetDesc (lclNum);
3423+ lclNum = fieldLclNum;
3424+ varDsc = comp->lvaGetDesc (lclNum);
3425+ replacedInLowering = true ;
34253426 }
34263427 else if (varDsc->lvPromoted )
34273428 {
@@ -3432,20 +3433,52 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret)
34323433
34333434 if (varDsc->lvDoNotEnregister )
34343435 {
3436+ assert (!replacedInLowering);
34353437 lclVar->ChangeOper (GT_LCL_FLD);
34363438 lclVar->AsLclFld ()->SetLclOffs (0 );
3437- lclVar->ChangeType (ret->TypeGet ());
3439+
3440+ // We are returning as a primitive type and the lcl is of struct type.
3441+ assert (comp->info .compRetNativeType != TYP_STRUCT);
3442+ assert ((genTypeSize (comp->info .compRetNativeType ) == genTypeSize (ret)) ||
3443+ (varTypeIsIntegral (ret) && varTypeIsIntegral (comp->info .compRetNativeType ) &&
3444+ (genTypeSize (comp->info .compRetNativeType ) <= genTypeSize (ret))));
3445+ // If the actual return type requires normalization, then make sure we
3446+ // do so by using the correct small type for the GT_LCL_FLD. It would
3447+ // be conservative to check just compRetNativeType for this since small
3448+ // structs are normalized to primitive types when they are returned in
3449+ // registers, so we would normalize for them as well.
3450+ if (varTypeIsSmall (comp->info .compRetType ))
3451+ {
3452+ assert (genTypeSize (comp->info .compRetNativeType ) == genTypeSize (comp->info .compRetType ));
3453+ lclVar->ChangeType (comp->info .compRetType );
3454+ }
3455+ else
3456+ {
3457+ // Otherwise we don't mind that we leave the upper bits undefined.
3458+ lclVar->ChangeType (ret->TypeGet ());
3459+ }
34383460 }
34393461 else
34403462 {
34413463 const var_types lclVarType = varDsc->GetRegisterType (lclVar);
34423464 assert (lclVarType != TYP_UNDEF);
3465+
3466+ if (varDsc->lvNormalizeOnLoad () && replacedInLowering)
3467+ {
3468+ // For a normalize-on-load var that we replaced late we need to insert a cast
3469+ // as morph would typically be responsible for this.
3470+ GenTreeCast* cast = comp->gtNewCastNode (TYP_INT, lclVar, false , lclVarType);
3471+ ret->gtOp1 = cast;
3472+ BlockRange ().InsertBefore (ret, cast);
3473+ ContainCheckCast (cast);
3474+ }
3475+
34433476 const var_types actualType = genActualType (lclVarType);
34443477 lclVar->ChangeType (actualType);
34453478
34463479 if (varTypeUsesFloatReg (ret) != varTypeUsesFloatReg (lclVarType))
34473480 {
3448- GenTree* bitcast = comp->gtNewBitCastNode (ret->TypeGet (), lclVar );
3481+ GenTree* bitcast = comp->gtNewBitCastNode (ret->TypeGet (), ret-> gtOp1 );
34493482 ret->gtOp1 = bitcast;
34503483 BlockRange ().InsertBefore (ret, bitcast);
34513484 ContainCheckBitCast (bitcast);
0 commit comments