Skip to content

Commit

Permalink
PGO: Profiled SequenceEqual (dotnet#96571)
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorBo authored Jan 7, 2024
1 parent c33557d commit c1de4ba
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 7 deletions.
11 changes: 10 additions & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -9515,7 +9515,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
{
Memset,
Memcpy,
Memmove
Memmove,
ProfiledMemmove,
ProfiledMemcmp
};

//------------------------------------------------------------------------
Expand Down Expand Up @@ -9589,6 +9591,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
threshold = maxRegSize * 4;
}

// For profiled memcmp/memmove we don't want to unroll too much as it's just a guess,
// and it works better for small sizes.
if ((type == UnrollKind::ProfiledMemcmp) || (type == UnrollKind::ProfiledMemmove))
{
threshold = maxRegSize * 2;
}

return threshold;
}

Expand Down
12 changes: 8 additions & 4 deletions src/coreclr/jit/fgprofile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1950,9 +1950,13 @@ class ValueHistogramProbeVisitor final : public GenTreeVisitor<ValueHistogramPro
Compiler::fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
{
GenTree* const node = *use;
if (node->IsCall() && node->AsCall()->IsSpecialIntrinsic(m_compiler, NI_System_Buffer_Memmove))
if (node->IsCall() && node->AsCall()->IsSpecialIntrinsic())
{
m_functor(m_compiler, node);
const NamedIntrinsic ni = m_compiler->lookupNamedIntrinsic(node->AsCall()->gtCallMethHnd);
if ((ni == NI_System_Buffer_Memmove) || (ni == NI_System_SpanHelpers_SequenceEqual))
{
m_functor(m_compiler, node);
}
}
return Compiler::WALK_CONTINUE;
}
Expand Down Expand Up @@ -2276,8 +2280,8 @@ class ValueHistogramProbeInserter
return;
}

// Only Buffer.Memmove call is currently expected
assert(node->IsCall() && (node->AsCall()->IsSpecialIntrinsic(compiler, NI_System_Buffer_Memmove)));
assert(node->AsCall()->IsSpecialIntrinsic(compiler, NI_System_Buffer_Memmove) ||
node->AsCall()->IsSpecialIntrinsic(compiler, NI_System_SpanHelpers_SequenceEqual));

const ICorJitInfo::PgoInstrumentationSchema& countEntry = m_schema[*m_currentSchemaIndex];
if (countEntry.ILOffset !=
Expand Down
39 changes: 37 additions & 2 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,32 @@ var_types Compiler::impImportCall(OPCODE opcode,
{
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("non-inline candidate call"));
}

if (JitConfig.JitProfileValues() && call->IsCall() &&
call->AsCall()->IsSpecialIntrinsic(this, NI_System_SpanHelpers_SequenceEqual))
{
if (opts.IsOptimizedWithProfile())
{
call = impDuplicateWithProfiledArg(call->AsCall(), rawILOffset);
if (call->OperIs(GT_QMARK))
{
// QMARK has to be a root node
unsigned tmp = lvaGrabTemp(true DEBUGARG("Grabbing temp for Qmark"));
impStoreTemp(tmp, call, CHECK_SPILL_ALL);
call = gtNewLclvNode(tmp, call->TypeGet());
}
}
else if (opts.IsInstrumented())
{
// We might want to instrument it for optimized versions too, but we don't currently.
HandleHistogramProfileCandidateInfo* pInfo =
new (this, CMK_Inlining) HandleHistogramProfileCandidateInfo;
pInfo->ilOffset = rawILOffset;
pInfo->probeIndex = 0;
call->AsCall()->gtHandleHistogramProfileCandidateInfo = pInfo;
compCurBB->SetFlags(BBF_HAS_VALUE_PROFILE);
}
}
}

//-------------------------------------------------------------------------
Expand Down Expand Up @@ -1536,7 +1562,15 @@ GenTree* Compiler::impDuplicateWithProfiledArg(GenTreeCall* call, IL_OFFSET ilOf
argNum = 2;

minValue = 1; // TODO: enable for 0 as well.
maxValue = (ssize_t)getUnrollThreshold(Memmove);
maxValue = (ssize_t)getUnrollThreshold(ProfiledMemmove);
}
else if (call->IsSpecialIntrinsic(this, NI_System_SpanHelpers_SequenceEqual))
{
// dst(0), src(1), len(2)
argNum = 2;

minValue = 1; // TODO: enable for 0 as well.
maxValue = (ssize_t)getUnrollThreshold(ProfiledMemcmp);
}
else
{
Expand Down Expand Up @@ -2729,7 +2763,8 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
break;

case NI_System_Buffer_Memmove:
// We're going to instrument this one
case NI_System_SpanHelpers_SequenceEqual:
// We're going to instrument these
betterToExpand = opts.IsInstrumented();
break;

Expand Down

0 comments on commit c1de4ba

Please sign in to comment.