Fix dotnet/coreclr#6517
authorBruce Forstall <brucefo@microsoft.com>
Fri, 5 Aug 2016 06:52:25 +0000 (23:52 -0700)
committerBruce Forstall <brucefo@microsoft.com>
Fri, 5 Aug 2016 23:30:56 +0000 (16:30 -0700)
My previous change dotnet/coreclr#6342 to implement tailcall-via-helper for RyuJIT/x86
also changed non-x86 for Delegate Invoke calls, to avoid creating a
temp where we already had a local. However, this temp is needed if the
local is a field (with an offset). Even if it is not a field, I saw it
needed in a JitStressRegs case. So I'm returning it to the previous logic
for non-x86, non-tailcall cases. It is still required for tailcall cases
to preserve some delicate ordering constraints on the special tailcall
argument values.

Commit migrated from https://github.com/dotnet/coreclr/commit/021a224809af2104a1c488da1d717d9d80f35cc8

src/coreclr/src/jit/lower.cpp

index e67d260..b5129ca 100644 (file)
@@ -2180,14 +2180,23 @@ GenTree* Lowering::LowerDelegateInvoke(GenTreeCall* call)
     assert(thisArgNode->gtOper == GT_PUTARG_REG);
     GenTree* originalThisExpr = thisArgNode->gtOp.gtOp1;
 
-    // If what we are passing as the thisptr is not already a local, make a new local to place it in
-    // because we will be creating expressions based on it.
+    // We're going to use the 'this' expression multiple times, so make a local to copy it.
+
     unsigned lclNum;
-    if (originalThisExpr->IsLocal())
+
+#ifdef _TARGET_X86_
+    if (call->IsTailCallViaHelper() && originalThisExpr->IsLocal())
     {
+        // For ordering purposes for the special tailcall arguments on x86, we forced the
+        // 'this' pointer in this case to a local in Compiler::fgMorphTailCall().
+        // We could possibly use this case to remove copies for all architectures and non-tailcall
+        // calls by creating a new lcl var or lcl field reference, as is done in the
+        // LowerVirtualVtableCall() code.
+        assert(originalThisExpr->OperGet() == GT_LCL_VAR);
         lclNum = originalThisExpr->AsLclVarCommon()->GetLclNum();
     }
     else
+#endif // _TARGET_X86_
     {
         unsigned delegateInvokeTmp = comp->lvaGrabTemp(true DEBUGARG("delegate invoke call"));
         GenTreeStmt* newStmt = comp->fgInsertEmbeddedFormTemp(&thisArgNode->gtOp.gtOp1, delegateInvokeTmp);