Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Set flag in comp info to signal that a caller has >8 byte struct args #22775

Merged
merged 5 commits into from
Feb 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8588,8 +8588,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
unsigned compArgsCount; // Number of arguments (incl. implicit and hidden)

#if FEATURE_FASTTAILCALL
size_t compArgStackSize; // Incoming argument stack size in bytes
#endif // FEATURE_FASTTAILCALL
size_t compArgStackSize; // Incoming argument stack size in bytes
bool compHasMultiSlotArgs; // Caller has >8 byte sized struct parameter
#endif // FEATURE_FASTTAILCALL

unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present);
int compTypeCtxtArg; // position of hidden param for type context for generic code (CORINFO_CALLCONV_PARAMTYPE)
Expand Down
11 changes: 7 additions & 4 deletions src/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,8 @@ void Compiler::lvaInitArgs(InitVarDscInfo* varDscInfo)
// Save the stack usage information
// We can get register usage information using codeGen->intRegState and
// codeGen->floatRegState
info.compArgStackSize = varDscInfo->stackArgSize;
info.compArgStackSize = varDscInfo->stackArgSize;
info.compHasMultiSlotArgs = varDscInfo->hasMultiSlotStruct;
#endif // FEATURE_FASTTAILCALL

// The total argument size must be aligned.
Expand Down Expand Up @@ -827,8 +828,9 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo)
// If there is a second eightbyte, get a register for it too and map the arg to the reg number.
if (structDesc.eightByteCount >= 2)
{
secondEightByteType = GetEightByteType(structDesc, 1);
secondAllocatedRegArgNum = varDscInfo->allocRegArg(secondEightByteType, 1);
secondEightByteType = GetEightByteType(structDesc, 1);
secondAllocatedRegArgNum = varDscInfo->allocRegArg(secondEightByteType, 1);
varDscInfo->hasMultiSlotStruct = true;
}

if (secondEightByteType != TYP_UNDEF)
Expand All @@ -840,7 +842,8 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo)
#ifdef _TARGET_ARM64_
if (cSlots == 2)
{
varDsc->lvOtherArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum + 1, TYP_I_IMPL);
varDsc->lvOtherArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum + 1, TYP_I_IMPL);
varDscInfo->hasMultiSlotStruct = true;
}
#endif // _TARGET_ARM64_
#endif // defined(UNIX_AMD64_ABI)
Expand Down
9 changes: 7 additions & 2 deletions src/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7168,6 +7168,7 @@ bool Compiler::fgCanFastTailCall(GenTreeCall* callee)
}

const unsigned maxRegArgs = MAX_REG_ARG;
hasTwoSlotSizedStruct = hasTwoSlotSizedStruct || info.compHasMultiSlotArgs;
jashook marked this conversation as resolved.
Show resolved Hide resolved

// If we reached here means that callee has only those argument types which can be passed in
// a register and if passed on stack will occupy exactly one stack slot in out-going arg area.
Expand Down Expand Up @@ -7242,8 +7243,12 @@ bool Compiler::fgCanFastTailCall(GenTreeCall* callee)
return false;
}

// Callee has a >8 and <=16 byte struct and arguments that has to go on the stack. Do not fastTailCall.
if (calleeStackSize > 0 && hasTwoSlotSizedStruct)
// Either the caller or callee has a >8 and <=16 byte struct and arguments that has to go on the stack. Do not
// fastTailCall.
//
// When either the caller or callee have multi-stlot stack arguments we cannot safely
// shuffle arguments in LowerFastTailCall. See https://github.com/dotnet/coreclr/issues/12468.
if (hasStackArgs && hasTwoSlotSizedStruct)
jashook marked this conversation as resolved.
Show resolved Hide resolved
{
reportFastTailCallDecision("Will not fastTailCall calleeStackSize > 0 && hasTwoSlotSizedStruct",
callerStackSize, calleeStackSize);
Expand Down
4 changes: 3 additions & 1 deletion src/jit/register_arg_convention.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct InitVarDscInfo
#if FEATURE_FASTTAILCALL
// It is used to calculate argument stack size information in byte
unsigned stackArgSize;
bool hasMultiSlotStruct;
#endif // FEATURE_FASTTAILCALL

public:
Expand All @@ -49,7 +50,8 @@ struct InitVarDscInfo
#endif // _TARGET_ARM_

#if FEATURE_FASTTAILCALL
stackArgSize = 0;
stackArgSize = 0;
hasMultiSlotStruct = false;
#endif // FEATURE_FASTTAILCALL
}

Expand Down
49 changes: 49 additions & 0 deletions tests/src/JIT/Regression/JitBlue/GitHub_22330/GitHub_22330.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using System.Runtime.CompilerServices;

class X
{
// a -> rdi
// b -> rsi
// c -> rdx
// -> rcx
// d -> r8
// e -> r9
// f -> s[0]
// g -> s[1]
public static int F(int a, int b, Guid c, int d, int e, int f, int g)
{
Guid[] z = new Guid[] { c };
// Bug is here passing params to G: f gets trashed by g.
return G(a, b, z, d, e, f, g);
}

// loop here is just to make this method too big to inline
// if we set [noinline] to effect this, we won't tail call it either.
//
// a -> rdi
// b -> rsi
// c -> rdx
// d -> rcx
// e -> r8
// f -> r9
// g -> s[0]
public static int G(int a, int b, Guid[] c, int d, int e, int f, int g)
{
int r = 0;
for (int i = 0; i < 10; i++)
{
r += f + g;
}
return r / 10;
}

// No-opt to stop F from being inlined without marking it noinline
[MethodImpl(MethodImplOptions.NoOptimization)]
public static int Main()
{
int result = F(0, 1, Guid.Empty, 3, 4, 33, 67);
Console.WriteLine($"Result={result}");
return result;
}
}
33 changes: 33 additions & 0 deletions tests/src/JIT/Regression/JitBlue/GitHub_22330/GitHub_22330.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{2649FAFE-07BF-4F93-8120-BA9A69285ABB}</ProjectGuid>
<OutputType>Exe</OutputType>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "></PropertyGroup>
<PropertyGroup>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
<Visible>False</Visible>
</CodeAnalysisDependentAssemblyPaths>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
</Project>