diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 61230a0e8292c8..4b371fe7db606f 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -3399,13 +3399,28 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) makeOutArgCopy = true; } } - else if (genTypeSize(varDsc->TypeGet()) != genTypeSize(structBaseType)) + else if (genTypeSize(varDsc) != genTypeSize(structBaseType)) { // Not a promoted struct, so just swizzle the type by using GT_LCL_FLD lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::SwizzleArg)); argObj->ChangeOper(GT_LCL_FLD); argObj->gtType = structBaseType; } + else if (varTypeUsesFloatReg(varDsc) != varTypeUsesFloatReg(structBaseType)) + { + // Here we can see int <-> float, long <-> double, long <-> simd8 mismatches, due + // to the "OBJ(ADDR(LCL))" => "LCL" folding above. The latter case is handled in + // lowering, others we will handle here via swizzling. + CLANG_FORMAT_COMMENT_ANCHOR; +#ifdef TARGET_AMD64 + if (varDsc->TypeGet() != TYP_SIMD8) +#endif // TARGET_AMD64 + { + lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::SwizzleArg)); + argObj->ChangeOper(GT_LCL_FLD); + argObj->gtType = structBaseType; + } + } } else if (argObj->OperIs(GT_LCL_FLD, GT_IND)) { diff --git a/src/tests/JIT/Directed/StructABI/TypeMismatchedArgs.cs b/src/tests/JIT/Directed/StructABI/TypeMismatchedArgs.cs index c450040daace48..8850934b2159d5 100644 --- a/src/tests/JIT/Directed/StructABI/TypeMismatchedArgs.cs +++ b/src/tests/JIT/Directed/StructABI/TypeMismatchedArgs.cs @@ -41,6 +41,11 @@ public static int Main() return 105; } + if (ProblemWithRegFileMismatch_Win_x64(12, 13)) + { + return 106; + } + return 100; } @@ -86,6 +91,21 @@ private static bool ProblemWithVectorCallArg() return result != s_vtor128.Vtor4.X; } + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool ProblemWithRegFileMismatch_Win_x64(double dbl, float flt) + { + if (CallForDblStruct(*(DblStruct*)&dbl) != dbl) + { + return true; + } + if (CallForFltStruct(*(FltStruct*)&flt) != flt) + { + return true; + } + + return false; + } + [MethodImpl(MethodImplOptions.NoInlining)] private static float CallForVector4(Vector4 value) => value.X; @@ -97,6 +117,12 @@ private static bool ProblemWithVectorCallArg() [MethodImpl(MethodImplOptions.NoInlining)] private static long CallForSplitStructWithFourLongs(int arg0, int arg1, StructWithFourLongs splitArg) => splitArg.LongOne; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static double CallForDblStruct(DblStruct value) => value.Dbl; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static float CallForFltStruct(FltStruct value) => value.Flt; } [StructLayout(LayoutKind.Explicit)] @@ -170,3 +196,13 @@ struct FourDoublesHfaStruct public double ThirdDblValue; public double FourthDblValue; } + +struct DblStruct +{ + public double Dbl; +} + +struct FltStruct +{ + public float Flt; +}