Skip to content
Draft
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
7 changes: 7 additions & 0 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -4411,6 +4411,7 @@ enum GenTreeCallFlags : unsigned int
GTF_CALL_M_CAST_OBJ_NONNULL = 0x04000000, // if we expand this specific cast we don't need to check the input object for null
// NOTE: if needed, this flag can be removed, and we can introduce new _NONNUL cast helpers
GTF_CALL_M_STACK_ARRAY = 0x08000000, // this call is a new array helper for a stack allocated array.
GTF_CALL_M_PINVOKE_STUB_NO_INLINE = 0x10000000, // PInvoke call where the IL stub should not be inlined
};

inline constexpr GenTreeCallFlags operator ~(GenTreeCallFlags a)
Expand Down Expand Up @@ -5508,6 +5509,12 @@ struct GenTreeCall final : public GenTree
return (gtCallMoreFlags & GTF_CALL_M_PINVOKE) != 0;
}

// Returns true if this PInvoke call's IL stub should not be inlined.
bool IsPInvokeStubNoInline() const
{
return (gtCallMoreFlags & GTF_CALL_M_PINVOKE_STUB_NO_INLINE) != 0;
}

// Note that the distinction of whether tail prefixed or an implicit tail call
// is maintained on a call node till fgMorphCall() after which it will be
// either a tail call (i.e. IsTailCall() is true) or a non-tail call.
Expand Down
35 changes: 14 additions & 21 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6930,6 +6930,8 @@ void Compiler::impCheckForPInvokeCall(
{
if (!impCanPInvokeInline())
{
// Mark this so we won't decide to inline the stub.
call->gtCallMoreFlags |= GTF_CALL_M_PINVOKE_STUB_NO_INLINE;
return;
}

Expand All @@ -6942,6 +6944,8 @@ void Compiler::impCheckForPInvokeCall(
if ((!compIsForInlining() && block->isRunRarely()) ||
(compIsForInlining() && impInlineInfo->iciBlock->isRunRarely()))
{
// Mark this so we won't decide to inline the stub.
call->gtCallMoreFlags |= GTF_CALL_M_PINVOKE_STUB_NO_INLINE;
return;
}
}
Expand Down Expand Up @@ -8376,12 +8380,11 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call,
}
}

// The inliner gets confused when the unmanaged convention reverses arg order (like x86).
// Just suppress for all targets for now.
//
if (call->GetUnmanagedCallConv() != CorInfoCallConvExtension::Managed)
if (call->IsUnmanaged())
{
inlineResult->NoteFatal(InlineObservation::CALLEE_HAS_UNMANAGED_CALLCONV);
// We must have IL to inline.
//
inlineResult->NoteFatal(InlineObservation::CALLEE_IS_UNMANAGED);
return;
}

Expand Down Expand Up @@ -8480,15 +8483,13 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call,
return;
}

/* Check legality of PInvoke callsite (for inlining of marshalling code) */

if (methAttr & CORINFO_FLG_PINVOKE)
// Don't inline the IL stub for PInvoke calls where impCheckForPInvokeCall set this flag.
if (call->IsPInvokeStubNoInline())
{
if (!impCanPInvokeInlineCallSite(compCurBB))
{
inlineResult->NoteFatal(InlineObservation::CALLSITE_PINVOKE_EH);
return;
}
assert(!call->IsUnmanaged());
assert(methAttr & CORINFO_FLG_PINVOKE);
inlineResult->NoteFatal(InlineObservation::CALLSITE_PINVOKE_STUB_NO_INLINE);
return;
}

InlineCandidateInfo* inlineCandidateInfo = nullptr;
Expand All @@ -8509,14 +8510,6 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call,
inlineResult->NoteFatal(InlineObservation::CALLSITE_IS_WITHIN_FILTER);
return;
}

// Do not inline pinvoke stubs with EH.
//
if ((methAttr & CORINFO_FLG_PINVOKE) != 0)
{
inlineResult->NoteFatal(InlineObservation::CALLEE_HAS_EH);
return;
}
}

// The old value should be null OR this call should be a guarded devirtualization candidate.
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/inline.def
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ INLINE_OBSERVATION(HAS_MANAGED_VARARGS, bool, "managed varargs",
INLINE_OBSERVATION(HAS_NATIVE_VARARGS, bool, "native varargs", FATAL, CALLEE)
INLINE_OBSERVATION(HAS_NO_BODY, bool, "has no body", FATAL, CALLEE)
INLINE_OBSERVATION(HAS_NULL_FOR_LDELEM, bool, "has null pointer for ldelem", FATAL, CALLEE)
INLINE_OBSERVATION(HAS_UNMANAGED_CALLCONV, bool, "has unmanaged calling convention", FATAL, CALLEE)
INLINE_OBSERVATION(IS_ARRAY_METHOD, bool, "is array method", FATAL, CALLEE)
INLINE_OBSERVATION(IS_JIT_NOINLINE, bool, "noinline per JitNoinline", FATAL, CALLEE)
INLINE_OBSERVATION(IS_NOINLINE, bool, "noinline per IL/cached result", FATAL, CALLEE)
INLINE_OBSERVATION(IS_SYNCHRONIZED, bool, "is synchronized", FATAL, CALLEE)
INLINE_OBSERVATION(IS_UNMANAGED, bool, "is unmanaged code", FATAL, CALLEE)
INLINE_OBSERVATION(IS_VM_NOINLINE, bool, "noinline per VM", FATAL, CALLEE)
INLINE_OBSERVATION(LACKS_RETURN, bool, "no return opcode", FATAL, CALLEE)
INLINE_OBSERVATION(LDFLD_NEEDS_HELPER, bool, "ldfld needs helper", FATAL, CALLEE)
Expand Down Expand Up @@ -163,7 +163,7 @@ INLINE_OBSERVATION(RANDOM_REJECT, bool, "random reject",
INLINE_OBSERVATION(RETURN_TYPE_MISMATCH, bool, "return type mismatch", FATAL, CALLSITE)
INLINE_OBSERVATION(STFLD_NEEDS_HELPER, bool, "stfld needs helper", FATAL, CALLSITE)
INLINE_OBSERVATION(TOO_MANY_LOCALS, bool, "too many locals", FATAL, CALLSITE)
INLINE_OBSERVATION(PINVOKE_EH, bool, "PInvoke call site with EH", FATAL, CALLSITE)
INLINE_OBSERVATION(PINVOKE_STUB_NO_INLINE, bool, "PInvoke stub not to be inlined", FATAL, CALLSITE)

// ------ Call Site Performance -------

Expand Down
Loading