Skip to content

Commit d257079

Browse files
authored
JIT: Unify handling of InstParam argument during inlining (#112119)
* Handle InstParam in the same way as all other arguments * Insert the evaluation of the InstParam in the right spot when inlining succeeded Fix #112092
1 parent d59ab53 commit d257079

File tree

5 files changed

+88
-69
lines changed

5 files changed

+88
-69
lines changed

src/coreclr/jit/compiler.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -5238,7 +5238,7 @@ class Compiler
52385238
InlineCandidateInfo** ppInlineCandidateInfo,
52395239
InlineResult* inlineResult);
52405240

5241-
void impInlineRecordArgInfo(InlineInfo* pInlineInfo, CallArg* arg, unsigned argNum, InlineResult* inlineResult);
5241+
void impInlineRecordArgInfo(InlineInfo* pInlineInfo, CallArg* arg, InlArgInfo* argInfo, InlineResult* inlineResult);
52425242

52435243
void impInlineInitVars(InlineInfo* pInlineInfo);
52445244

src/coreclr/jit/fginline.cpp

+20-8
Original file line numberDiff line numberDiff line change
@@ -2045,20 +2045,32 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
20452045
}
20462046
}
20472047

2048-
// Append the InstParam
2049-
if (inlineInfo->inlInstParamArgInfo != nullptr)
2048+
#ifdef DEBUG
2049+
if (call->gtArgs.CountUserArgs() > 0)
20502050
{
2051-
fgInsertInlineeArgument(*inlineInfo->inlInstParamArgInfo, block, &afterStmt, &newStmt, callDI);
2051+
JITDUMP("\nArguments setup:\n");
20522052
}
2053+
#endif
20532054

2054-
// Treat arguments that had to be assigned to temps
2055-
if (inlineInfo->argCnt)
2055+
unsigned ilArgNum = 0;
2056+
for (CallArg& arg : call->gtArgs.Args())
20562057
{
2057-
JITDUMP("\nArguments setup:\n");
2058-
for (unsigned argNum = 0; argNum < inlineInfo->argCnt; argNum++)
2058+
InlArgInfo* argInfo = nullptr;
2059+
switch (arg.GetWellKnownArg())
20592060
{
2060-
fgInsertInlineeArgument(inlArgInfo[argNum], block, &afterStmt, &newStmt, callDI);
2061+
case WellKnownArg::RetBuffer:
2062+
continue;
2063+
case WellKnownArg::InstParam:
2064+
argInfo = inlineInfo->inlInstParamArgInfo;
2065+
break;
2066+
default:
2067+
assert(ilArgNum < inlineInfo->argCnt);
2068+
argInfo = &inlineInfo->inlArgInfo[ilArgNum++];
2069+
break;
20612070
}
2071+
2072+
assert(argInfo != nullptr);
2073+
fgInsertInlineeArgument(*argInfo, block, &afterStmt, &newStmt, callDI);
20622074
}
20632075

20642076
// Add the CCTOR check if asked for.

src/coreclr/jit/gentree.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,37 @@ unsigned CallArgs::GetIndex(CallArg* arg)
15811581
return (unsigned)-1;
15821582
}
15831583

1584+
//---------------------------------------------------------------
1585+
// GetIndex: Get the user arg index for the specified argument (IL index).
1586+
//
1587+
// Parameters:
1588+
// arg - The argument to obtain the index of.
1589+
//
1590+
// Returns:
1591+
// The user index.
1592+
//
1593+
unsigned CallArgs::GetUserIndex(CallArg* arg)
1594+
{
1595+
unsigned i = 0;
1596+
for (CallArg& a : Args())
1597+
{
1598+
if (!a.IsUserArg())
1599+
{
1600+
continue;
1601+
}
1602+
1603+
if (&a == arg)
1604+
{
1605+
return i;
1606+
}
1607+
1608+
i++;
1609+
}
1610+
1611+
assert(!"Could not find argument in arg list");
1612+
return (unsigned)-1;
1613+
}
1614+
15841615
//---------------------------------------------------------------
15851616
// Reverse: Reverse the specified subrange of arguments.
15861617
//

