JIT: refine types when creating arg temps to improve devirtualization (#13530)
authorAndy Ayers <andya@microsoft.com>
Wed, 23 Aug 2017 16:16:07 +0000 (09:16 -0700)
committerGitHub <noreply@github.com>
Wed, 23 Aug 2017 16:16:07 +0000 (09:16 -0700)
The jit will refine the types of temps used to pass arguments to inlinees
when it creates the assignments to these temps.

Unfortunately this is too late to drive devirtualization in the body of
the inlinee, as thes assignments are created after the inlinee body is
imported.

So, add similar refinement logic to the place where the temps are first
created.

Closes #13520.

src/jit/flowgraph.cpp
src/jit/importer.cpp

index 7790363..d6afead 100644 (file)
@@ -22625,13 +22625,10 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
                     impAssignTempGen(tmpNum, argNode, structHnd, (unsigned)CHECK_SPILL_NONE, &afterStmt, callILOffset,
                                      block);
 
-                    // If we know the argument's value can't be
-                    // changed within the method body, try and improve
-                    // the type of the temp.
-                    if (argIsSingleDef && (argType == TYP_REF))
-                    {
-                        lvaUpdateClass(tmpNum, argNode);
-                    }
+                    // We used to refine the temp type here based on
+                    // the actual arg, but we now do this up front, when
+                    // creating the temp, over in impInlineFetchArg.
+                    CLANG_FORMAT_COMMENT_ANCHOR;
 
 #ifdef DEBUG
                     if (verbose)
index 46ca8ff..b824e6b 100644 (file)
@@ -18165,11 +18165,22 @@ GenTreePtr Compiler::impInlineFetchArg(unsigned lclNum, InlArgInfo* inlArgInfo,
 
             lvaTable[tmpNum].lvType = lclTyp;
 
-            // Copy over class handle for ref types. Note this may be
-            // further improved if it is a shared type and we know the exact context.
+            // For ref types, determine the type of the temp.
             if (lclTyp == TYP_REF)
             {
-                lvaSetClass(tmpNum, lclInfo.lclVerTypeInfo.GetClassHandleForObjRef());
+                if (!argCanBeModified)
+                {
+                    // If the arg can't be modified in the method
+                    // body, use the type of the value, if
+                    // known. Otherwise, use the declared type.
+                    lvaSetClass(tmpNum, argInfo.argNode, lclInfo.lclVerTypeInfo.GetClassHandleForObjRef());
+                }
+                else
+                {
+                    // Arg might be modified, use the delcared type of
+                    // the argument.
+                    lvaSetClass(tmpNum, lclInfo.lclVerTypeInfo.GetClassHandleForObjRef());
+                }
             }
 
             assert(lvaTable[tmpNum].lvAddrExposed == 0);