[RyuJit][Armel] Do not lose type information (#15449)
authorSergey Andreenko <seandree@microsoft.com>
Fri, 15 Dec 2017 02:17:53 +0000 (18:17 -0800)
committerGitHub <noreply@github.com>
Fri, 15 Dec 2017 02:17:53 +0000 (18:17 -0800)
* Do not lose type information

fgMorphMultiregStructArg could lose type information when replaced smth like this:
 GT_OBJ - TYP_STRUCT     <== arg
  + GT_ADDR - TYP_I_IMPL
   +  + GT_LCL_VAR - TYP_BLK  <== argValue

* Move the test to pri0 to test in ci.

* add an assert

* add the test to the arm list

* make the optimization only if struct handlers match.

* format job

* fix for the unoptimized case.

* check that we have addr node.

* change the reason to lvaSetVarDoNotEnregister

src/jit/morph.cpp
tests/src/JIT/Methodical/tailcall/_il_dbgtest_3b.ilproj
tests/testsRunningInsideARM.txt

index 73883e5..b5d2e8a 100644 (file)
@@ -4963,11 +4963,18 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f
         objClass           = argObj->gtClass;
         structSize         = info.compCompHnd->getClassSize(objClass);
 
-        // If we have a GT_OBJ of a GT_ADDR then we set argValue to the child node of the GT_ADDR
-        //
-        if (argObj->gtOp1->OperGet() == GT_ADDR)
+        // If we have a GT_OBJ of a GT_ADDR then we set argValue to the child node of the GT_ADDR.
+        GenTree* op1 = argObj->gtOp1;
+        if (op1->OperGet() == GT_ADDR)
         {
-            argValue = argObj->gtOp1->gtOp.gtOp1;
+            GenTree* underlyingTree = op1->gtOp.gtOp1;
+
+            // Only update to the same type.
+            if ((underlyingTree->TypeGet() == argValue->TypeGet()) &&
+                (objClass == gtGetStructHandleIfPresent(underlyingTree)))
+            {
+                argValue = underlyingTree;
+            }
         }
     }
     else if (arg->OperGet() == GT_LCL_VAR)
@@ -5342,6 +5349,19 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f
             GenTreePtr  baseAddr = argObj->gtOp1;
             var_types   addrType = baseAddr->TypeGet();
 
+            if (baseAddr->OperGet() == GT_ADDR)
+            {
+                GenTree* addrTaken = baseAddr->gtOp.gtOp1;
+                if (addrTaken->IsLocal())
+                {
+                    GenTreeLclVarCommon* varNode = addrTaken->AsLclVarCommon();
+                    unsigned             varNum  = varNode->gtLclNum;
+                    // We access non-struct type (for example, long) as a struct type.
+                    // Make sure lclVar lives on stack to make sure its fields are accessible by address.
+                    lvaSetVarDoNotEnregister(varNum DEBUGARG(DNER_LocalField));
+                }
+            }
+
             // Create a new tree for 'arg'
             //    replace the existing LDOBJ(EXPR)
             //    with a FIELD_LIST(IND(EXPR), FIELD_LIST(IND(EXPR+8), nullptr) ...)
index 114e9e8..fb6053c 100644 (file)
@@ -10,7 +10,6 @@
     <OutputType>Exe</OutputType>
     <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
-    <CLRTestPriority>1</CLRTestPriority>
   </PropertyGroup>
   <!-- Default configurations to help VS understand the configurations -->
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
index de33d2e..507bfc4 100644 (file)
@@ -1,5 +1,6 @@
 JIT/Directed/coverage/importer/ldelemnullarr2/
 JIT/Methodical/Coverage/b39946/
+JIT/Methodical/tailcall/_il_dbgtest_3b/
 JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b26863/b26863/
 JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b28037/b28037/
 JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b29068/b29068/