diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index 868e0ce6f5c8..5e8088d2c476 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -1004,37 +1004,57 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
assert(structSize > 0);
#ifdef UNIX_AMD64_ABI
-
// An 8-byte struct may need to be returned in a floating point register
// So we always consult the struct "Classifier" routine
//
SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
eeGetSystemVAmd64PassStructInRegisterDescriptor(clsHnd, &structDesc);
- // If we have one eightByteCount then we can set 'useType' based on that
if (structDesc.eightByteCount == 1)
{
- // Set 'useType' to the type of the first eightbyte item
- useType = GetEightByteType(structDesc, 0);
- assert(structDesc.passedInRegisters == true);
+ assert(structSize <= sizeof(double));
+
+ if (structDesc.eightByteClassifications[0] == SystemVClassificationTypeSSE)
+ {
+ // If this is returned as a floating type, use that.
+ // Otherwise, leave as TYP_UNKONWN and we'll sort things out below.
+ useType = GetEightByteType(structDesc, 0);
+ howToReturnStruct = SPK_PrimitiveType;
+ }
}
-#else // not UNIX_AMD64
+#endif // UNIX_AMD64_ABI
+ // Check for cases where a small struct is returned in a register
+ // via a primitive type.
+ //
// The largest primitive type is 8 bytes (TYP_DOUBLE)
// so we can skip calling getPrimitiveTypeForStruct when we
// have a struct that is larger than that.
- //
- if (structSize <= sizeof(double))
+ if ((useType == TYP_UNKNOWN) && (structSize <= sizeof(double)))
{
// We set the "primitive" useType based upon the structSize
// and also examine the clsHnd to see if it is an HFA of count one
//
- // The ABI for struct returns in varArg methods, is same as the normal case, so pass false for isVararg
+ // The ABI for struct returns in varArg methods, is same as the normal case,
+ // so pass false for isVararg
useType = getPrimitiveTypeForStruct(structSize, clsHnd, /*isVararg=*/false);
- }
-#endif // UNIX_AMD64_ABI
+ if (useType != TYP_UNKNOWN)
+ {
+ if (structSize == genTypeSize(useType))
+ {
+ // Currently: 1, 2, 4, or 8 byte structs
+ howToReturnStruct = SPK_PrimitiveType;
+ }
+ else
+ {
+ // Currently: 3, 5, 6, or 7 byte structs
+ assert(structSize < genTypeSize(useType));
+ howToReturnStruct = SPK_EnclosingType;
+ }
+ }
+ }
#ifdef _TARGET_64BIT_
// Note this handles an odd case when FEATURE_MULTIREG_RET is disabled and HFAs are enabled
@@ -1048,16 +1068,16 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
//
if ((FEATURE_MULTIREG_RET == 0) && (useType == TYP_UNKNOWN) && (structSize == (2 * sizeof(float))) && IsHfa(clsHnd))
{
- useType = TYP_I_IMPL;
+ useType = TYP_I_IMPL;
+ howToReturnStruct = SPK_PrimitiveType;
}
#endif
// Did we change this struct type into a simple "primitive" type?
- //
if (useType != TYP_UNKNOWN)
{
- // Yes, we should use the "primitive" type in 'useType'
- howToReturnStruct = SPK_PrimitiveType;
+ // If so, we should have already set howToReturnStruct, too.
+ assert(howToReturnStruct != SPK_Unknown);
}
else // We can't replace the struct with a "primitive" type
{
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 2e8d27d71a0d..eb92395f7abf 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -1691,6 +1691,8 @@ class Compiler
GenTree* impAssignMultiRegTypeToVar(GenTree* op, CORINFO_CLASS_HANDLE hClass);
#endif // FEATURE_MULTIREG_RET
+ GenTree* impAssignSmallStructTypeToVar(GenTree* op, CORINFO_CLASS_HANDLE hClass);
+
#ifdef ARM_SOFTFP
bool isSingleFloat32Struct(CORINFO_CLASS_HANDLE hClass);
#endif // ARM_SOFTFP
@@ -4223,6 +4225,9 @@ class Compiler
{
SPK_Unknown, // Invalid value, never returned
SPK_PrimitiveType, // The struct is passed/returned using a primitive type.
+ SPK_EnclosingType, // Like SPK_Primitive type, but used for return types that
+ // require a primitive type temp that is larger than the struct size.
+ // Currently used for structs of size 3, 5, 6, or 7 bytes.
SPK_ByValue, // The struct is passed/returned by value (using the ABI rules)
// for ARM64 and UNIX_X64 in multiple registers. (when all of the
// parameters registers are used, then the stack will be used)
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp
index a852fb315f64..197af3100b53 100644
--- a/src/jit/flowgraph.cpp
+++ b/src/jit/flowgraph.cpp
@@ -22324,33 +22324,113 @@ Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder(GenTr
}
}
-#if FEATURE_MULTIREG_RET
-
- // Did we record a struct return class handle above?
+ // If an inline was rejected and the call returns a struct, we may
+ // have deferred some work when importing call for cases where the
+ // struct is returned in register(s).
+ //
+ // See the bail-out clauses in impFixupCallStructReturn for inline
+ // candidates.
//
+ // Do the deferred work now.
if (retClsHnd != NO_CLASS_HANDLE)
{
- // Is this a type that is returned in multiple registers?
- // if so we need to force into into a form we accept.
- // i.e. LclVar = call()
- //
- if (comp->IsMultiRegReturnedType(retClsHnd))
+ structPassingKind howToReturnStruct;
+ var_types returnType = comp->getReturnTypeForStruct(retClsHnd, &howToReturnStruct);
+ GenTree* parent = data->parent;
+
+ switch (howToReturnStruct)
{
- GenTree* parent = data->parent;
- // See assert below, we only look one level above for an asg parent.
- if (parent->gtOper == GT_ASG)
+
+#if FEATURE_MULTIREG_RET
+
+ // Is this a type that is returned in multiple registers
+ // or a via a primitve type that is larger than the struct type?
+ // if so we need to force into into a form we accept.
+ // i.e. LclVar = call()
+ case SPK_ByValue:
+ case SPK_ByValueAsHfa:
{
- // Either lhs is a call V05 = call(); or lhs is addr, and asg becomes a copyBlk.
- comp->fgAttachStructInlineeToAsg(parent, tree, retClsHnd);
+ // See assert below, we only look one level above for an asg parent.
+ if (parent->gtOper == GT_ASG)
+ {
+ // Either lhs is a call V05 = call(); or lhs is addr, and asg becomes a copyBlk.
+ comp->fgAttachStructInlineeToAsg(parent, tree, retClsHnd);
+ }
+ else
+ {
+ // Just assign the inlinee to a variable to keep it simple.
+ tree->ReplaceWith(comp->fgAssignStructInlineeToVar(tree, retClsHnd), comp);
+ }
}
- else
+ break;
+
+#endif // FEATURE_MULTIREG_RET
+
+ case SPK_EnclosingType:
{
- // Just assign the inlinee to a variable to keep it simple.
- tree->ReplaceWith(comp->fgAssignStructInlineeToVar(tree, retClsHnd), comp);
+ // For enclosing type returns, we must return the call value to a temp since
+ // the return type is larger than the struct type.
+ if (!tree->IsCall())
+ {
+ break;
+ }
+
+ GenTreeCall* call = tree->AsCall();
+
+ assert(call->gtReturnType == TYP_STRUCT);
+
+ if (call->gtReturnType != TYP_STRUCT)
+ {
+ break;
+ }
+
+ JITDUMP("\nCall returns small struct via enclosing type, retyping. Before:\n");
+ DISPTREE(call);
+
+ // Create new struct typed temp for return value
+ const unsigned tmpNum =
+ comp->lvaGrabTemp(true DEBUGARG("small struct return temp for rejected inline"));
+ comp->lvaSetStruct(tmpNum, retClsHnd, false);
+ GenTree* assign = comp->gtNewTempAssign(tmpNum, call);
+
+ // Modify assign tree and call return types to the primitive return type
+ call->gtReturnType = returnType;
+ call->gtType = returnType;
+ assign->gtType = returnType;
+
+ // Modify the temp reference in the assign as a primitive reference via GT_LCL_FLD
+ GenTree* tempAsPrimitive = assign->gtOp.gtOp1;
+ assert(tempAsPrimitive->gtOper == GT_LCL_VAR);
+ tempAsPrimitive->gtType = returnType;
+ tempAsPrimitive->ChangeOper(GT_LCL_FLD);
+
+ // Return temp as value of call tree via comma
+ GenTree* tempAsStruct = comp->gtNewLclvNode(tmpNum, TYP_STRUCT);
+ GenTree* comma = comp->gtNewOperNode(GT_COMMA, TYP_STRUCT, assign, tempAsStruct);
+ parent->ReplaceOperand(pTree, comma);
+
+ JITDUMP("\nAfter:\n");
+ DISPTREE(comma);
}
+ break;
+
+ case SPK_PrimitiveType:
+ // We should have already retyped the call as a primitive type
+ // when we first imported the call
+ break;
+
+ case SPK_ByReference:
+ // We should have already added the return buffer
+ // when we first imported the call
+ break;
+
+ default:
+ noway_assert(!"Unexpected struct passing kind");
+ break;
}
}
+#if FEATURE_MULTIREG_RET
#if defined(DEBUG)
// Make sure we don't have a tree like so: V05 = (, , , retExpr);
diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp
index e1bc249cdfca..bba58cbecf8f 100644
--- a/src/jit/gentree.cpp
+++ b/src/jit/gentree.cpp
@@ -17679,6 +17679,10 @@ void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp, CORINFO_CLASS_HA
switch (howToReturnStruct)
{
+ case Compiler::SPK_EnclosingType:
+ m_isEnclosingType = true;
+ __fallthrough;
+
case Compiler::SPK_PrimitiveType:
{
assert(returnType != TYP_UNKNOWN);
diff --git a/src/jit/gentree.h b/src/jit/gentree.h
index 4baed55b6b5c..e59b79d9c8c5 100644
--- a/src/jit/gentree.h
+++ b/src/jit/gentree.h
@@ -3089,6 +3089,7 @@ struct ReturnTypeDesc
{
private:
var_types m_regType[MAX_RET_REG_COUNT];
+ bool m_isEnclosingType;
#ifdef DEBUG
bool m_inited;
@@ -3114,6 +3115,7 @@ struct ReturnTypeDesc
{
m_regType[i] = TYP_UNKNOWN;
}
+ m_isEnclosingType = false;
#ifdef DEBUG
m_inited = false;
#endif
@@ -3206,6 +3208,13 @@ struct ReturnTypeDesc
return result;
}
+ // True if this value is returned in integer register
+ // that is larger than the type itself.
+ bool IsEnclosingType() const
+ {
+ return m_isEnclosingType;
+ }
+
// Get ith ABI return register
regNumber GetABIReturnReg(unsigned idx);
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
index 1b2e35771810..74f48083d20d 100644
--- a/src/jit/importer.cpp
+++ b/src/jit/importer.cpp
@@ -8464,8 +8464,24 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN
{
if (retRegCount == 1)
{
- // struct returned in a single register
- call->gtReturnType = retTypeDesc->GetReturnRegType(0);
+ // See if the struct size is smaller than the return
+ // type size...
+ if (retTypeDesc->IsEnclosingType())
+ {
+ // If we know for sure this call will remain a call,
+ // retype and return value via a suitable temp.
+ if ((!call->CanTailCall()) && (!call->IsInlineCandidate()))
+ {
+ call->gtReturnType = retTypeDesc->GetReturnRegType(0);
+ return impAssignSmallStructTypeToVar(call, retClsHnd);
+ }
+ }
+ else
+ {
+ // Return type is same size as struct, so we can
+ // simply retype the call.
+ call->gtReturnType = retTypeDesc->GetReturnRegType(0);
+ }
}
else
{
@@ -8507,7 +8523,25 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN
else
{
assert(returnType != TYP_UNKNOWN);
- call->gtReturnType = returnType;
+
+ // See if the struct size is smaller than the return
+ // type size...
+ if (howToReturnStruct == SPK_EnclosingType)
+ {
+ // If we know for sure this call will remain a call,
+ // retype and return value via a suitable temp.
+ if ((!call->CanTailCall()) && (!call->IsInlineCandidate()))
+ {
+ call->gtReturnType = returnType;
+ return impAssignSmallStructTypeToVar(call, retClsHnd);
+ }
+ }
+ else
+ {
+ // Return type is same size as struct, so we can
+ // simply retype the call.
+ call->gtReturnType = returnType;
+ }
// ToDo: Refactor this common code sequence into its own method as it is used 4+ times
if ((returnType == TYP_LONG) && (compLongUsed == false))
@@ -8555,6 +8589,9 @@ GenTree* Compiler::impFixupStructReturnType(GenTree* op, CORINFO_CLASS_HANDLE re
assert(varTypeIsStruct(info.compRetType));
assert(info.compRetBuffArg == BAD_VAR_NUM);
+ JITDUMP("\nimpFixupStructReturnType: retyping\n");
+ DISPTREE(op);
+
#if defined(_TARGET_XARCH_)
#ifdef UNIX_AMD64_ABI
@@ -8725,9 +8762,7 @@ GenTree* Compiler::impFixupStructReturnType(GenTree* op, CORINFO_CLASS_HANDLE re
}
else
{
- assert(info.compRetNativeType == op->gtCall.gtReturnType);
-
- // Don't change the gtType of the node just yet, it will get changed later.
+ // Don't change the gtType of the call just yet, it will get changed later.
return op;
}
}
@@ -8750,6 +8785,9 @@ GenTree* Compiler::impFixupStructReturnType(GenTree* op, CORINFO_CLASS_HANDLE re
op->gtType = info.compRetNativeType;
+ JITDUMP("\nimpFixupStructReturnType: result of retyping is\n");
+ DISPTREE(op);
+
return op;
}
@@ -15647,7 +15685,45 @@ void Compiler::impMarkLclDstNotPromotable(unsigned tmpNum, GenTree* src, CORINFO
}
#endif // _TARGET_ARM_
+//------------------------------------------------------------------------
+// impAssignSmallStructTypeToVar: ensure calls that return small structs whose
+// sizes are not supported integral type sizes return values to temps.
+//
+// Arguments:
+// op -- call returning a small struct in a register
+// hClass -- class handle for struct
+//
+// Returns:
+// Tree with reference to struct local to use as call return value.
+//
+// Remarks:
+// The call will be spilled into a preceding statement.
+// Currently handles struct returns for 3, 5, 6, and 7 byte structs.
+
+GenTree* Compiler::impAssignSmallStructTypeToVar(GenTree* op, CORINFO_CLASS_HANDLE hClass)
+{
+ unsigned tmpNum = lvaGrabTemp(true DEBUGARG("Return value temp for small struct return."));
+ impAssignTempGen(tmpNum, op, hClass, (unsigned)CHECK_SPILL_ALL);
+ GenTree* ret = gtNewLclvNode(tmpNum, lvaTable[tmpNum].lvType);
+
+ // TODO-1stClassStructs: Handle constant propagation and CSE-ing of small struct returns.
+ ret->gtFlags |= GTF_DONT_CSE;
+
+ return ret;
+}
+
#if FEATURE_MULTIREG_RET
+//------------------------------------------------------------------------
+// impAssignMultiRegTypeToVar: ensure calls that return structs in multiple
+// registers return values to suitable temps.
+//
+// Arguments:
+// op -- call returning a struct in a registers
+// hClass -- class handle for struct
+//
+// Returns:
+// Tree with reference to struct local to use as call return value.
+
GenTree* Compiler::impAssignMultiRegTypeToVar(GenTree* op, CORINFO_CLASS_HANDLE hClass)
{
unsigned tmpNum = lvaGrabTemp(true DEBUGARG("Return value temp for multireg return."));
diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp
index b36fcad94164..eb6545f8e944 100644
--- a/src/jit/lclvars.cpp
+++ b/src/jit/lclvars.cpp
@@ -141,7 +141,8 @@ void Compiler::lvaInitTypeRef()
Compiler::structPassingKind howToReturnStruct;
var_types returnType = getReturnTypeForStruct(retClsHnd, &howToReturnStruct);
- if (howToReturnStruct == SPK_PrimitiveType)
+ // We can safely widen the return type for enclosed structs.
+ if ((howToReturnStruct == SPK_PrimitiveType) || (howToReturnStruct == SPK_EnclosingType))
{
assert(returnType != TYP_UNKNOWN);
assert(!varTypeIsStruct(returnType));
diff --git a/tests/arm/Tests.lst b/tests/arm/Tests.lst
index 9e96a1eb994d..db556779e9dc 100644
--- a/tests/arm/Tests.lst
+++ b/tests/arm/Tests.lst
@@ -94740,3 +94740,67 @@ MaxAllowedDurationSeconds=600
Categories=EXPECTED_PASS
HostStyle=0
+[GitHub_18522.cmd_11903]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522\GitHub_18522.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_1.cmd_11904]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_1\GitHub_18522_1.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_1
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_2.cmd_11905]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_2\GitHub_18522_2.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_2
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_3.cmd_11906]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_3\GitHub_18522_3.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_3
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_4.cmd_11907]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_4\GitHub_18522_4.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_4
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_5.cmd_11908]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_5\GitHub_18522_5.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_5
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_6.cmd_11909]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_6\GitHub_18522_6.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_6
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_7.cmd_11910]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_7\GitHub_18522_7.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_7
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
diff --git a/tests/arm64/Tests.lst b/tests/arm64/Tests.lst
index a9a732053a00..4d7592873474 100644
--- a/tests/arm64/Tests.lst
+++ b/tests/arm64/Tests.lst
@@ -94763,3 +94763,67 @@ Expected=0
MaxAllowedDurationSeconds=600
Categories=EXPECTED_PASS
HostStyle=0
+
+[GitHub_18522.cmd_12223]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522\GitHub_18522.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_1.cmd_12224]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_1\GitHub_18522_1.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_1
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_2.cmd_12225]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_2\GitHub_18522_2.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_2
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_3.cmd_12226]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_3\GitHub_18522_3.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_3
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_4.cmd_12227]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_4\GitHub_18522_4.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_4
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_5.cmd_12228]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_5\GitHub_18522_5.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_5
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_6.cmd_12229]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_6\GitHub_18522_6.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_6
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
+
+[GitHub_18522_7.cmd_12230]
+RelativePath=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_7\GitHub_18522_7.cmd
+WorkingDir=JIT\Regression\JitBlue\GitHub_18522\GitHub_18522_7
+Expected=0
+MaxAllowedDurationSeconds=600
+Categories=EXPECTED_PASS
+HostStyle=0
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.cs
new file mode 100644
index 000000000000..8cbcc6e5b8b1
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+// Based on a program generated by Fuzzlyn
+
+struct S0
+{
+ public ushort F0;
+}
+
+struct S1
+{
+ public S0 F0;
+ public ushort F1;
+}
+
+public class GitHub_18522
+{
+ static S1 s_36;
+
+ // When generating code for the x64 SysV ABI, the jit was
+ // incorrectly typing the return type from M113, and so
+ // inadvertently overwriting the F1 field of s_36 on return from
+ // the (inlined) call.
+ public static int Main()
+ {
+ s_36.F1 = 0xAA;
+ s_36.F0 = M113();
+ return (s_36.F1 == 0xAA ? 100 : 0);
+ }
+
+ static S0 M113()
+ {
+ return new S0();
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.csproj
new file mode 100644
index 000000000000..95aba995a255
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.csproj
@@ -0,0 +1,34 @@
+
+
+
+
+ Debug
+ AnyCPU
+ $(MSBuildProjectName)
+ 2.0
+ {95DFC527-4DC1-495E-97D7-E94EE1F7140D}
+ Exe
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ ..\..\
+
+
+
+
+
+
+ False
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.cs
new file mode 100644
index 000000000000..a5726451fb6c
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+// Based on
+// Original generated by Fuzzlyn on 2018-06-20 00:58:58
+// Seed: 11049252875418439527
+// Reduced from 97.5 KiB to 0.5 KiB
+// Debug: Outputs -1
+// Release: Outputs -65536
+
+struct S0
+{
+ public sbyte F0;
+ public char F1;
+ public ushort F2;
+}
+
+struct S1
+{
+ public short F0;
+ public S0 F1;
+ public S0 F2;
+ public S0 F3;
+ public int F4;
+ public S1(int f4): this()
+ {
+ F4 = f4;
+ }
+}
+
+public class GitHub_18522_1
+{
+ static S1 s_6;
+ static S1[] s_13 = new S1[]{new S1(-1)};
+ public static int Main()
+ {
+ // When generating code for the x64 SysV ABI, the jit was
+ // incorrectly typing the return type from M16, and so
+ // inadvertently overwriting the F4 field of s_13[0] on return
+ // from the (inlined) call.
+ s_13[0].F3 = M16();
+ return s_13[0].F4 == -1 ? 100 : 0;
+ }
+
+ static S0 M16()
+ {
+ return s_6.F3;
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.csproj
new file mode 100644
index 000000000000..95aba995a255
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.csproj
@@ -0,0 +1,34 @@
+
+
+
+
+ Debug
+ AnyCPU
+ $(MSBuildProjectName)
+ 2.0
+ {95DFC527-4DC1-495E-97D7-E94EE1F7140D}
+ Exe
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ ..\..\
+
+
+
+
+
+
+ False
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.cs
new file mode 100644
index 000000000000..ab4090d0d369
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+
+// Based on
+// Original generated by Fuzzlyn on 2018-06-20 00:58:58
+// Seed: 11049252875418439527
+// Reduced from 97.5 KiB to 0.5 KiB
+// Debug: Outputs -1
+// Release: Outputs -65536
+
+struct S0
+{
+ public sbyte F0;
+ public char F1;
+ public ushort F2;
+}
+
+struct S1
+{
+ public short F0;
+ public S0 F1;
+ public S0 F2;
+ public S0 F3;
+ public int F4;
+ public S1(int f4): this()
+ {
+ F4 = f4;
+ }
+}
+
+public class GitHub_18522_2
+{
+ static S1 s_6;
+ static S1[] s_13 = new S1[]{new S1(-1)};
+ public static int Main()
+ {
+ // When generating code for the x64 SysV ABI, the jit was
+ // incorrectly typing the return type from M16, and so
+ // inadvertently overwriting the F4 field of s_13[0] on return
+ // from the (not inlined) call.
+ s_13[0].F3 = M16();
+ return s_13[0].F4 == -1 ? 100 : 0;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static S0 M16()
+ {
+ return s_6.F3;
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.csproj
new file mode 100644
index 000000000000..95aba995a255
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.csproj
@@ -0,0 +1,34 @@
+
+
+
+
+ Debug
+ AnyCPU
+ $(MSBuildProjectName)
+ 2.0
+ {95DFC527-4DC1-495E-97D7-E94EE1F7140D}
+ Exe
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ ..\..\
+
+
+
+
+
+
+ False
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.cs
new file mode 100644
index 000000000000..9d6960cfcb76
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.cs
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+
+// Based on
+// Original generated by Fuzzlyn on 2018-06-20 00:58:58
+// Seed: 11049252875418439527
+// Reduced from 97.5 KiB to 0.5 KiB
+// Debug: Outputs -1
+// Release: Outputs -65536
+
+struct S0
+{
+ public sbyte F0;
+ public char F1;
+ public ushort F2;
+}
+
+struct S1
+{
+ public short F0;
+ public S0 F1;
+ public S0 F2;
+ public S0 F3;
+ public int F4;
+ public S1(int f4): this()
+ {
+ F4 = f4;
+ }
+}
+
+public class GitHub_18522_3
+{
+ static S1 s_6;
+ static S1[] s_13 = new S1[]{new S1(-1)};
+ public static int Main()
+ {
+ // When generating code for the x64 SysV ABI, the jit was
+ // incorrectly typing the return type from M16, and so
+ // inadvertently overwriting the F4 field of s_13[0] on return
+ // from the call (which was an inline candidate, but not inlined).
+ s_13[0].F3 = M16();
+ return s_13[0].F4 == -1 ? 100 : 0;
+ }
+
+ static S0 M16()
+ {
+ // This bit of code is intended to allow M16 to be an
+ // inline candidate that ultimately does not get inlined.
+ short x = 0;
+ for (int i = 0; i < 10; i++)
+ {
+ for (int j = 0; j < 10; j++)
+ {
+ x++;
+ }
+ }
+ s_6.F0 = x;
+
+ // Actual interesting part
+ return s_6.F3;
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.csproj
new file mode 100644
index 000000000000..95aba995a255
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.csproj
@@ -0,0 +1,34 @@
+
+
+
+
+ Debug
+ AnyCPU
+ $(MSBuildProjectName)
+ 2.0
+ {95DFC527-4DC1-495E-97D7-E94EE1F7140D}
+ Exe
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ ..\..\
+
+
+
+
+
+
+ False
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.cs
new file mode 100644
index 000000000000..b6f54dc61507
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.cs
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+
+// Based on
+// Original generated by Fuzzlyn on 2018-06-20 00:58:58
+// Seed: 11049252875418439527
+// Reduced from 97.5 KiB to 0.5 KiB
+// Debug: Outputs -1
+// Release: Outputs -65536
+
+struct S0
+{
+ public sbyte F0;
+ public char F1;
+ public ushort F2;
+}
+
+struct S1
+{
+ public short F0;
+ public S0 F1;
+ public S0 F2;
+ public S0 F3;
+ public int F4;
+ public S1(int f4): this()
+ {
+ F4 = f4;
+ }
+}
+
+public class GitHub_18522_4
+{
+ static S1 s_6;
+ static S1[] s_13 = new S1[]{new S1(-1)};
+ public static int Main()
+ {
+ // When generating code for the x64 SysV ABI, the jit was
+ // incorrectly typing the return type from M16, and so
+ // inadvertently overwriting the F4 field of s_13[0] on return
+ // from the call.
+ //
+ // Here we make sure we properly handle an inline call that
+ // resolves to a noinline call.
+ s_13[0].F3 = W();
+ return s_13[0].F4 == -1 ? 100 : 0;
+ }
+
+ static S0 W()
+ {
+ return M16();
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static S0 M16()
+ {
+ return s_6.F3;
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.csproj
new file mode 100644
index 000000000000..95aba995a255
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.csproj
@@ -0,0 +1,34 @@
+
+
+
+
+ Debug
+ AnyCPU
+ $(MSBuildProjectName)
+ 2.0
+ {95DFC527-4DC1-495E-97D7-E94EE1F7140D}
+ Exe
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ ..\..\
+
+
+
+
+
+
+ False
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.cs
new file mode 100644
index 000000000000..fdb2a72dc9ca
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.cs
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+
+// Based on
+// Original generated by Fuzzlyn on 2018-06-20 00:58:58
+// Seed: 11049252875418439527
+// Reduced from 97.5 KiB to 0.5 KiB
+// Debug: Outputs -1
+// Release: Outputs -65536
+
+struct S0
+{
+ public sbyte F0;
+ public char F1;
+ public ushort F2;
+}
+
+struct S1
+{
+ public short F0;
+ public S0 F1;
+ public S0 F2;
+ public S0 F3;
+ public int F4;
+ public S1(int f4): this()
+ {
+ F4 = f4;
+ }
+}
+
+public class GitHub_18522_5
+{
+ static S1 s_6;
+ static S1[] s_13 = new S1[]{new S1(-1)};
+ public static int Main()
+ {
+ // When generating code for the x64 SysV ABI, the jit was
+ // incorrectly typing the return type from M16, and so
+ // inadvertently overwriting the F4 field of s_13[0] on return
+ // from the call.
+ //
+ // Here we make sure we properly handle an inlined call that
+ // resolves to a rejected inline candidate.
+ s_13[0].F3 = W();
+ return s_13[0].F4 == -1 ? 100 : 0;
+ }
+
+ static S0 W()
+ {
+ return M16();
+ }
+
+ static S0 M16()
+ {
+ // This bit of code is intended to allow M16 to be an
+ // inline candidate that ultimately does not get inlined.
+ short x = 0;
+ for (int i = 0; i < 10; i++)
+ {
+ for (int j = 0; j < 10; j++)
+ {
+ x++;
+ }
+ }
+ s_6.F0 = x;
+
+ // Actual interesting part
+ return s_6.F3;
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.csproj
new file mode 100644
index 000000000000..95aba995a255
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.csproj
@@ -0,0 +1,34 @@
+
+
+
+
+ Debug
+ AnyCPU
+ $(MSBuildProjectName)
+ 2.0
+ {95DFC527-4DC1-495E-97D7-E94EE1F7140D}
+ Exe
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ ..\..\
+
+
+
+
+
+
+ False
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.cs
new file mode 100644
index 000000000000..5a3990f509ae
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.cs
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+
+// Based on
+// Original generated by Fuzzlyn on 2018-06-20 00:58:58
+// Seed: 11049252875418439527
+// Reduced from 97.5 KiB to 0.5 KiB
+// Debug: Outputs -1
+// Release: Outputs -65536
+
+struct S0
+{
+ public sbyte F0;
+ public char F1;
+ public ushort F2;
+}
+
+struct S1
+{
+ public short F0;
+ public S0 F1;
+ public S0 F2;
+ public S0 F3;
+ public int F4;
+ public S1(int f4): this()
+ {
+ F4 = f4;
+ }
+}
+
+public class GitHub_18522_6
+{
+ static S1 s_6;
+ static S1[] s_13 = new S1[]{new S1(-1)};
+ public static int Main()
+ {
+ // When generating code for the x64 SysV ABI, the jit was
+ // incorrectly typing the return type from M16, and so
+ // inadvertently overwriting the F4 field of s_13[0] on return
+ // from the call.
+ //
+ // Here we make sure we properly handle an inlined call that
+ // resolves to another inlined call.
+ s_13[0].F3 = W();
+ return s_13[0].F4 == -1 ? 100 : 0;
+ }
+
+ static S0 W()
+ {
+ return M16();
+ }
+
+ static S0 M16()
+ {
+ return s_6.F3;
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.csproj
new file mode 100644
index 000000000000..95aba995a255
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.csproj
@@ -0,0 +1,34 @@
+
+
+
+
+ Debug
+ AnyCPU
+ $(MSBuildProjectName)
+ 2.0
+ {95DFC527-4DC1-495E-97D7-E94EE1F7140D}
+ Exe
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ ..\..\
+
+
+
+
+
+
+ False
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.cs
new file mode 100644
index 000000000000..e59d3ded8b19
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+
+// Based on
+// Original generated by Fuzzlyn on 2018-06-20 00:58:58
+// Seed: 11049252875418439527
+// Reduced from 97.5 KiB to 0.5 KiB
+// Debug: Outputs -1
+// Release: Outputs -65536
+
+// Similar to other variants but using a 3 byte struct instead of 6.
+
+struct S0
+{
+ public byte F0;
+ public byte F1;
+ public byte F2;
+}
+
+struct S1
+{
+ public S0 F3;
+ public sbyte F4;
+ public short F0;
+ public S1(sbyte f4): this()
+ {
+ F4 = f4;
+ }
+}
+
+public class GitHub_18522_7
+{
+ static S1 s_6;
+ static S1[] s_13 = new S1[]{new S1(-1)};
+ public static int Main()
+ {
+ // When generating code for the x64 SysV ABI, the jit was
+ // incorrectly typing the return type from M16, and so
+ // inadvertently overwriting the F4 field of s_13[0] on return
+ // from the call.
+ //
+ // Here we make sure we properly handle the failed inline case.
+ s_13[0].F3 = M16();
+ return s_13[0].F4 == -1 ? 100 : 0;
+ }
+
+ static S0 M16()
+ {
+ // This bit of code is intended to allow M16 to be an
+ // inline candidate that ultimately does not get inlined.
+ short x = 0;
+ for (int i = 0; i < 10; i++)
+ {
+ for (int j = 0; j < 10; j++)
+ {
+ x++;
+ }
+ }
+ s_6.F0 = x;
+
+ return s_6.F3;
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.csproj
new file mode 100644
index 000000000000..95aba995a255
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.csproj
@@ -0,0 +1,34 @@
+
+
+
+
+ Debug
+ AnyCPU
+ $(MSBuildProjectName)
+ 2.0
+ {95DFC527-4DC1-495E-97D7-E94EE1F7140D}
+ Exe
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ ..\..\
+
+
+
+
+
+
+ False
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+