Set the lvIsMultiRegArgOrRet for a variable containing the result of
authorLubomir Litchev <lubol@microsoft.com>
Thu, 14 Apr 2016 22:36:25 +0000 (15:36 -0700)
committerLubomir Litchev <lubol@microsoft.com>
Fri, 15 Apr 2016 20:59:38 +0000 (13:59 -0700)
inlined multi-register return call.

This change makes sure the lvIsMultiRegArgOrRet on a variable used to
store the result of inlined multi-register return function is set.
The way the code works today, this is not an issue since the code in
fgAttachStructInlineeToAsg always uses a CopyObj/Blk to asign the return
value from the registers to the var on stack. The CopyBlock/Obj gets the
address of the variable making it address-exposed and that prevents struct
promotion.
In the future (when CopyObj/Blk is not used) not having
lvIsMultiRegArgOrRet set could cause a problem.

Fixes issue 4276.

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

src/coreclr/src/jit/codegenxarch.cpp
src/coreclr/src/jit/flowgraph.cpp

index 8e2482f..d8af377 100644 (file)
@@ -2663,9 +2663,8 @@ CodeGen::genMultiRegCallStoreToLocal(GenTreePtr treeNode)
     // var in 'var = call' is flagged as lvIsMultiRegArgOrRet to prevent it from
     // being struct poromoted.  
     //
-    // TODO-BUG: Crossgen of mscorlib fires the below assert.
-    // A git issue is opened for investigating this.
-    // noway_assert(varDsc->lvIsMultiRegArgOrRet);
+
+    noway_assert(varDsc->lvIsMultiRegArgOrRet);
 
     getEmitter()->emitIns_S_R(ins_Store(type0), emitTypeSize(type0), reg0, lclNum, 0);
     getEmitter()->emitIns_S_R(ins_Store(type1), emitTypeSize(type1), reg1, lclNum, 8);
index ceba942..74821ec 100644 (file)
@@ -21674,6 +21674,13 @@ GenTreePtr Compiler::fgAssignStructInlineeToVar(GenTreePtr child, CORINFO_CLASS_
         // If inlinee was just a call, new inlinee is v05 = call()
         newInlinee = gtNewAssignNode(dst, src);
 
+        // When returning a multi-register value in a local var, make sure the variable is
+        // marked as lvIsMultiRegArgOrRet, so it does not get promoted.
+        if (src->AsCall()->HasMultiRegRetVal())
+        {
+            lvaTable[tmpNum].lvIsMultiRegArgOrRet = true;
+        }
+
         // If inlinee was comma, but a deeper call, new inlinee is (, , , v05 = call())
         if (child->gtOper == GT_COMMA)
         {