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

Commit 6f78fbb

Browse files
author
Jarret Shook
authored
Port #22775 into release/2.1 (#24858)
* Set flag in comp info to signal that a caller has >8 byte struct args (#22775) * Set flag in comp info to signal that a caller has >8 byte struct args This will be used by fgCanFastTailCall to correctly determine whether an arm64 or x64 linux caller/callee can fastTailCall. It is also a workaround to #12468 to catch early any slot shuffling that would happen in LowerFastTailCall. Which currently assumes all parameters are one slot size. * Address feedback * Apply format patch * Add comment * apply new format patch * Address feedback and add header
1 parent 1eed8df commit 6f78fbb

File tree

6 files changed

+105
-8
lines changed

6 files changed

+105
-8
lines changed

src/jit/compiler.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8599,8 +8599,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
85998599
unsigned compArgsCount; // Number of arguments (incl. implicit and hidden)
86008600

86018601
#if FEATURE_FASTTAILCALL
8602-
size_t compArgStackSize; // Incoming argument stack size in bytes
8603-
#endif // FEATURE_FASTTAILCALL
8602+
size_t compArgStackSize; // Incoming argument stack size in bytes
8603+
bool compHasMultiSlotArgs; // Caller has >8 byte sized struct parameter
8604+
#endif // FEATURE_FASTTAILCALL
86048605

86058606
unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present);
86068607
int compTypeCtxtArg; // position of hidden param for type context for generic code (CORINFO_CALLCONV_PARAMTYPE)

src/jit/lclvars.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ void Compiler::lvaInitArgs(InitVarDscInfo* varDscInfo)
360360
// Save the stack usage information
361361
// We can get register usage information using codeGen->intRegState and
362362
// codeGen->floatRegState
363-
info.compArgStackSize = varDscInfo->stackArgSize;
363+
info.compArgStackSize = varDscInfo->stackArgSize;
364+
info.compHasMultiSlotArgs = varDscInfo->hasMultiSlotStruct;
364365
#endif // FEATURE_FASTTAILCALL
365366

366367
// The total argument size must be aligned.
@@ -797,8 +798,9 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo)
797798
// If there is a second eightbyte, get a register for it too and map the arg to the reg number.
798799
if (structDesc.eightByteCount >= 2)
799800
{
800-
secondEightByteType = GetEightByteType(structDesc, 1);
801-
secondAllocatedRegArgNum = varDscInfo->allocRegArg(secondEightByteType, 1);
801+
secondEightByteType = GetEightByteType(structDesc, 1);
802+
secondAllocatedRegArgNum = varDscInfo->allocRegArg(secondEightByteType, 1);
803+
varDscInfo->hasMultiSlotStruct = true;
802804
}
803805

804806
if (secondEightByteType != TYP_UNDEF)
@@ -813,6 +815,7 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo)
813815
{
814816
varDsc->lvOtherArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum + 1, TYP_I_IMPL);
815817
varDsc->addPrefReg(genRegMask(varDsc->lvOtherArgReg), this);
818+
varDscInfo->hasMultiSlotStruct = true;
816819
}
817820
#endif // _TARGET_ARM64_
818821
#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)

src/jit/morph.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7672,6 +7672,7 @@ bool Compiler::fgCanFastTailCall(GenTreeCall* callee)
76727672
}
76737673

76747674
const unsigned maxRegArgs = MAX_REG_ARG;
7675+
hasTwoSlotSizedStruct = hasTwoSlotSizedStruct || info.compHasMultiSlotArgs;
76757676

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

7749-
// Callee has a >8 and <=16 byte struct and arguments that has to go on the stack. Do not fastTailCall.
7750-
if (calleeStackSize > 0 && hasTwoSlotSizedStruct)
7750+
// Either the caller or callee has a >8 and <=16 byte struct and arguments that has to go on the stack. Do not
7751+
// fastTailCall.
7752+
//
7753+
// When either the caller or callee have multi-stlot stack arguments we cannot safely
7754+
// shuffle arguments in LowerFastTailCall. See https://github.com/dotnet/coreclr/issues/12468.
7755+
if (hasStackArgs && hasTwoSlotSizedStruct)
77517756
{
77527757
reportFastTailCallDecision("Will not fastTailCall calleeStackSize > 0 && hasTwoSlotSizedStruct",
77537758
callerStackSize, calleeStackSize);

src/jit/register_arg_convention.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct InitVarDscInfo
2929
#if FEATURE_FASTTAILCALL
3030
// It is used to calculate argument stack size information in byte
3131
unsigned stackArgSize;
32+
bool hasMultiSlotStruct;
3233
#endif // FEATURE_FASTTAILCALL
3334

3435
public:
@@ -49,7 +50,8 @@ struct InitVarDscInfo
4950
#endif // _TARGET_ARM_
5051

5152
#if FEATURE_FASTTAILCALL
52-
stackArgSize = 0;
53+
stackArgSize = 0;
54+
hasMultiSlotStruct = false;
5355
#endif // FEATURE_FASTTAILCALL
5456
}
5557

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Runtime.CompilerServices;
7+
8+
class X
9+
{
10+
// a -> rdi
11+
// b -> rsi
12+
// c -> rdx
13+
// -> rcx
14+
// d -> r8
15+
// e -> r9
16+
// f -> s[0]
17+
// g -> s[1]
18+
public static int F(int a, int b, Guid c, int d, int e, int f, int g)
19+
{
20+
Guid[] z = new Guid[] { c };
21+
// Bug is here passing params to G: f gets trashed by g.
22+
return G(a, b, z, d, e, f, g);
23+
}
24+
25+
// loop here is just to make this method too big to inline
26+
// if we set [noinline] to effect this, we won't tail call it either.
27+
//
28+
// a -> rdi
29+
// b -> rsi
30+
// c -> rdx
31+
// d -> rcx
32+
// e -> r8
33+
// f -> r9
34+
// g -> s[0]
35+
public static int G(int a, int b, Guid[] c, int d, int e, int f, int g)
36+
{
37+
int r = 0;
38+
for (int i = 0; i < 10; i++)
39+
{
40+
r += f + g;
41+
}
42+
return r / 10;
43+
}
44+
45+
// No-opt to stop F from being inlined without marking it noinline
46+
[MethodImpl(MethodImplOptions.NoOptimization)]
47+
public static int Main()
48+
{
49+
int result = F(0, 1, Guid.Empty, 3, 4, 33, 67);
50+
Console.WriteLine($"Result={result}");
51+
return result;
52+
}
53+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<SchemaVersion>2.0</SchemaVersion>
8+
<ProjectGuid>{2649FAFE-07BF-4F93-8120-BA9A69285ABB}</ProjectGuid>
9+
<OutputType>Exe</OutputType>
10+
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
11+
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
12+
</PropertyGroup>
13+
<!-- Default configurations to help VS understand the configurations -->
14+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
15+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "></PropertyGroup>
16+
<PropertyGroup>
17+
<DebugType>None</DebugType>
18+
<Optimize>True</Optimize>
19+
</PropertyGroup>
20+
<ItemGroup>
21+
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
22+
<Visible>False</Visible>
23+
</CodeAnalysisDependentAssemblyPaths>
24+
</ItemGroup>
25+
<ItemGroup>
26+
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
27+
</ItemGroup>
28+
<ItemGroup>
29+
<Compile Include="$(MSBuildProjectName).cs" />
30+
</ItemGroup>
31+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
32+
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
33+
</Project>

0 commit comments

Comments
 (0)