Skip to content

Propagate static readonly loads by value during inlining #108579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 19 commits into from
Closed
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
14 changes: 9 additions & 5 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,9 +851,10 @@ class FgStack
return false;
}
const unsigned argNum = value - SLOT_ARGUMENT;
if (argNum < info->argCnt)
if ((argNum < info->argCnt) && info->inlArgInfo[argNum].argIsConstant)
{
return info->inlArgInfo[argNum].argIsInvariant;
assert(info->inlArgInfo[argNum].argIsInvariant);
return true;
}
return false;
}
Expand Down Expand Up @@ -2671,8 +2672,9 @@ void Compiler::fgObserveInlineConstants(OPCODE opcode, const FgStack& stack, boo
// Check for the double whammy of an incoming constant argument
// feeding a constant test.
unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
if (impInlineInfo->inlArgInfo[varNum].argIsInvariant)
if (impInlineInfo->inlArgInfo[varNum].argIsConstant)
{
assert(impInlineInfo->inlArgInfo[varNum].argIsInvariant);
compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
}
}
Expand Down Expand Up @@ -2713,8 +2715,9 @@ void Compiler::fgObserveInlineConstants(OPCODE opcode, const FgStack& stack, boo
compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_TEST);

unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
if (impInlineInfo->inlArgInfo[varNum].argIsInvariant)
if (impInlineInfo->inlArgInfo[varNum].argIsConstant)
{
assert(impInlineInfo->inlArgInfo[varNum].argIsInvariant);
compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
}
}
Expand All @@ -2724,8 +2727,9 @@ void Compiler::fgObserveInlineConstants(OPCODE opcode, const FgStack& stack, boo
compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_TEST);

unsigned varNum = FgStack::SlotTypeToArgNum(slot1);
if (impInlineInfo->inlArgInfo[varNum].argIsInvariant)
if (impInlineInfo->inlArgInfo[varNum].argIsConstant)
{
assert(impInlineInfo->inlArgInfo[varNum].argIsInvariant);
compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
}
}
Expand Down
9 changes: 7 additions & 2 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4258,7 +4258,7 @@ GenTree* Compiler::impImportStaticFieldAddress(CORINFO_RESOLVED_TOKEN* pResolved
}
if (isStaticReadOnlyInitedRef)
{
indirFlags |= (GTF_IND_INVARIANT | GTF_IND_NONNULL);
indirFlags |= (GTF_IND_NONFAULTING | GTF_IND_INVARIANT | GTF_IND_NONNULL);
}
break;
}
Expand Down Expand Up @@ -12638,7 +12638,9 @@ void Compiler::impFixPredLists()
//
bool Compiler::impIsInvariant(const GenTree* tree)
{
return tree->OperIsConst() || impIsAddressInLocal(tree) || tree->OperIs(GT_FTN_ADDR);
return tree->OperIsConst() || impIsAddressInLocal(tree) || tree->OperIs(GT_FTN_ADDR) ||
(tree->OperIs(GT_IND) && tree->AsIndir()->IsInvariantLoad() &&
((tree->AsIndir()->gtFlags & GTF_SIDE_EFFECT) == 0));
}

//------------------------------------------------------------------------
Expand Down Expand Up @@ -13073,6 +13075,7 @@ void Compiler::impInlineRecordArgInfo(InlineInfo* pInlineInfo,
if (impIsInvariant(curArgVal))
{
inlCurArgInfo->argIsInvariant = true;
inlCurArgInfo->argIsConstant = !curArgVal->OperIs(GT_IND);
if (inlCurArgInfo->argIsThis && (curArgVal->gtOper == GT_CNS_INT) && (curArgVal->AsIntCon()->gtIconVal == 0))
{
// Abort inlining at this call site
Expand All @@ -13083,6 +13086,7 @@ void Compiler::impInlineRecordArgInfo(InlineInfo* pInlineInfo,
else if (gtIsTypeof(curArgVal))
{
inlCurArgInfo->argIsInvariant = true;
inlCurArgInfo->argIsConstant = true;
inlCurArgInfo->argHasSideEff = false;
}

Expand Down Expand Up @@ -13216,6 +13220,7 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo)
if (arg.GetNode()->IsCnsIntOrI())
{
ctxInfo->argIsInvariant = true;
ctxInfo->argIsConstant = true;
}
else
{
Expand Down
21 changes: 11 additions & 10 deletions src/coreclr/jit/inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -643,22 +643,23 @@ struct LateDevirtualizationInfo

struct InlArgInfo
{
CallArg* arg; // the caller argument
GenTree* argBashTmpNode; // tmp node created, if it may be replaced with actual arg
unsigned argTmpNum; // the argument tmp number
unsigned argIsUsed : 1; // is this arg used at all?
unsigned argIsInvariant : 1; // the argument is a constant or a local variable address
unsigned argIsLclVar : 1; // the argument is a local variable
unsigned argIsThis : 1; // the argument is the 'this' pointer
unsigned argHasSideEff : 1; // the argument has side effects
unsigned argHasGlobRef : 1; // the argument has a global ref
CallArg* arg; // the caller argument
GenTree* argBashTmpNode; // tmp node created, if it may be replaced with actual arg
unsigned argTmpNum; // the argument tmp number
unsigned argIsUsed : 1; // is this arg used at all?
unsigned argIsInvariant : 1; // the argument is a constant, a local variable address or a static readonly field
unsigned argIsLclVar : 1; // the argument is a local variable
unsigned argIsThis : 1; // the argument is the 'this' pointer
unsigned argHasSideEff : 1; // the argument has side effects
unsigned argHasGlobRef : 1; // the argument has a global ref
unsigned argHasCallerLocalRef : 1; // the argument value depends on an aliased caller local
unsigned argHasTmp : 1; // the argument will be evaluated to a temp
unsigned argHasLdargaOp : 1; // Is there LDARGA(s) operation on this argument?
unsigned argHasStargOp : 1; // Is there STARG(s) operation on this argument?
unsigned argIsByRefToStructLocal : 1; // Is this arg an address of a struct local or a normed struct local or a
// field in them?
unsigned argIsExact : 1; // Is this arg of an exact class?
unsigned argIsExact : 1; // Is this arg of an exact class?
unsigned argIsConstant : 1; // the argument is a constant or a local variable address
};

// InlLclVarInfo describes inline candidate argument and local variable properties.
Expand Down
Loading