Merge pull request #12735 from erozenfeld/RecursiveTailCallBug
authorEugene Rozenfeld <erozen@microsoft.com>
Tue, 11 Jul 2017 23:10:55 +0000 (16:10 -0700)
committerGitHub <noreply@github.com>
Tue, 11 Jul 2017 23:10:55 +0000 (16:10 -0700)
Fix for a bug in tail recursion elimination.

1  2 
src/jit/morph.cpp

diff --combined src/jit/morph.cpp
@@@ -7586,6 -7586,39 +7586,39 @@@ void Compiler::fgMorphRecursiveFastTail
          fgInsertStmtBefore(block, paramAssignmentInsertionPoint, arg0AssignmentStmt);
      }
  
+     // If compInitMem is set, we may need to zero-initialize some locals. Normally it's done in the prolog
+     // but this loop can't include the prolog. Since we don't have liveness information, we insert zero-initialization
+     // for all non-parameter non-temp locals. Liveness phase will remove unnecessary initializations.
+     if (info.compInitMem)
+     {
+         unsigned   varNum;
+         LclVarDsc* varDsc;
+         for (varNum = 0, varDsc = lvaTable; varNum < info.compLocalsCount; varNum++, varDsc++)
+         {
+             if (!varDsc->lvIsParam)
+             {
+                 assert(!varDsc->lvIsTemp);
+                 var_types  lclType = varDsc->TypeGet();
+                 GenTreePtr lcl     = gtNewLclvNode(varNum, lclType);
+                 GenTreePtr init    = nullptr;
+                 if (lclType == TYP_STRUCT)
+                 {
+                     const bool isVolatile  = false;
+                     const bool isCopyBlock = false;
+                     init = gtNewBlkOpNode(lcl, gtNewIconNode(0), varDsc->lvSize(), isVolatile, isCopyBlock);
+                     init = fgMorphInitBlock(init);
+                 }
+                 else
+                 {
+                     GenTreePtr zero = gtNewZeroConNode(genActualType(lclType));
+                     init            = gtNewAssignNode(lcl, zero);
+                 }
+                 GenTreePtr initStmt = gtNewStmt(init, callILOffset);
+                 fgInsertStmtBefore(block, last, initStmt);
+             }
+         }
+     }
      // Remove the call
      fgRemoveStmt(block, last);
  
@@@ -14148,6 -14181,7 +14181,6 @@@ GenTree* Compiler::fgMorphSmpOpOptional
                          /* The target is used as well as being defined */
                          if (op1->OperIsLocal())
                          {
 -                            op1->gtFlags &= ~GTF_VAR_USEDEF;
                              op1->gtFlags |= GTF_VAR_USEASG;
                          }