summaryrefslogtreecommitdiff
path: root/src/jit
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit')
-rw-r--r--src/jit/compiler.h3
-rw-r--r--src/jit/flowgraph.cpp4
-rw-r--r--src/jit/importer.cpp29
-rw-r--r--src/jit/indirectcalltransformer.cpp6
4 files changed, 34 insertions, 8 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 21a426e3f1..6c93434dea 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -3329,7 +3329,8 @@ public:
unsigned* methodFlags,
CORINFO_CONTEXT_HANDLE* contextHandle,
CORINFO_CONTEXT_HANDLE* exactContextHandle,
- bool isLateDevirtualization);
+ bool isLateDevirtualization,
+ bool isExplicitTailCall);
//=========================================================================
// PROTECTED
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp
index eedb1aa58f..86f18ca404 100644
--- a/src/jit/flowgraph.cpp
+++ b/src/jit/flowgraph.cpp
@@ -22552,7 +22552,9 @@ Compiler::fgWalkResult Compiler::fgLateDevirtualization(GenTree** pTree, fgWalkD
unsigned methodFlags = 0;
CORINFO_CONTEXT_HANDLE context = nullptr;
const bool isLateDevirtualization = true;
- comp->impDevirtualizeCall(call, &method, &methodFlags, &context, nullptr, isLateDevirtualization);
+ bool explicitTailCall = (call->gtCall.gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0;
+ comp->impDevirtualizeCall(call, &method, &methodFlags, &context, nullptr, isLateDevirtualization,
+ explicitTailCall);
}
}
else if (tree->OperGet() == GT_ASG)
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
index 47ed202e1b..27ea06abaf 100644
--- a/src/jit/importer.cpp
+++ b/src/jit/importer.cpp
@@ -5276,7 +5276,7 @@ BOOL Compiler::verIsSDArray(typeInfo ti)
typeInfo Compiler::verGetArrayElemType(typeInfo arrayObjectType)
{
- assert(!arrayObjectType.IsNullObjRef()); // you need to check for null explictly since that is a success case
+ assert(!arrayObjectType.IsNullObjRef()); // you need to check for null explicitly since that is a success case
if (!verIsSDArray(arrayObjectType))
{
@@ -8590,9 +8590,11 @@ var_types Compiler::impImportCall(OPCODE opcode,
assert(obj->gtType == TYP_REF);
// See if we can devirtualize.
+
+ bool explicitTailCall = (tailCall & PREFIX_TAILCALL_EXPLICIT) != 0;
const bool isLateDevirtualization = false;
impDevirtualizeCall(call->AsCall(), &callInfo->hMethod, &callInfo->methodFlags, &callInfo->contextHandle,
- &exactContextHnd, isLateDevirtualization);
+ &exactContextHnd, isLateDevirtualization, explicitTailCall);
}
if (impIsThis(obj))
@@ -8742,7 +8744,6 @@ DONE:
if (info.compCompHnd->canTailCall(info.compMethodHnd, methHnd, exactCalleeHnd, explicitTailCall))
{
- canTailCall = true;
if (explicitTailCall)
{
// In case of explicit tail calls, mark it so that it is not considered
@@ -20174,6 +20175,7 @@ bool Compiler::IsMathIntrinsic(GenTree* tree)
// contextHandle -- [IN/OUT] context handle for the call. Updated iff call devirtualized.
// exactContextHnd -- [OUT] updated context handle iff call devirtualized
// isLateDevirtualization -- if devirtualization is happening after importation
+// isExplicitTailCalll -- [IN] true if we plan on using an explicit tail call
//
// Notes:
// Virtual calls in IL will always "invoke" the base class method.
@@ -20207,7 +20209,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
unsigned* methodFlags,
CORINFO_CONTEXT_HANDLE* contextHandle,
CORINFO_CONTEXT_HANDLE* exactContextHandle,
- bool isLateDevirtualization)
+ bool isLateDevirtualization,
+ bool isExplicitTailCall)
{
assert(call != nullptr);
assert(method != nullptr);
@@ -20558,6 +20561,12 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
{
JITDUMP("Now have direct call to boxed entry point, looking for unboxed entry point\n");
+ if (isExplicitTailCall)
+ {
+ JITDUMP("Call is an explicit tail call, we cannot perform an unbox\n");
+ return;
+ }
+
// Note for some shared methods the unboxed entry point requires an extra parameter.
bool requiresInstMethodTableArg = false;
CORINFO_METHOD_HANDLE unboxedEntryMethod =
@@ -20640,6 +20649,18 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
call->gtCallMethHnd = unboxedEntryMethod;
call->gtCallMoreFlags |= GTF_CALL_M_UNBOXED;
derivedMethod = unboxedEntryMethod;
+
+#if FEATURE_TAILCALL_OPT
+ if (call->IsImplicitTailCall())
+ {
+ JITDUMP("Clearing the implicit tail call flag\n");
+
+ // If set, we clear the implicit tail call flag
+ // as we just introduced a new address taken local variable
+ //
+ call->gtCallMoreFlags &= ~GTF_CALL_M_IMPLICIT_TAILCALL;
+ }
+#endif // FEATURE_TAILCALL_OPT
}
else
{
diff --git a/src/jit/indirectcalltransformer.cpp b/src/jit/indirectcalltransformer.cpp
index 85d6d227cb..e0782b5b73 100644
--- a/src/jit/indirectcalltransformer.cpp
+++ b/src/jit/indirectcalltransformer.cpp
@@ -676,14 +676,16 @@ private:
JITDUMP("Direct call [%06u] in block BB%02u\n", compiler->dspTreeID(call), thenBlock->bbNum);
- // Then invoke impDevirtualizeCall do actually
+ // Then invoke impDevirtualizeCall to actually
// transform the call for us. It should succeed.... as we have
// now provided an exact typed this.
CORINFO_METHOD_HANDLE methodHnd = inlineInfo->methInfo.ftn;
unsigned methodFlags = inlineInfo->methAttr;
CORINFO_CONTEXT_HANDLE context = inlineInfo->exactContextHnd;
const bool isLateDevirtualization = true;
- compiler->impDevirtualizeCall(call, &methodHnd, &methodFlags, &context, nullptr, isLateDevirtualization);
+ bool explicitTailCall = (call->gtCall.gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0;
+ compiler->impDevirtualizeCall(call, &methodHnd, &methodFlags, &context, nullptr, isLateDevirtualization,
+ explicitTailCall);
// Presumably devirt might fail? If so we should try and avoid
// making this a guarded devirt candidate instead of ending