src/coreclr/jit/gentree.h

+1
Original file line numberDiff line numberDiff line change
@@ -4920,6 +4920,7 @@ class CallArgs
49204920
CallArg* GetArgByIndex(unsigned index);
49214921
CallArg* GetUserArgByIndex(unsigned index);
49224922
unsigned GetIndex(CallArg* arg);
4923+
unsigned GetUserIndex(CallArg* arg);
49234924

49244925
bool IsEmpty() const
49254926
{

src/coreclr/jit/importer.cpp

+35-60
Original file line numberDiff line numberDiff line change
@@ -12988,7 +12988,7 @@ void Compiler::impCanInlineIL(CORINFO_METHOD_HANDLE fncHandle,
1298812988
// Arguments:
1298912989
// pInlineInfo - inline info for the inline candidate
1299012990
// arg - the caller argument
12991-
// argNum - logical index of this argument
12991+
// argInfo - Structure to record information into
1299212992
// inlineResult - result of ongoing inline evaluation
1299312993
//
1299412994
// Notes:
@@ -13000,12 +13000,10 @@ void Compiler::impCanInlineIL(CORINFO_METHOD_HANDLE fncHandle,
1300013000

1300113001
void Compiler::impInlineRecordArgInfo(InlineInfo* pInlineInfo,
1300213002
CallArg* arg,
13003-
unsigned argNum,
13003+
InlArgInfo* argInfo,
1300413004
InlineResult* inlineResult)
1300513005
{
13006-
InlArgInfo* inlCurArgInfo = &pInlineInfo->inlArgInfo[argNum];
13007-
13008-
inlCurArgInfo->arg = arg;
13006+
argInfo->arg = arg;
1300913007
GenTree* curArgVal = arg->GetNode();
1301013008

1301113009
assert(!curArgVal->OperIs(GT_RET_EXPR));
@@ -13018,7 +13016,7 @@ void Compiler::impInlineRecordArgInfo(InlineInfo* pInlineInfo,
1301813016

1301913017
if (varTypeIsStruct(varDsc))
1302013018
{
13021-
inlCurArgInfo->argIsByRefToStructLocal = true;
13019+
argInfo->argIsByRefToStructLocal = true;
1302213020
#ifdef FEATURE_SIMD
1302313021
if (varTypeIsSIMD(varDsc))
1302413022
{
@@ -13033,22 +13031,21 @@ void Compiler::impInlineRecordArgInfo(InlineInfo* pInlineInfo,
1303313031

1303413032
if (curArgVal->gtFlags & GTF_ALL_EFFECT)
1303513033
{
13036-
inlCurArgInfo->argHasGlobRef = (curArgVal->gtFlags & GTF_GLOB_REF) != 0;
13037-
inlCurArgInfo->argHasSideEff = (curArgVal->gtFlags & (GTF_ALL_EFFECT & ~GTF_GLOB_REF)) != 0;
13034+
argInfo->argHasGlobRef = (curArgVal->gtFlags & GTF_GLOB_REF) != 0;
13035+
argInfo->argHasSideEff = (curArgVal->gtFlags & (GTF_ALL_EFFECT & ~GTF_GLOB_REF)) != 0;
1303813036
}
1303913037

1304013038
if (curArgVal->gtOper == GT_LCL_VAR)
1304113039
{
13042-
inlCurArgInfo->argIsLclVar = true;
13043-
13044-
/* Remember the "original" argument number */
13045-
INDEBUG(curArgVal->AsLclVar()->gtLclILoffs = argNum;)
13040+
argInfo->argIsLclVar = true;
1304613041
}
1304713042

13043+
argInfo->argIsThis = arg->GetWellKnownArg() == WellKnownArg::ThisPointer;
13044+
1304813045
if (impIsInvariant(curArgVal))
1304913046
{
13050-
inlCurArgInfo->argIsInvariant = true;
13051-
if (inlCurArgInfo->argIsThis && (curArgVal->gtOper == GT_CNS_INT) && (curArgVal->AsIntCon()->gtIconVal == 0))
13047+
argInfo->argIsInvariant = true;
13048+
if (argInfo->argIsThis && (curArgVal->gtOper == GT_CNS_INT) && (curArgVal->AsIntCon()->gtIconVal == 0))
1305213049
{
1305313050
// Abort inlining at this call site
1305413051
inlineResult->NoteFatal(InlineObservation::CALLSITE_ARG_HAS_NULL_THIS);
@@ -13057,13 +13054,13 @@ void Compiler::impInlineRecordArgInfo(InlineInfo* pInlineInfo,
1305713054
}
1305813055
else if (gtIsTypeof(curArgVal))
1305913056
{
13060-
inlCurArgInfo->argIsInvariant = true;
13061-
inlCurArgInfo->argHasSideEff = false;
13057+
argInfo->argIsInvariant = true;
13058+
argInfo->argHasSideEff = false;
1306213059
}
1306313060

13064-
bool isExact = false;
13065-
bool isNonNull = false;
13066-
inlCurArgInfo->argIsExact = (gtGetClassHandle(curArgVal, &isExact, &isNonNull) != NO_CLASS_HANDLE) && isExact;
13061+
bool isExact = false;
13062+
bool isNonNull = false;
13063+
argInfo->argIsExact = (gtGetClassHandle(curArgVal, &isExact, &isNonNull) != NO_CLASS_HANDLE) && isExact;
1306713064

1306813065
// If the arg is a local that is address-taken, we can't safely
1306913066
// directly substitute it into the inlinee.
@@ -13074,51 +13071,51 @@ void Compiler::impInlineRecordArgInfo(InlineInfo* pInlineInfo,
1307413071
// which is safe in this case.
1307513072
//
1307613073
// Instead mark the arg as having a caller local ref.
13077-
if (!inlCurArgInfo->argIsInvariant && gtHasLocalsWithAddrOp(curArgVal))
13074+
if (!argInfo->argIsInvariant && gtHasLocalsWithAddrOp(curArgVal))
1307813075
{
13079-
inlCurArgInfo->argHasCallerLocalRef = true;
13076+
argInfo->argHasCallerLocalRef = true;
1308013077
}
1308113078

1308213079
#ifdef DEBUG
1308313080
if (verbose)
1308413081
{
13085-
if (inlCurArgInfo->argIsThis)
13082+
if (arg->GetWellKnownArg() != WellKnownArg::None)
1308613083
{
13087-
printf("thisArg:");
13084+
printf("%s:", getWellKnownArgName(arg->GetWellKnownArg()));
1308813085
}
1308913086
else
1309013087
{
13091-
printf("\nArgument #%u:", argNum);
13088+
printf("IL argument #%u:", pInlineInfo->iciCall->gtArgs.GetUserIndex(arg));
1309213089
}
13093-
if (inlCurArgInfo->argIsLclVar)
13090+
if (argInfo->argIsLclVar)
1309413091
{
1309513092
printf(" is a local var");
1309613093
}
13097-
if (inlCurArgInfo->argIsInvariant)
13094+
if (argInfo->argIsInvariant)
1309813095
{
1309913096
printf(" is a constant or invariant");
1310013097
}
13101-
if (inlCurArgInfo->argHasGlobRef)
13098+
if (argInfo->argHasGlobRef)
1310213099
{
1310313100
printf(" has global refs");
1310413101
}
13105-
if (inlCurArgInfo->argHasCallerLocalRef)
13102+
if (argInfo->argHasCallerLocalRef)
1310613103
{
1310713104
printf(" has caller local ref");
1310813105
}
13109-
if (inlCurArgInfo->argHasSideEff)
13106+
if (argInfo->argHasSideEff)
1311013107
{
1311113108
printf(" has side effects");
1311213109
}
13113-
if (inlCurArgInfo->argHasLdargaOp)
13110+
if (argInfo->argHasLdargaOp)
1311413111
{
1311513112
printf(" has ldarga effect");
1311613113
}
13117-
if (inlCurArgInfo->argHasStargOp)
13114+
if (argInfo->argHasStargOp)
1311813115
{
1311913116
printf(" has starg effect");
1312013117
}
13121-
if (inlCurArgInfo->argIsByRefToStructLocal)
13118+
if (argInfo->argIsByRefToStructLocal)
1312213119
{
1312313120
printf(" is byref to a struct local");
1312413121
}
@@ -13174,51 +13171,29 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo)
1317413171
unsigned ilArgCnt = 0;
1317513172
for (CallArg& arg : call->gtArgs.Args())
1317613173
{
13174+
InlArgInfo* argInfo;
1317713175
switch (arg.GetWellKnownArg())
1317813176
{
13179-
case WellKnownArg::ThisPointer:
13180-
inlArgInfo[ilArgCnt].argIsThis = true;
13181-
break;
1318213177
case WellKnownArg::RetBuffer:
1318313178
// This does not appear in the table of inline arg info; do not include them
1318413179
continue;
1318513180
case WellKnownArg::InstParam:
13186-
{
13187-
InlArgInfo* ctxInfo = new (this, CMK_Inlining) InlArgInfo{};
13188-
ctxInfo->arg = &arg;
13189-
ctxInfo->argTmpNum = BAD_VAR_NUM;
13190-
ctxInfo->argIsLclVar = arg.GetNode()->OperIs(GT_LCL_VAR);
13191-
if (arg.GetNode()->IsCnsIntOrI())
13192-
{
13193-
ctxInfo->argIsInvariant = true;
13194-
}
13195-
else
13196-
{
13197-
// Conservative approach
13198-
ctxInfo->argHasSideEff = true;
13199-
ctxInfo->argHasGlobRef = true;
13200-
}
13201-
pInlineInfo->inlInstParamArgInfo = ctxInfo;
13202-
continue;
13203-
}
13181+
pInlineInfo->inlInstParamArgInfo = argInfo = new (this, CMK_Inlining) InlArgInfo{};
13182+
break;
1320413183
default:
13184+
argInfo = &inlArgInfo[ilArgCnt++];
1320513185
break;
1320613186
}
1320713187

1320813188
arg.SetEarlyNode(gtFoldExpr(arg.GetEarlyNode()));
13209-
impInlineRecordArgInfo(pInlineInfo, &arg, ilArgCnt, inlineResult);
13189+
impInlineRecordArgInfo(pInlineInfo, &arg, argInfo, inlineResult);
1321013190

1321113191
if (inlineResult->IsFailure())
1321213192
{
1321313193
return;
1321413194
}
13215-
13216-
ilArgCnt++;
1321713195
}
1321813196

13219-
/* Make sure we got the arg number right */
13220-
assert(ilArgCnt == methInfo->args.totalILArgs());
13221-
1322213197
#ifdef FEATURE_SIMD
1322313198
bool foundSIMDType = pInlineInfo->hasSIMDTypeArgLocalOrReturn;
1322413199
#endif // FEATURE_SIMD
@@ -13598,7 +13573,7 @@ unsigned Compiler::impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reas
1359813573
//
1359913574
// This method will side effect inlArgInfo. It should only be called
1360013575
// for actual uses of the argument in the inlinee.
13601-
13576+
//
1360213577
GenTree* Compiler::impInlineFetchArg(InlArgInfo& argInfo, const InlLclVarInfo& lclInfo)
1360313578
{
1360413579
// Cache the relevant arg and lcl info for this argument.

0 commit comments

Comments
 (0)