Merge pull request #6558 from bryanar/dumpling_ci2
[platform/upstream/coreclr.git] / src / jit / optimizer.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                              Optimizer                                    XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13
14 #include "jitpch.h"
15 #ifdef _MSC_VER
16 #pragma hdrstop
17 #pragma warning ( disable : 4701 )
18 #endif
19
20 /*****************************************************************************/
21
22 #if COUNT_RANGECHECKS
23 /* static */
24 unsigned                Compiler::optRangeChkRmv = 0;
25 /* static */
26 unsigned                Compiler::optRangeChkAll = 0;
27 #endif
28
29 /*****************************************************************************/
30
31 void                Compiler::optInit()
32 {
33     optLoopsMarked      = false;
34     fgHasLoops          = false;
35     
36     /* Initialize the # of tracked loops to 0 */
37     optLoopCount        = 0;
38     /* Keep track of the number of calls and indirect calls made by this method */
39     optCallCount         = 0;
40     optIndirectCallCount = 0;
41     optNativeCallCount   = 0;
42     optAssertionCount    = 0;
43     optAssertionDep      = NULL;
44 #if FEATURE_ANYCSE
45     optCSECandidateTotal = 0;
46     optCSEstart          = UINT_MAX;
47     optCSEcount          = 0;
48 #endif // FEATURE_ANYCSE
49
50 }
51
52 DataFlow::DataFlow(Compiler* pCompiler)
53     : m_pCompiler(pCompiler)
54 {
55 }
56
57 /*****************************************************************************
58  *
59  */
60
61 void                Compiler::optSetBlockWeights()
62 {
63     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
64     assert(fgDomsComputed);
65
66 #ifdef DEBUG
67     bool changed = false;
68 #endif
69
70     bool firstBBdomsRets = true;
71
72     BasicBlock  *   block;
73
74     for (block = fgFirstBB; (block != NULL); block = block->bbNext)
75     {
76         /* Blocks that can't be reached via the first block are rarely executed */
77         if (!fgReachable(fgFirstBB, block))
78             block->bbSetRunRarely();
79
80         if (block->bbWeight != BB_ZERO_WEIGHT)
81         {
82             // Calculate our bbWeight:
83             //
84             //  o BB_UNITY_WEIGHT if we dominate all BBJ_RETURN blocks
85             //  o otherwise BB_UNITY_WEIGHT / 2
86             //
87             bool domsRets = true;     // Assume that we will dominate
88             
89             for (BasicBlockList* retBlocks = fgReturnBlocks; retBlocks != nullptr; retBlocks = retBlocks->next)
90             {
91                 if (!fgDominate(block, retBlocks->block))
92                 {
93                     domsRets = false;
94                     break;
95                 }
96             }
97
98             if (block == fgFirstBB)
99             {
100                 firstBBdomsRets = domsRets;
101             }
102             
103             // If we are not using profile weight then we lower the weight 
104             // of blocks that do not dominate a return block
105             //
106             if (firstBBdomsRets && (fgIsUsingProfileWeights() == false) && (domsRets == false))
107             {
108 #if DEBUG
109                 changed = true;
110 #endif
111                 block->modifyBBWeight(block->bbWeight / 2);
112                 noway_assert(block->bbWeight);
113             }
114         }
115     }
116
117 #if DEBUG
118     if  (changed && verbose)
119     {
120         printf("\nAfter optSetBlockWeights:\n");
121         fgDispBasicBlocks();
122         printf("\n");
123     }
124
125     /* Check that the flowgraph data (bbNum, bbRefs, bbPreds) is up-to-date */
126     fgDebugCheckBBlist();
127 #endif
128 }
129
130 /*****************************************************************************
131  *
132  *  Marks the blocks between 'begBlk' and 'endBlk' as part of a loop.
133  */
134
135 void        Compiler::optMarkLoopBlocks(BasicBlock *begBlk,
136                                         BasicBlock *endBlk,
137                                         bool       excludeEndBlk)
138 {
139     /* Calculate the 'loopWeight',
140        this is the amount to increase each block in the loop
141        Our heuristic is that loops are weighted eight times more
142        than straight line code.
143        Thus we increase each block by 7 times the weight of
144        the loop header block,
145        if the loops are all properly formed gives us:
146        (assuming that BB_LOOP_WEIGHT is 8)
147
148           1 -- non loop basic block
149           8 -- single loop nesting
150          64 -- double loop nesting
151         512 -- triple loop nesting
152
153     */
154
155     noway_assert(begBlk->bbNum <= endBlk->bbNum);
156     noway_assert(begBlk->isLoopHead());
157     noway_assert(fgReachable(begBlk, endBlk));
158
159 #ifdef  DEBUG
160     if (verbose) {        
161         printf("\nMarking loop L%02u", begBlk->bbLoopNum);
162     }
163 #endif
164
165     noway_assert(!opts.MinOpts());
166
167     /* Build list of backedges for block begBlk */
168     flowList *  backedgeList = NULL;
169
170     for (flowList* pred  = begBlk->bbPreds; 
171                    pred != NULL; 
172                    pred  = pred->flNext)
173     {
174         /* Is this a backedge? */
175         if (pred->flBlock->bbNum >= begBlk->bbNum)
176         {
177             flowList* flow = new (this, CMK_FlowList) flowList();
178
179 #if MEASURE_BLOCK_SIZE
180             genFlowNodeCnt  += 1;
181             genFlowNodeSize += sizeof(flowList);
182 #endif // MEASURE_BLOCK_SIZE
183
184             flow->flNext  = backedgeList;
185             flow->flBlock = pred->flBlock;
186             backedgeList   = flow;
187         }
188     }
189
190     /* At least one backedge must have been found (the one from endBlk) */
191     noway_assert(backedgeList);
192     
193     BasicBlock * curBlk = begBlk;
194
195     while (true)
196     {
197         noway_assert(curBlk);
198
199         // For curBlk to be part of a loop that starts at begBlk
200         // curBlk must be reachable from begBlk and (since this is a loop)
201         // likewise begBlk must be reachable from curBlk.
202         // 
203
204         if (fgReachable(curBlk, begBlk) && fgReachable(begBlk, curBlk))
205         {
206             /* If this block reaches any of the backedge blocks we set reachable   */
207             /* If this block dominates any of the backedge blocks we set dominates */
208             bool          reachable = false;
209             bool          dominates = false;
210
211             for (flowList* tmp  = backedgeList; 
212                            tmp != NULL; 
213                            tmp  = tmp->flNext)
214             {
215                 BasicBlock *  backedge = tmp->flBlock;
216
217                 if (!curBlk->isRunRarely())
218                 {
219                     reachable |= fgReachable(curBlk, backedge);
220                     dominates |= fgDominate (curBlk, backedge);
221
222                     if (dominates && reachable)
223                         break;
224                 }
225             }
226
227             if (reachable)
228             {
229                 noway_assert(curBlk->bbWeight > BB_ZERO_WEIGHT);
230
231                 unsigned weight;
232
233                 if ((curBlk->bbFlags & BBF_PROF_WEIGHT) != 0)
234                 {
235                     // We have real profile weights, so we aren't going to change this blocks weight
236                     weight = curBlk->bbWeight;
237                 }
238                 else
239                 {
240                     if (dominates) {
241                         weight = curBlk->bbWeight * BB_LOOP_WEIGHT;
242                     }
243                     else {
244                         weight = curBlk->bbWeight * (BB_LOOP_WEIGHT/2);
245                     }
246
247                     //
248                     // The multiplication may have caused us to overflow
249                     //
250                     if (weight < curBlk->bbWeight)
251                     {
252                         // The multiplication caused us to overflow 
253                         weight = BB_MAX_WEIGHT;
254                     }
255                     //
256                     //  Set the new weight
257                     //  
258                     curBlk->modifyBBWeight(weight);
259                 }
260 #ifdef  DEBUG
261                 if (verbose)
262                 {
263                     printf("\n    BB%02u(wt=%s)", 
264                             curBlk->bbNum,
265                             refCntWtd2str(curBlk->getBBWeight(this)));
266                 }
267 #endif
268             }
269         }
270
271         /* Stop if we've reached the last block in the loop */
272         
273         if  (curBlk == endBlk)
274             break;
275         
276         curBlk = curBlk->bbNext;
277
278         /* If we are excluding the endBlk then stop if we've reached endBlk */
279         
280         if  (excludeEndBlk && (curBlk == endBlk))
281             break;
282     }
283 }
284
285 /*****************************************************************************
286  *
287  *   Unmark the blocks between 'begBlk' and 'endBlk' as part of a loop.
288  */
289
290 void        Compiler::optUnmarkLoopBlocks(BasicBlock *begBlk,
291                                           BasicBlock *endBlk)
292 {
293     /* A set of blocks that were previously marked as a loop are now
294        to be unmarked, since we have decided that for some reason this
295        loop no longer exists.
296        Basically we are just reseting the blocks bbWeight to their
297        previous values.
298     */
299     
300     noway_assert(begBlk->bbNum <= endBlk->bbNum);
301     noway_assert(begBlk->isLoopHead());
302
303     noway_assert(!opts.MinOpts());
304
305     BasicBlock *  curBlk;
306     unsigned      backEdgeCount = 0;
307
308     for (flowList * pred  = begBlk->bbPreds; 
309                     pred != NULL;
310                     pred  = pred->flNext)
311     {
312         curBlk = pred->flBlock;
313
314         /* is this a backward edge? (from curBlk to begBlk) */
315
316         if (begBlk->bbNum > curBlk->bbNum)
317             continue;
318
319         /* We only consider back-edges that are BBJ_COND or BBJ_ALWAYS for loops */
320
321         if ((curBlk->bbJumpKind != BBJ_COND)   &&
322             (curBlk->bbJumpKind != BBJ_ALWAYS)    )
323           continue;
324
325         backEdgeCount++;
326     }
327
328     /* Only unmark the loop blocks if we have exactly one loop back edge */
329     if (backEdgeCount != 1)
330     {
331 #ifdef  DEBUG
332         if (verbose)
333         {
334             if (backEdgeCount > 0)
335             {
336                 printf("\nNot removing loop L%02u, due to an additional back edge",
337                        begBlk->bbLoopNum);
338             }
339             else if (backEdgeCount == 0)
340             {
341                 printf("\nNot removing loop L%02u, due to no back edge",
342                        begBlk->bbLoopNum);
343             }
344         }
345 #endif
346         return;
347     }
348     noway_assert(backEdgeCount == 1);
349     noway_assert(fgReachable(begBlk, endBlk));
350
351 #ifdef  DEBUG
352     if (verbose) 
353         printf("\nUnmarking loop L%02u", begBlk->bbLoopNum);
354 #endif
355
356     curBlk = begBlk;
357     while (true)
358     {        
359         noway_assert(curBlk);
360
361         // For curBlk to be part of a loop that starts at begBlk
362         // curBlk must be reachable from begBlk and (since this is a loop)
363         // likewise begBlk must be reachable from curBlk.
364         // 
365         if (!curBlk->isRunRarely() && fgReachable(curBlk, begBlk) && fgReachable(begBlk, curBlk))
366         {
367             unsigned weight = curBlk->bbWeight;
368
369             // Don't unmark blocks that are set to BB_MAX_WEIGHT
370             // Don't unmark blocks when we are using profile weights
371             //
372             if (!curBlk->isMaxBBWeight() && ((curBlk->bbFlags & BBF_PROF_WEIGHT) == 0))
373             {
374                 if (!fgDominate(curBlk, endBlk))
375                 {
376                     weight *= 2;
377                 }
378                 else
379                 {
380                     /* Merging of blocks can disturb the Dominates
381                        information (see RAID #46649) */
382                     if (weight < BB_LOOP_WEIGHT)
383                         weight *= 2;
384                 }
385
386                 // We can overflow here so check for it
387                 if (weight < curBlk->bbWeight)
388                     weight = BB_MAX_WEIGHT;
389
390                 assert (weight >= BB_LOOP_WEIGHT);
391                 
392                 curBlk->modifyBBWeight(weight / BB_LOOP_WEIGHT);
393             }
394
395 #ifdef  DEBUG
396             if (verbose)
397             {
398                 printf("\n    BB%02u(wt=%s)", 
399                         curBlk->bbNum,
400                         refCntWtd2str(curBlk->getBBWeight(this)));
401             }
402 #endif
403         }
404         /* Stop if we've reached the last block in the loop */
405         
406         if  (curBlk == endBlk)
407             break;
408
409         curBlk = curBlk->bbNext;
410
411         /* Stop if we go past the last block in the loop, as it may have been deleted */
412         if (curBlk->bbNum > endBlk->bbNum)
413             break;
414     }
415 }
416
417 /*****************************************************************************************************
418  *
419  *  Function called to update the loop table and bbWeight before removing a block
420  */
421
422 void                Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock * block, 
423                                                               bool         skipUnmarkLoop)
424 {
425     if (!optLoopsMarked)
426         return;
427
428     noway_assert(!opts.MinOpts());
429
430     bool removeLoop = false;
431
432     /* If an unreachable block was part of a loop entry or bottom then the loop is unreachable */
433     /* Special case: the block was the head of a loop - or pointing to a loop entry */
434
435     for (unsigned loopNum = 0; loopNum < optLoopCount; loopNum++)
436     {
437         /* Some loops may have been already removed by
438          * loop unrolling or conditional folding */
439
440         if (optLoopTable[loopNum].lpFlags & LPFLG_REMOVED)
441             continue;
442
443         if (block == optLoopTable[loopNum].lpEntry ||
444             block == optLoopTable[loopNum].lpBottom  )
445         {
446             optLoopTable[loopNum].lpFlags |= LPFLG_REMOVED;
447             continue;
448         }
449
450 #ifdef  DEBUG
451         if (verbose)
452         {
453             printf("\nUpdateLoopsBeforeRemoveBlock Before: ");
454             optPrintLoopInfo(loopNum);
455         }
456 #endif
457
458         /* If the loop is still in the table
459          * any block in the loop must be reachable !!! */
460
461         noway_assert(optLoopTable[loopNum].lpEntry != block);
462         noway_assert(optLoopTable[loopNum].lpBottom != block);
463
464         if (optLoopTable[loopNum].lpExit == block)
465         {
466             optLoopTable[loopNum].lpExit   = NULL;
467             optLoopTable[loopNum].lpFlags &= ~LPFLG_ONE_EXIT;;
468         }
469
470
471         /* If this points to the actual entry in the loop
472          * then the whole loop may become unreachable */
473
474         switch (block->bbJumpKind)
475         {
476             unsigned        jumpCnt;
477             BasicBlock * *  jumpTab;
478
479         case BBJ_NONE:
480         case BBJ_COND:
481             if (block->bbNext == optLoopTable[loopNum].lpEntry)
482             {
483                 removeLoop = true;
484                 break;
485             }
486             if (block->bbJumpKind == BBJ_NONE)
487                 break;
488
489             __fallthrough;
490
491         case BBJ_ALWAYS:
492             noway_assert(block->bbJumpDest);
493             if (block->bbJumpDest == optLoopTable[loopNum].lpEntry)
494             {
495                 removeLoop = true;
496             }
497             break;
498
499         case BBJ_SWITCH:
500             jumpCnt = block->bbJumpSwt->bbsCount;
501             jumpTab = block->bbJumpSwt->bbsDstTab;
502
503             do {
504                 noway_assert(*jumpTab);
505                 if ((*jumpTab) == optLoopTable[loopNum].lpEntry)
506                 {
507                     removeLoop = true;
508                 }
509             } while (++jumpTab, --jumpCnt);
510             break;
511
512         default:
513             break;
514         }
515
516         if  (removeLoop)
517         {
518             /* Check if the entry has other predecessors outside the loop
519              * TODO: Replace this when predecessors are available */
520
521             BasicBlock      *       auxBlock;
522             for (auxBlock = fgFirstBB; auxBlock; auxBlock = auxBlock->bbNext)
523             {
524                 /* Ignore blocks in the loop */
525
526                 if  (auxBlock->bbNum >  optLoopTable[loopNum].lpHead->bbNum &&
527                      auxBlock->bbNum <= optLoopTable[loopNum].lpBottom->bbNum)
528                     continue;
529
530                 switch (auxBlock->bbJumpKind)
531                 {
532                     unsigned        jumpCnt;
533                     BasicBlock * *  jumpTab;
534
535                 case BBJ_NONE:
536                 case BBJ_COND:
537                     if (auxBlock->bbNext == optLoopTable[loopNum].lpEntry)
538                     {
539                         removeLoop = false;
540                         break;
541                     }
542                     if (auxBlock->bbJumpKind == BBJ_NONE)
543                         break;
544
545                     __fallthrough;
546
547                 case BBJ_ALWAYS:
548                     noway_assert(auxBlock->bbJumpDest);
549                     if (auxBlock->bbJumpDest == optLoopTable[loopNum].lpEntry)
550                     {
551                         removeLoop = false;
552                     }
553                     break;
554
555                 case BBJ_SWITCH:
556                     jumpCnt = auxBlock->bbJumpSwt->bbsCount;
557                     jumpTab = auxBlock->bbJumpSwt->bbsDstTab;
558
559                     do
560                     {
561                         noway_assert(*jumpTab);
562                         if ((*jumpTab) == optLoopTable[loopNum].lpEntry)
563                         {
564                             removeLoop = false;
565                         }
566                     } while (++jumpTab, --jumpCnt);
567                     break;
568
569                 default:
570                     break;
571                 }
572             }
573
574             if (removeLoop)
575             {
576                 optLoopTable[loopNum].lpFlags |= LPFLG_REMOVED;
577             }
578         }
579         else if (optLoopTable[loopNum].lpHead == block)
580         {
581             /* The loop has a new head - Just update the loop table */
582             optLoopTable[loopNum].lpHead = block->bbPrev;
583         }
584
585 #ifdef  DEBUG
586         if (verbose) {
587             printf("\nUpdateLoopsBeforeRemoveBlock After: ");
588             optPrintLoopInfo(loopNum);
589         }
590 #endif
591     }
592
593     if ((skipUnmarkLoop == false)                                              &&
594         ((block->bbJumpKind == BBJ_ALWAYS) || (block->bbJumpKind == BBJ_COND)) &&
595         (block->bbJumpDest->isLoopHead())                                      &&
596         (block->bbJumpDest->bbNum <= block->bbNum)                             &&
597         fgDomsComputed                                                         &&
598         (fgCurBBEpochSize == fgDomBBcount + 1)                                 &&
599         fgReachable(block->bbJumpDest, block))
600     {
601         optUnmarkLoopBlocks(block->bbJumpDest, block);
602     }
603 }
604
605 #ifdef  DEBUG
606
607 /*****************************************************************************
608  *
609  *  Given the beginBlock of the loop, return the index of this loop
610  *  to the loop table.
611  */
612
613 unsigned Compiler::optFindLoopNumberFromBeginBlock(BasicBlock* begBlk)
614 {
615     unsigned lnum = 0;
616     
617     for (lnum = 0; lnum < optLoopCount; lnum++)
618     {
619         if (optLoopTable[lnum].lpHead->bbNext == begBlk)
620         {
621             // Found the loop.
622             return lnum;
623         }
624     }
625
626     noway_assert(!"Loop number not found.");
627
628     return optLoopCount; 
629 }
630
631 /*****************************************************************************
632  *
633  *  Print loop info in an uniform way.
634  */
635
636 void Compiler::optPrintLoopInfo(unsigned        loopInd,
637                                 BasicBlock *    lpHead,     
638                                 BasicBlock *    lpFirst,
639                                 BasicBlock *    lpTop,
640                                 BasicBlock *    lpEntry,      
641                                 BasicBlock *    lpBottom,
642                                 unsigned char   lpExitCnt,
643                                 BasicBlock *    lpExit,
644                                 unsigned        parentLoop
645                                 )
646 {
647     noway_assert(lpHead);
648         
649     //
650     // NOTE: we take "loopInd" as an argument instead of using the one
651     //       stored in begBlk->bbLoopNum because sometimes begBlk->bbLoopNum
652     //       has not be set correctly. For example, in optRecordLoop().
653     //       However, in most of the cases, loops should have been recorded.
654     //       Therefore the correct way is to call the Compiler::optPrintLoopInfo(unsigned lnum)
655     //       version of this method.
656     //
657     printf("L%02u, from BB%02u", loopInd, lpFirst->bbNum);
658     if (lpTop != lpFirst)
659     {
660         printf(" (loop top is BB%02u)", lpTop->bbNum);
661     }
662
663     printf(" to BB%02u (Head=BB%02u, Entry=BB%02u, ExitCnt=%d",
664            lpBottom->bbNum,
665            lpHead->bbNum,
666            lpEntry->bbNum,
667            lpExitCnt
668            );
669
670     if (lpExitCnt == 1) {
671         printf(" at BB%02u", lpExit->bbNum);
672     }
673
674     if (parentLoop != BasicBlock::NOT_IN_LOOP)
675     {
676         printf(", parent loop = L%02u", parentLoop);
677     }
678     printf(")");
679 }
680
681 /*****************************************************************************
682  *
683  *  Print loop information given the index of the loop in the loop table.
684  */
685
686 void Compiler::optPrintLoopInfo(unsigned lnum)
687 {
688     noway_assert(lnum < optLoopCount);
689
690     LoopDsc* ldsc = &optLoopTable[lnum];    // lnum is the INDEX to the loop table.
691     
692     optPrintLoopInfo(lnum, 
693                      ldsc->lpHead,
694                      ldsc->lpFirst,
695                      ldsc->lpTop,
696                      ldsc->lpEntry,
697                      ldsc->lpBottom,
698                      ldsc->lpExitCnt,
699                      ldsc->lpExit,
700                      ldsc->lpParent
701                      );
702 }
703
704
705 #endif
706
707 //------------------------------------------------------------------------
708 // optPopulateInitInfo: Populate loop init info in the loop table.
709 //
710 // Arguments:
711 //     init     -  the tree that is supposed to initialize the loop iterator.
712 //     iterVar  -  loop iteration variable.
713 //
714 // Return Value:
715 //     "false" if the loop table could not be populated with the loop iterVar init info.
716 //
717 // Operation:
718 //     The 'init' tree is checked if its lhs is a local and rhs is either
719 //     a const or a local.
720 //
721 bool Compiler::optPopulateInitInfo(unsigned loopInd, GenTreePtr init, unsigned iterVar)
722 {
723     // Operator should be =
724     if (init->gtOper != GT_ASG)
725     {
726         return false;
727     }
728
729     GenTreePtr lhs = init->gtOp.gtOp1;
730     GenTreePtr rhs = init->gtOp.gtOp2;
731     // LHS has to be local and should equal iterVar.
732     if (lhs->gtOper != GT_LCL_VAR || lhs->gtLclVarCommon.gtLclNum != iterVar)
733     {
734         return false;
735     }
736
737     // RHS can be constant or local var.
738     // TODO-CQ: CLONE: Add arr length for descending loops.
739     if (rhs->gtOper == GT_CNS_INT && rhs->TypeGet() == TYP_INT)
740     {
741         optLoopTable[loopInd].lpFlags |= LPFLG_CONST_INIT;
742         optLoopTable[loopInd].lpConstInit = (int)rhs->gtIntCon.gtIconVal;
743     }
744     else if (rhs->gtOper == GT_LCL_VAR)
745     {
746         optLoopTable[loopInd].lpFlags |= LPFLG_VAR_INIT;
747         optLoopTable[loopInd].lpVarInit = rhs->gtLclVarCommon.gtLclNum;
748     }
749     else
750     {
751         return false;
752     }
753     return true;
754 }
755
756 //----------------------------------------------------------------------------------
757 // optCheckIterInLoopTest: Check if iter var is used in loop test.
758 //
759 // Arguments:
760 //      test          "jtrue" tree or an asg of the loop iter termination condition
761 //      from/to       blocks (beg, end) which are part of the loop.
762 //      iterVar       loop iteration variable.
763 //      loopInd       loop index.
764 //
765 //  Operation:
766 //      The test tree is parsed to check if "iterVar" matches the lhs of the condition
767 //      and the rhs limit is extracted from the "test" tree. The limit information is
768 //      added to the loop table.
769 //
770 //  Return Value:
771 //      "false" if the loop table could not be populated with the loop test info or
772 //      if the test condition doesn't involve iterVar.
773 //
774 bool Compiler::optCheckIterInLoopTest(unsigned loopInd, GenTreePtr test, BasicBlock* from, BasicBlock* to, unsigned iterVar)
775 {
776     // Obtain the relop from the "test" tree.
777     GenTreePtr relop;
778     if (test->gtOper == GT_JTRUE)
779     {
780         relop = test->gtGetOp1();
781     }
782     else 
783     {
784         assert(test->gtOper == GT_ASG);
785         relop = test->gtGetOp2();
786     }
787
788     noway_assert(relop->OperKind() & GTK_RELOP);          
789
790     GenTreePtr opr1 = relop->gtOp.gtOp1;
791     GenTreePtr opr2 = relop->gtOp.gtOp2;
792
793     GenTreePtr iterOp;
794     GenTreePtr limitOp;
795
796     // Make sure op1 or op2 is the iterVar.
797     if (opr1->gtOper == GT_LCL_VAR && opr1->gtLclVarCommon.gtLclNum == iterVar)
798     {
799         iterOp = opr1;
800         limitOp = opr2;
801     }
802     else if (opr2->gtOper == GT_LCL_VAR && opr2->gtLclVarCommon.gtLclNum == iterVar)
803     {
804         iterOp = opr2;
805         limitOp = opr1;
806     }
807     else
808     {
809         return false;
810     }
811
812     if (iterOp->gtType != TYP_INT)
813     {
814         return false;
815     }
816
817     // Mark the iterator node.
818     iterOp->gtFlags |= GTF_VAR_ITERATOR;
819
820     // Check what type of limit we have - constant, variable or arr-len.
821     if (limitOp->gtOper == GT_CNS_INT)
822     {
823         optLoopTable[loopInd].lpFlags |= LPFLG_CONST_LIMIT;
824     }
825     else if (limitOp->gtOper == GT_LCL_VAR && !optIsVarAssigned(from, to, nullptr, limitOp->gtLclVarCommon.gtLclNum))
826     {
827         optLoopTable[loopInd].lpFlags |= LPFLG_VAR_LIMIT;
828     }
829     else if (limitOp->gtOper == GT_ARR_LENGTH)
830     {
831         optLoopTable[loopInd].lpFlags |= LPFLG_ARRLEN_LIMIT;
832     }
833     else
834     {
835         return false;
836     }
837     // Save the type of the comparison between the iterator and the limit.
838     optLoopTable[loopInd].lpTestTree = relop;
839     return true;
840 }
841
842 //----------------------------------------------------------------------------------
843 // optIsLoopIncrTree: Check if loop is a tree of form v += 1 or v = v + 1
844 //
845 // Arguments:
846 //      incr        The incr tree to be checked. Whether incr tree is
847 //                  oper-equal(+=, -=...) type nodes or v=v+1 type ASG nodes.
848 //
849 //  Operation:
850 //      The test tree is parsed to check if "iterVar" matches the lhs of the condition
851 //      and the rhs limit is extracted from the "test" tree. The limit information is
852 //      added to the loop table.
853 //
854 //  Return Value:
855 //      iterVar local num if the iterVar is found, otherwise BAD_VAR_NUM.
856 //
857 unsigned Compiler::optIsLoopIncrTree(GenTreePtr incr)
858 {
859     GenTree* incrVal;
860     genTreeOps updateOper;
861     unsigned iterVar = incr->IsLclVarUpdateTree(&incrVal, &updateOper);
862     if (iterVar != BAD_VAR_NUM)
863     {
864         // We have v = v op y type asg node.
865         switch (updateOper)
866         {
867         case GT_ADD:
868         case GT_SUB:
869         case GT_MUL:
870         case GT_RSH:
871         case GT_LSH:
872             break;
873         default:
874             return BAD_VAR_NUM;
875         }
876
877         // Increment should be by a const int.
878         // TODO-CQ: CLONE: allow variable increments.
879         if ((incrVal->gtOper != GT_CNS_INT) || (incrVal->TypeGet() != TYP_INT))
880         {
881             return BAD_VAR_NUM;
882         }
883     }
884
885     return iterVar;
886 }
887
888 //----------------------------------------------------------------------------------
889 // optComputeIterInfo: Check tree is loop increment of a lcl that is loop-invariant.
890 //
891 // Arguments:
892 //      from, to    - are blocks (beg, end) which are part of the loop.
893 //      incr        - tree that increments the loop iterator. v+=1 or v=v+1.
894 //      pIterVar    - see return value.
895 //
896 //  Return Value:
897 //      Returns true if iterVar "v" can be returned in "pIterVar", otherwise returns
898 //      false.
899 //
900 //  Operation:
901 //      Check if the "incr" tree is a "v=v+1 or v+=1" type tree and make sure it is not
902 //      assigned in the loop.
903 //
904 bool Compiler::optComputeIterInfo(GenTreePtr incr, BasicBlock* from, BasicBlock* to, unsigned* pIterVar)
905 {
906
907     unsigned iterVar = optIsLoopIncrTree(incr);
908     if (iterVar == BAD_VAR_NUM)
909     {
910         return false;
911     }
912     if (optIsVarAssigned(from, to, incr, iterVar))
913     {
914         JITDUMP("iterVar is assigned in loop\n");
915         return false;
916     }
917
918     *pIterVar = iterVar;
919     return true;
920 }
921
922 //----------------------------------------------------------------------------------
923 // optIsLoopTestEvalIntoTemp:
924 //      Pattern match if the test tree is computed into a tmp
925 //      and the "tmp" is used as jump condition for loop termination.
926 //
927 // Arguments:
928 //      testStmt    - is the JTRUE statement that is of the form: jmpTrue (Vtmp != 0)
929 //                    where Vtmp contains the actual loop test result.
930 //      newStmt     - contains the statement that is the actual test stmt involving
931 //                    the loop iterator.
932 //
933 //  Return Value:
934 //      Returns true if a new test tree can be obtained.
935 //
936 //  Operation:
937 //      Scan if the current stmt is a jtrue with (Vtmp != 0) as condition
938 //      Then returns the rhs for def of Vtmp as the "test" node.
939 //
940 //  Note:
941 //      This method just retrieves what it thinks is the "test" node,
942 //      the callers are expected to verify that "iterVar" is used in the test.
943 //
944 bool Compiler::optIsLoopTestEvalIntoTemp(GenTreePtr testStmt, GenTreePtr* newTest)
945 {
946     GenTreePtr test = testStmt->gtStmt.gtStmtExpr;
947
948     if (test->gtOper != GT_JTRUE)
949     {
950         return false;
951     }
952
953     GenTreePtr relop = test->gtGetOp1();
954     noway_assert(relop->OperIsCompare());
955
956     GenTreePtr opr1 = relop->gtOp.gtOp1;
957     GenTreePtr opr2 = relop->gtOp.gtOp2;
958
959     // Make sure we have jtrue (vtmp != 0)
960     if ((relop->OperGet() == GT_NE) && 
961         (opr1->OperGet() == GT_LCL_VAR) &&
962         (opr2->OperGet() == GT_CNS_INT) && 
963         opr2->IsIntegralConst(0))
964     {
965         // Get the previous statement to get the def (rhs) of Vtmp to see
966         // if the "test" is evaluated into Vtmp.
967         GenTreePtr prevStmt = testStmt->gtPrev;
968         if (prevStmt == nullptr)
969         {
970             return false;
971         }
972
973         GenTreePtr tree = prevStmt->gtStmt.gtStmtExpr;
974         if (tree->OperGet() == GT_ASG)
975         {
976             GenTreePtr lhs = tree->gtOp.gtOp1;
977             GenTreePtr rhs = tree->gtOp.gtOp2;
978
979             // Return as the new test node.
980             if (lhs->gtOper == GT_LCL_VAR && lhs->AsLclVarCommon()->GetLclNum() == opr1->AsLclVarCommon()->GetLclNum())
981             {
982                 if (rhs->OperIsCompare())
983                 {
984                     *newTest = prevStmt;
985                      return true;
986                 }
987             }
988         }
989     }
990     return false;
991 }
992
993 //----------------------------------------------------------------------------------
994 // optExtractInitTestIncr:
995 //      Extract the "init", "test" and "incr" nodes of the loop.
996 //
997 // Arguments:
998 //      head    - Loop head block
999 //      bottom  - Loop bottom block
1000 //      top     - Loop top block
1001 //      ppInit  - The init stmt of the loop if found.
1002 //      ppTest  - The test stmt of the loop if found.
1003 //      ppIncr  - The incr stmt of the loop if found.
1004 //
1005 //  Return Value:
1006 //      The results are put in "ppInit", "ppTest" and "ppIncr" if the method
1007 //      returns true. Returns false if the information can't be extracted.
1008 //
1009 //  Operation:
1010 //      Check if the "test" stmt is last stmt in the loop "bottom". If found good,
1011 //      "test" stmt is found. Try to find the "incr" stmt. Check previous stmt of
1012 //      "test" to get the "incr" stmt. If it is not found it could be a loop of the
1013 //      below form.
1014 //
1015 //                     +-------<-----------------<-----------+
1016 //                     |                                     |
1017 //                     v                                     |
1018 //      BBinit(head) -> BBcond(top) -> BBLoopBody(bottom) ---^
1019 //
1020 //      Check if the "incr" tree is present in the loop "top" node as the last stmt.
1021 //      Also check if the "test" tree is assigned to a tmp node and the tmp is used
1022 //      in the jtrue condition.
1023 //
1024 //  Note:
1025 //      This method just retrieves what it thinks is the "test" node,
1026 //      the callers are expected to verify that "iterVar" is used in the test.
1027 //
1028 bool Compiler::optExtractInitTestIncr(BasicBlock* head, BasicBlock* bottom, BasicBlock* top, GenTreePtr* ppInit, GenTreePtr* ppTest, GenTreePtr* ppIncr)
1029 {
1030     assert(ppInit != nullptr);
1031     assert(ppTest != nullptr);
1032     assert(ppIncr != nullptr);
1033
1034     // Check if last two statements in the loop body are the increment of the iterator
1035     // and the loop termination test.
1036     noway_assert(bottom->bbTreeList != nullptr);
1037     GenTreePtr test = bottom->bbTreeList->gtPrev;
1038     noway_assert(test != nullptr && test->gtNext == nullptr);
1039
1040     GenTreePtr newTest;
1041     if (optIsLoopTestEvalIntoTemp(test, &newTest))
1042     {
1043         test = newTest;
1044     }
1045
1046     // Check if we have the incr tree before the test tree, if we don't,
1047     // check if incr is part of the loop "top".
1048     GenTreePtr incr = test->gtPrev;
1049     if (incr == nullptr || optIsLoopIncrTree(incr->gtStmt.gtStmtExpr) == BAD_VAR_NUM)
1050     {
1051         if (top == nullptr || top->bbTreeList == nullptr || top->bbTreeList->gtPrev == nullptr)
1052         {
1053             return false;
1054         }
1055
1056         // If the prev stmt to loop test is not incr, then check if we have loop test evaluated into a tmp.
1057         GenTreePtr topLast = top->bbTreeList->gtPrev;
1058         if (optIsLoopIncrTree(topLast->gtStmt.gtStmtExpr) != BAD_VAR_NUM)
1059         {
1060             incr = topLast;
1061         }
1062         else
1063         {
1064             return false;
1065         }
1066     }
1067
1068     assert(test != incr);
1069
1070     // Find the last statement in the loop pre-header which we expect to be the initialization of
1071     // the loop iterator.
1072     GenTreePtr phdr = head->bbTreeList;
1073     if (phdr == nullptr)
1074     {
1075         return false;
1076     }
1077
1078     GenTreePtr init = phdr->gtPrev;
1079     noway_assert(init != nullptr && (init->gtNext == 0));
1080
1081     // If it is a duplicated loop condition, skip it.
1082     if (init->gtFlags & GTF_STMT_CMPADD)
1083     {
1084         // Must be a duplicated loop condition.
1085         noway_assert(init->gtStmt.gtStmtExpr->gtOper == GT_JTRUE);
1086         init = init->gtPrev;
1087         noway_assert(init != nullptr);
1088     }
1089
1090     noway_assert(init->gtOper == GT_STMT);
1091     noway_assert(test->gtOper == GT_STMT);
1092     noway_assert(incr->gtOper == GT_STMT);
1093
1094     *ppInit = init->gtStmt.gtStmtExpr;
1095     *ppTest = test->gtStmt.gtStmtExpr;
1096     *ppIncr = incr->gtStmt.gtStmtExpr;
1097
1098     return true;
1099 }
1100
1101 /*****************************************************************************
1102  *
1103  *  Record the loop in the loop table.
1104  */
1105
1106 void                Compiler::optRecordLoop(BasicBlock *    head,
1107                                             BasicBlock *    first,
1108                                             BasicBlock *    top,
1109                                             BasicBlock *    entry,
1110                                             BasicBlock *    bottom,
1111                                             BasicBlock *    exit,
1112                                             unsigned char   exitCnt)
1113 {
1114     // Record this loop in the table, if there's room.
1115
1116     assert(optLoopCount <= MAX_LOOP_NUM);
1117     if (optLoopCount == MAX_LOOP_NUM) 
1118     {
1119 #if COUNT_LOOPS
1120         loopOverflowThisMethod = true;
1121 #endif
1122         return;
1123     }
1124
1125     // Assumed preconditions on the loop we're adding.
1126     assert(first->bbNum <= top->bbNum);
1127     assert(top->bbNum <= entry->bbNum);
1128     assert(entry->bbNum <= bottom->bbNum);
1129     assert(head->bbNum < top->bbNum || head->bbNum > bottom->bbNum);
1130
1131     // If the new loop contains any existing ones, add it in the right place. 
1132     unsigned char loopInd = optLoopCount;
1133     for (unsigned char prevPlus1 = optLoopCount; prevPlus1 > 0; prevPlus1--)
1134     {
1135         unsigned char prev = prevPlus1 - 1;
1136         if (optLoopTable[prev].lpContainedBy(first, bottom))
1137             loopInd = prev;
1138     }
1139     // Move up any loops if necessary.
1140     for (unsigned j = optLoopCount; j > loopInd; j--)
1141     {
1142         optLoopTable[j] = optLoopTable[j-1];
1143     }
1144         
1145 #ifdef DEBUG
1146     for (unsigned i = loopInd+1; i < optLoopCount; i++)
1147     {
1148         // The loop is well-formed.
1149         assert(optLoopTable[i].lpWellFormed());
1150         // Check for disjoint.
1151         if (optLoopTable[i].lpDisjoint(first, bottom)) continue;
1152         // Otherwise, assert complete containment (of optLoopTable[i] in new loop).
1153         assert(optLoopTable[i].lpContainedBy(first, bottom));
1154     }
1155 #endif // DEBUG
1156
1157     optLoopTable[loopInd].lpHead      = head;
1158     optLoopTable[loopInd].lpFirst     = first;
1159     optLoopTable[loopInd].lpTop       = top;
1160     optLoopTable[loopInd].lpBottom    = bottom;
1161     optLoopTable[loopInd].lpEntry     = entry;
1162     optLoopTable[loopInd].lpExit      = exit;
1163     optLoopTable[loopInd].lpExitCnt   = exitCnt;
1164
1165     optLoopTable[loopInd].lpParent    = BasicBlock::NOT_IN_LOOP;
1166     optLoopTable[loopInd].lpChild     = BasicBlock::NOT_IN_LOOP;
1167     optLoopTable[loopInd].lpSibling   = BasicBlock::NOT_IN_LOOP;
1168
1169     optLoopTable[loopInd].lpFlags     = 0;
1170
1171     // We haven't yet recorded any side effects.
1172     optLoopTable[loopInd].lpLoopHasHeapHavoc = false;
1173     optLoopTable[loopInd].lpFieldsModified = nullptr;
1174     optLoopTable[loopInd].lpArrayElemTypesModified = 0;
1175
1176     // If DO-WHILE loop mark it as such.
1177     if (head->bbNext == entry)
1178     {
1179         optLoopTable[loopInd].lpFlags |= LPFLG_DO_WHILE;
1180     }
1181
1182     // If single exit loop mark it as such.
1183     if (exitCnt == 1)
1184     {
1185         noway_assert(exit);
1186         optLoopTable[loopInd].lpFlags |= LPFLG_ONE_EXIT;
1187     }
1188
1189     //
1190     // Try to find loops that have an iterator (i.e. for-like loops) "for (init; test; incr){ ... }"
1191     // We have the following restrictions:
1192     //     1. The loop condition must be a simple one i.e. only one JTRUE node
1193     //     2. There must be a loop iterator (a local var) that is
1194     //        incremented (decremented or lsh, rsh, mul) with a constant value
1195     //     3. The iterator is incremented exactly once
1196     //     4. The loop condition must use the iterator.
1197     //
1198     if  (bottom->bbJumpKind == BBJ_COND)
1199     {
1200         GenTreePtr init;
1201         GenTreePtr test;
1202         GenTreePtr incr;
1203         if (!optExtractInitTestIncr(head, bottom, top, &init, &test, &incr))
1204         {
1205             goto DONE_LOOP;
1206         }
1207
1208         unsigned iterVar = BAD_VAR_NUM;
1209         if (!optComputeIterInfo(incr, head->bbNext, bottom, &iterVar))
1210         {
1211             goto DONE_LOOP;
1212         }
1213
1214         // Make sure the "iterVar" initialization is never skipped,
1215         // i.e. HEAD dominates the ENTRY.
1216         if (!fgDominate(head, entry))
1217         {
1218             goto DONE_LOOP;
1219         }
1220
1221         if (!optPopulateInitInfo(loopInd, init, iterVar))
1222         {
1223             goto DONE_LOOP;
1224         }
1225
1226         // Check that the iterator is used in the loop condition.
1227         if (!optCheckIterInLoopTest(loopInd, test, head->bbNext, bottom, iterVar))
1228         {
1229             goto DONE_LOOP;
1230         }
1231
1232         // We know the loop has an iterator at this point ->flag it as LPFLG_ITER
1233         // Record the iterator, the pointer to the test node
1234         // and the initial value of the iterator (constant or local var)
1235         optLoopTable[loopInd].lpFlags |= LPFLG_ITER;
1236
1237         // Record iterator.
1238         optLoopTable[loopInd].lpIterTree = incr;
1239
1240 #if COUNT_LOOPS
1241         // Save the initial value of the iterator - can be lclVar or constant
1242         // Flag the loop accordingly.
1243
1244         iterLoopCount++;
1245 #endif
1246
1247 #if COUNT_LOOPS
1248         simpleTestLoopCount++;
1249 #endif
1250
1251         // Check if a constant iteration loop.
1252         if ((optLoopTable[loopInd].lpFlags & LPFLG_CONST_INIT) &&
1253             (optLoopTable[loopInd].lpFlags & LPFLG_CONST_LIMIT))
1254         {
1255             // This is a constant loop.
1256             optLoopTable[loopInd].lpFlags |= LPFLG_CONST;
1257 #if COUNT_LOOPS
1258             constIterLoopCount++;
1259 #endif
1260         }
1261
1262 #ifdef  DEBUG
1263         if (verbose && 0)
1264         {
1265             printf("\nConstant loop initializer:\n");
1266             gtDispTree(init);
1267
1268             printf("\nConstant loop body:\n");
1269
1270             BasicBlock* block = head;
1271             do
1272             {
1273                 block = block->bbNext;
1274                 for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
1275                 {
1276                     if (stmt->gtStmt.gtStmtExpr == incr)
1277                         break;
1278                     printf("\n");
1279                     gtDispTree(stmt->gtStmt.gtStmtExpr);
1280                 }
1281             }
1282             while (block != bottom);
1283         }
1284 #endif // DEBUG
1285     }
1286
1287
1288 DONE_LOOP:
1289     DBEXEC(verbose, optPrintLoopRecording(loopInd));
1290     optLoopCount++;
1291 }
1292
1293 #ifdef DEBUG
1294 //------------------------------------------------------------------------
1295 // optPrintLoopRecording: Print a recording of the loop.
1296 //
1297 // Arguments:
1298 //      loopInd     - loop index.
1299 //
1300 void Compiler::optPrintLoopRecording(unsigned loopInd)
1301 {
1302     printf("Recorded loop %s", (loopInd != optLoopCount ? "(extended) " : ""));
1303     optPrintLoopInfo(optLoopCount,  // Not necessarily the loop index, but the number of loops that have been added.
1304         optLoopTable[loopInd].lpHead, 
1305         optLoopTable[loopInd].lpFirst,
1306         optLoopTable[loopInd].lpTop,
1307         optLoopTable[loopInd].lpEntry,      
1308         optLoopTable[loopInd].lpBottom,
1309         optLoopTable[loopInd].lpExitCnt,
1310         optLoopTable[loopInd].lpExit
1311     );
1312
1313     // If an iterator loop print the iterator and the initialization.
1314     if  (optLoopTable[loopInd].lpFlags & LPFLG_ITER)
1315     {
1316         printf(" [over V%02u", optLoopTable[loopInd].lpIterVar());
1317         printf(" (");
1318         printf(GenTree::NodeName(optLoopTable[loopInd].lpIterOper()));
1319         printf(" ");
1320         printf("%d )", optLoopTable[loopInd].lpIterConst());
1321
1322         if  (optLoopTable[loopInd].lpFlags & LPFLG_CONST_INIT)
1323             printf(" from %d", optLoopTable[loopInd].lpConstInit);
1324         if  (optLoopTable[loopInd].lpFlags & LPFLG_VAR_INIT)
1325             printf(" from V%02u", optLoopTable[loopInd].lpVarInit);
1326
1327         // If a simple test condition print operator and the limits */
1328         printf(GenTree::NodeName(optLoopTable[loopInd].lpTestOper()));
1329
1330         if  (optLoopTable[loopInd].lpFlags & LPFLG_CONST_LIMIT)
1331             printf("%d ", optLoopTable[loopInd].lpConstLimit());
1332
1333         if  (optLoopTable[loopInd].lpFlags & LPFLG_VAR_LIMIT)
1334             printf("V%02u ", optLoopTable[loopInd].lpVarLimit());
1335
1336         printf("]");
1337     }
1338
1339     printf("\n");
1340 }
1341
1342 void                Compiler::optCheckPreds()
1343 {
1344     BasicBlock   *  block;
1345     BasicBlock   *  blockPred;
1346     flowList     *  pred;
1347
1348     for (block = fgFirstBB; block; block = block->bbNext)
1349     {
1350         for (pred = block->bbPreds; pred; pred = pred->flNext)
1351         {
1352             // make sure this pred is part of the BB list
1353             for (blockPred = fgFirstBB; blockPred; blockPred = blockPred->bbNext)
1354             {
1355                 if (blockPred == pred->flBlock)
1356                     break;
1357             }
1358             noway_assert(blockPred);
1359             switch (blockPred->bbJumpKind)
1360             {
1361             case BBJ_COND:
1362                 if (blockPred->bbJumpDest == block)
1363                     break;
1364                 __fallthrough;
1365             case BBJ_NONE:
1366                 noway_assert(blockPred->bbNext == block);
1367                 break;
1368             case BBJ_EHFILTERRET:
1369             case BBJ_ALWAYS:
1370             case BBJ_EHCATCHRET:
1371                 noway_assert(blockPred->bbJumpDest == block);
1372                 break;
1373             default:
1374                 break;
1375             }
1376         }
1377     }
1378 }
1379
1380 #endif // DEBUG
1381
1382 /*****************************************************************************
1383  * Find the natural loops, using dominators. Note that the test for
1384  * a loop is slightly different from the standard one, because we have
1385  * not done a depth first reordering of the basic blocks.
1386  */
1387
1388 void                Compiler::optFindNaturalLoops()
1389
1390 #ifdef DEBUG
1391     if  (verbose) 
1392         printf("*************** In optFindNaturalLoops()\n");
1393 #endif // DEBUG
1394
1395     flowList    *   pred;
1396     flowList    *   predTop;
1397     flowList    *   predEntry;
1398
1399     noway_assert(fgDomsComputed);
1400     assert(fgHasLoops);
1401
1402 #if COUNT_LOOPS
1403     hasMethodLoops  = false;
1404     loopsThisMethod = 0;
1405     loopOverflowThisMethod = false;
1406 #endif
1407
1408     /* We will use the following terminology:
1409      * HEAD    - the basic block that flows into the loop ENTRY block (Currently MUST be lexically before entry).
1410                  Not part of the looping of the loop.
1411      * FIRST   - the lexically first basic block (in bbNext order) within this loop.  (May be part of a nested loop,
1412      *           but not the outer loop. ???)
1413      * TOP     - the target of the backward edge from BOTTOM. In most cases FIRST and TOP are the same.
1414      * BOTTOM  - the lexically last block in the loop (i.e. the block from which we jump to the top)
1415      * EXIT    - the loop exit or the block right after the bottom
1416      * ENTRY   - the entry in the loop (not necessarly the TOP), but there must be only one entry
1417      *
1418      * We (currently) require the body of a loop to be a contiguous (in bbNext order) sequence of basic blocks.
1419
1420             |
1421             v
1422           head 
1423             |
1424             |    top/beg <--+
1425             |       |       |
1426             |      ...      |
1427             |       |       |
1428             |       v       |
1429             +---> entry     |
1430                     |       |
1431                    ...      |
1432                     |       |
1433                     v       |
1434              +-- exit/tail  |
1435              |      |       |
1436              |     ...      |
1437              |      |       |
1438              |      v       |
1439              |    bottom ---+
1440              |      
1441              +------+      
1442                     |
1443                     v
1444
1445      */
1446
1447     BasicBlock   *  head;
1448     BasicBlock   *  top;
1449     BasicBlock   *  bottom;
1450     BasicBlock   *  entry;
1451     BasicBlock   *  exit;
1452     unsigned char   exitCount;
1453
1454
1455     for (head = fgFirstBB; head->bbNext; head = head->bbNext)
1456     {
1457         top       = head->bbNext;
1458         exit      = NULL;
1459         exitCount = 0;
1460
1461         //  Blocks that are rarely run have a zero bbWeight and should
1462         //  never be optimized here
1463
1464         if (top->bbWeight == BB_ZERO_WEIGHT)
1465             continue;
1466
1467         for (pred = top->bbPreds; pred; pred = pred->flNext)
1468         {
1469             /* Is this a loop candidate? - We look for "back edges", i.e. an edge from BOTTOM
1470              * to TOP (note that this is an abuse of notation since this is not necessarily a back edge
1471              * as the definition says, but merely an indication that we have a loop there).
1472              * Thus, we have to be very careful and after entry discovery check that it is indeed
1473              * the only place we enter the loop (especially for non-reducible flow graphs).
1474              */
1475
1476             bottom    = pred->flBlock;
1477             exitCount = 0;
1478
1479             if (top->bbNum <= bottom->bbNum)    // is this a backward edge? (from BOTTOM to TOP)
1480             {
1481                 if ((bottom->bbJumpKind == BBJ_EHFINALLYRET) ||
1482                     (bottom->bbJumpKind == BBJ_EHFILTERRET)  ||
1483                     (bottom->bbJumpKind == BBJ_EHCATCHRET)   ||
1484                     (bottom->bbJumpKind == BBJ_CALLFINALLY)  ||
1485                     (bottom->bbJumpKind == BBJ_SWITCH)        )
1486                 {
1487                     /* BBJ_EHFINALLYRET, BBJ_EHFILTERRET, BBJ_EHCATCHRET, and BBJ_CALLFINALLY can never form a loop.
1488                      * BBJ_SWITCH that has a backward jump appears only for labeled break. */
1489                     goto NO_LOOP;
1490                 }
1491
1492                 BasicBlock   *   loopBlock;
1493
1494                 /* The presence of a "back edge" is an indication that a loop might be present here
1495                  *
1496                  * LOOP:
1497                  *        1. A collection of STRONGLY CONNECTED nodes i.e. there is a path from any
1498                  *           node in the loop to any other node in the loop (wholly within the loop)
1499                  *        2. The loop has a unique ENTRY, i.e. there is only one way to reach a node
1500                  *           in the loop from outside the loop, and that is through the ENTRY
1501                  */
1502
1503                 /* Let's find the loop ENTRY */
1504
1505                 if (head->bbJumpKind == BBJ_ALWAYS)
1506                 {
1507                     if (head->bbJumpDest->bbNum <= bottom->bbNum &&
1508                         head->bbJumpDest->bbNum >= top->bbNum  )
1509                     {
1510                         /* OK - we enter somewhere within the loop */
1511                         entry = head->bbJumpDest;
1512
1513                         /* some useful asserts
1514                          * Cannot enter at the top - should have being caught by redundant jumps */
1515
1516                         assert ((entry != top) || (head->bbFlags & BBF_KEEP_BBJ_ALWAYS));
1517                     }
1518                     else
1519                     {
1520                         /* special case - don't consider now */
1521                         //assert (!"Loop entered in weird way!");
1522                         goto NO_LOOP;
1523                     }
1524                 }
1525                 // Can we fall through into the loop?
1526                 else if (head->bbJumpKind == BBJ_NONE || head->bbJumpKind == BBJ_COND)
1527                 {
1528                     /* The ENTRY is at the TOP (a do-while loop) */
1529                     entry = top;
1530                 }
1531                 else 
1532                 {
1533                     goto NO_LOOP;       // head does not flow into the loop bail for now
1534                 }
1535
1536                 // Now we find the "first" block -- the earliest block reachable within the loop.
1537                 // This is usually the same as "top", but can differ in rare cases where "top" is
1538                 // the entry block of a nested loop, and that nested loop branches backwards to a
1539                 // a block before "top".  We find this by searching for such backwards branches
1540                 // in the loop known so far.
1541                 BasicBlock* first = top;
1542                 BasicBlock* newFirst;
1543                 bool blocksToSearch = true;
1544                 BasicBlock* validatedAfter = bottom->bbNext;
1545                 while (blocksToSearch)
1546                 {
1547                     blocksToSearch = false;
1548                     newFirst = nullptr;
1549                     blocksToSearch = false;
1550                     for (loopBlock = first; loopBlock != validatedAfter; loopBlock = loopBlock->bbNext)
1551                     {
1552                         unsigned nSucc = loopBlock->NumSucc();
1553                         for (unsigned j = 0; j < nSucc; j++)
1554                         {
1555                             BasicBlock* succ = loopBlock->GetSucc(j);
1556                             if (   (newFirst == nullptr && succ->bbNum < first->bbNum) 
1557                                 || (newFirst != nullptr && succ->bbNum < newFirst->bbNum))
1558                             {
1559                                 newFirst = succ;
1560                             }
1561                         }
1562                     }
1563                     if (newFirst != nullptr)
1564                     {
1565                         validatedAfter = first;
1566                         first = newFirst;
1567                         blocksToSearch = true;
1568                     }
1569                 }
1570
1571                 // Is "head" still before "first"?  If not, we don't have a valid loop...
1572                 if (head->bbNum >= first->bbNum)
1573                 {
1574                     JITDUMP("Extending loop [BB%02u..BB%02u] 'first' to BB%02u captures head BB%02u.  Rejecting loop.\n",
1575                            top->bbNum, bottom->bbNum, first->bbNum, head->bbNum);
1576                     goto NO_LOOP;
1577                 }
1578
1579                 /* Make sure ENTRY dominates all blocks in the loop
1580                  * This is necessary to ensure condition 2. above
1581                  * At the same time check if the loop has a single exit
1582                  * point - those loops are easier to optimize */
1583
1584                 for (loopBlock = top;
1585                      loopBlock != bottom->bbNext;
1586                      loopBlock = loopBlock->bbNext)
1587                 {
1588                     if (!fgDominate(entry, loopBlock))
1589                     {
1590                         goto NO_LOOP;
1591                     }
1592
1593                     if (loopBlock == bottom)
1594                     {
1595                         if (bottom->bbJumpKind != BBJ_ALWAYS)
1596                         {
1597                             /* there is an exit at the bottom */
1598
1599                             noway_assert(bottom->bbJumpDest == top);
1600                             exit = bottom;
1601                             exitCount++;
1602                             continue;
1603                         }
1604                     }
1605
1606                     BasicBlock  * exitPoint;
1607
1608                     switch (loopBlock->bbJumpKind)
1609                     {
1610                     case BBJ_COND:
1611                     case BBJ_CALLFINALLY:
1612                     case BBJ_ALWAYS:
1613                     case BBJ_EHCATCHRET:
1614                         assert (loopBlock->bbJumpDest);
1615                         exitPoint = loopBlock->bbJumpDest;
1616
1617                         if (exitPoint->bbNum < top->bbNum     ||
1618                             exitPoint->bbNum > bottom->bbNum   )
1619                         {
1620                             /* exit from a block other than BOTTOM */
1621                             exit = loopBlock;
1622                             exitCount++;
1623                         }
1624                         break;
1625
1626                     case BBJ_NONE:
1627                         break;
1628
1629                     case BBJ_EHFINALLYRET:
1630                     case BBJ_EHFILTERRET:
1631                         /* The "try" associated with this "finally" must be in the
1632                          * same loop, so the finally block will return control inside the loop */
1633                         break;
1634
1635                     case BBJ_THROW:
1636                     case BBJ_RETURN:
1637                         /* those are exits from the loop */
1638                         exit = loopBlock;
1639                         exitCount++;
1640                         break;
1641
1642                     case BBJ_SWITCH:
1643
1644                         unsigned        jumpCnt; jumpCnt = loopBlock->bbJumpSwt->bbsCount;
1645                         BasicBlock * *  jumpTab; jumpTab = loopBlock->bbJumpSwt->bbsDstTab;
1646
1647                         do
1648                         {
1649                             noway_assert(*jumpTab);
1650                             exitPoint = *jumpTab;
1651
1652                             if (exitPoint->bbNum < top->bbNum     ||
1653                                 exitPoint->bbNum > bottom->bbNum   )
1654                             {
1655                                 exit = loopBlock;
1656                                 exitCount++;
1657                             }
1658                         }
1659                         while (++jumpTab, --jumpCnt);
1660                         break;
1661
1662                     default:
1663                         noway_assert(!"Unexpected bbJumpKind");
1664                         break;
1665                     }
1666                 }
1667
1668                 /* Make sure we can iterate the loop (i.e. there is a way back to ENTRY)
1669                  * This is to ensure condition 1. above which prevents marking fake loops
1670                  *
1671                  * Below is an example:
1672                  *          for (....)
1673                  *          {
1674                  *            ...
1675                  *              computations
1676                  *            ...
1677                  *            break;
1678                  *          }
1679                  * The example above is not a loop since we bail after the first iteration
1680                  *
1681                  * The condition we have to check for is
1682                  *  1. ENTRY must have at least one predecessor inside the loop. Since we know that that block is
1683                  *     reachable, it can only be reached through ENTRY, therefore we have a way back to ENTRY
1684                  *
1685                  *  2. If we have a GOTO (BBJ_ALWAYS) outside of the loop and that block dominates the
1686                  *     loop bottom then we cannot iterate
1687                  *
1688                  * NOTE that this doesn't entirely satisfy condition 1. since "break" statements are not
1689                  * part of the loop nodes (as per definition they are loop exits executed only once),
1690                  * but we have no choice but to include them because we consider all blocks within TOP-BOTTOM */
1691
1692                 for (loopBlock = top; loopBlock != bottom; loopBlock = loopBlock->bbNext)
1693                 {
1694                     switch (loopBlock->bbJumpKind)
1695                     {
1696                     case BBJ_ALWAYS:
1697                     case BBJ_THROW:
1698                     case BBJ_RETURN:
1699                         if  (fgDominate(loopBlock, bottom))
1700                             goto NO_LOOP;
1701                     default:
1702                         break;
1703                     }
1704                 }
1705
1706                 bool canIterateLoop = false;
1707
1708                 for (predEntry = entry->bbPreds; predEntry; predEntry = predEntry->flNext)
1709                 {
1710                     if (predEntry->flBlock->bbNum >= top->bbNum    &&
1711                         predEntry->flBlock->bbNum <= bottom->bbNum  )
1712                     {
1713                         canIterateLoop = true;
1714                         break;
1715                     }
1716                     else if (predEntry->flBlock != head)
1717                     {
1718                         // The entry block has multiple predecessors outside the loop; the 'head'
1719                         // block isn't the only one. We only support a single 'head', so bail.
1720                         goto NO_LOOP;
1721                     }
1722                 }
1723
1724                 if (!canIterateLoop)
1725                     goto NO_LOOP;
1726
1727                 /* Double check - make sure that all loop blocks except ENTRY
1728                  * have no predecessors outside the loop - this ensures only one loop entry and prevents
1729                  * us from considering non-loops due to incorrectly assuming that we had a back edge
1730                  *
1731                  * OBSERVATION:
1732                  *    Loops of the form "while (a || b)" will be treated as 2 nested loops (with the same header)
1733                  */
1734
1735                 for (loopBlock = top;
1736                      loopBlock != bottom->bbNext;
1737                      loopBlock = loopBlock->bbNext)
1738                 {
1739                     if (loopBlock == entry)
1740                         continue;
1741
1742                     for (predTop = loopBlock->bbPreds;
1743                          predTop != nullptr;
1744                          predTop = predTop->flNext)
1745                     {
1746                         if (predTop->flBlock->bbNum < top->bbNum    ||
1747                             predTop->flBlock->bbNum > bottom->bbNum  )
1748                         {
1749                             //noway_assert(!"Found loop with multiple entries");
1750                             goto NO_LOOP;
1751                         }
1752                     }
1753                 }
1754
1755                 // Disqualify loops where the first block of the loop is less nested in EH than
1756                 // the bottom block. That is, we don't want to handle loops where the back edge
1757                 // goes from within an EH region to a first block that is outside that same EH
1758                 // region. Note that we *do* handle loops where the first block is the *first*
1759                 // block of a more nested EH region (since it is legal to branch to the first
1760                 // block of an immediately more nested EH region). So, for example, disqualify
1761                 // this:
1762                 //
1763                 // BB02
1764                 // ...
1765                 // try {
1766                 // ...
1767                 // BB10 BBJ_COND => BB02
1768                 // ...
1769                 // }
1770                 //
1771                 // Here, BB10 is more nested than BB02. 
1772
1773                 if (bottom->hasTryIndex() &&
1774                     !bbInTryRegions(bottom->getTryIndex(), first))
1775                 {
1776                     JITDUMP("Loop 'first' BB%02u is in an outer EH region compared to loop 'bottom' BB%02u. Rejecting loop.\n",
1777                            first->bbNum, bottom->bbNum);
1778                     goto NO_LOOP;
1779                 }
1780
1781 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1782                 // Disqualify loops where the first block of the loop is a finally target.
1783                 // The main problem is when multiple loops share a 'first' block that is a finally
1784                 // target and we canonicalize the loops by adding a new loop head. In that case, we
1785                 // need to update the blocks so the finally target bit is moved to the newly created
1786                 // block, and removed from the old 'first' block. This is 'hard', so at this point
1787                 // in the RyuJIT codebase (when we don't expect to keep the "old" ARM32 code generator
1788                 // long-term), it's easier to disallow the loop than to update the flow graph to
1789                 // support this case.
1790
1791                 if ((first->bbFlags & BBF_FINALLY_TARGET) != 0)
1792                 {
1793                     JITDUMP("Loop 'first' BB%02u is a finally target. Rejecting loop.\n",
1794                            first->bbNum);
1795                     goto NO_LOOP;
1796                 }
1797 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1798
1799                 /* At this point we have a loop - record it in the loop table
1800                  * If we found only one exit, record it in the table too
1801                  * (otherwise an exit = 0 in the loop table means multiple exits) */
1802
1803                 assert (pred);
1804                 if (exitCount != 1)
1805                 {
1806                     exit = 0;
1807                 }
1808                 optRecordLoop(head, first, top, entry, bottom, exit, exitCount);
1809
1810 #if COUNT_LOOPS
1811                 if (!hasMethodLoops)
1812                 {
1813                     /* mark the method as containing natural loops */
1814                     totalLoopMethods++;
1815                     hasMethodLoops = true;
1816                 }
1817
1818                 /* increment total number of loops found */
1819                 totalLoopCount++;
1820                 loopsThisMethod++;
1821
1822                 /* keep track of the number of exits */
1823                 loopExitCountTable.record(static_cast<unsigned>(exitCount));
1824 #endif // COUNT_LOOPS
1825             }
1826
1827             /* current predecessor not good for a loop - continue with another one, if any */
1828 NO_LOOP: ;
1829         }
1830     }
1831
1832 #if COUNT_LOOPS
1833     loopCountTable.record(loopsThisMethod);
1834     if (maxLoopsPerMethod < loopsThisMethod)
1835     {
1836         maxLoopsPerMethod = loopsThisMethod;
1837     }
1838     if (loopOverflowThisMethod)
1839     {
1840         totalLoopOverflows++;
1841     }
1842 #endif // COUNT_LOOPS
1843
1844     // Now the loop indices are stable.  We can figure out parent/child relationships
1845     // (using table indices to name loops), and label blocks.
1846     for (unsigned char loopInd = 1; loopInd < optLoopCount; loopInd++)
1847     {
1848         for (unsigned char possibleParent = loopInd; possibleParent > 0;)
1849         {
1850             possibleParent--;
1851             if (optLoopTable[possibleParent].lpContains(optLoopTable[loopInd]))
1852             {
1853                 optLoopTable[loopInd].lpParent = possibleParent;
1854                 optLoopTable[loopInd].lpSibling = optLoopTable[possibleParent].lpChild;
1855                 optLoopTable[possibleParent].lpChild = loopInd;
1856                 break;
1857             }
1858         }
1859     }
1860
1861     // Now label the blocks with the innermost loop to which they belong.  Since parents
1862     // precede children in the table, doing the labeling for each loop in order will achieve
1863     // this -- the innermost loop labeling will be done last.
1864     for (unsigned char loopInd = 0; loopInd < optLoopCount; loopInd++)
1865     {
1866         BasicBlock* first = optLoopTable[loopInd].lpFirst;
1867         BasicBlock* bottom = optLoopTable[loopInd].lpBottom;
1868         for (BasicBlock* blk = first; blk != nullptr; blk = blk->bbNext)
1869         {
1870             blk->bbNatLoopNum = loopInd;
1871             if (blk == bottom) break;
1872             assert(blk->bbNext != nullptr);  // We should never reach nullptr.
1873         }
1874     }
1875
1876     // Make sure that loops are canonical: that every loop has a unique "top", by creating an empty "nop"
1877     // one, if necessary, for loops containing others that share a "top."
1878     bool mod = false;
1879     for (unsigned char loopInd = 0; loopInd < optLoopCount; loopInd++)
1880     {
1881         // Traverse the outermost loops as entries into the loop nest; so skip non-outermost.
1882         if (optLoopTable[loopInd].lpParent != BasicBlock::NOT_IN_LOOP)
1883             continue;
1884
1885         // Otherwise...
1886         if (optCanonicalizeLoopNest(loopInd))
1887         {
1888             mod = true;
1889         }
1890     }
1891     if (mod)
1892     {
1893         fgUpdateChangedFlowGraph();
1894     }
1895
1896 #ifdef DEBUG
1897     if (verbose && optLoopCount > 0)
1898     {
1899         printf("\nFinal natural loop table:\n");
1900         for (unsigned loopInd = 0; loopInd < optLoopCount; loopInd++)
1901         {
1902             optPrintLoopInfo(loopInd);
1903             printf("\n");
1904         }
1905     }
1906 #endif // DEBUG
1907 }
1908
1909 void Compiler::optRedirectBlock(BasicBlock* blk, BlockToBlockMap* redirectMap)
1910 {
1911     BasicBlock* newJumpDest = nullptr;
1912     switch (blk->bbJumpKind)
1913     {
1914     case BBJ_THROW:
1915     case BBJ_RETURN: 
1916     case BBJ_NONE:
1917     case BBJ_EHFILTERRET:
1918     case BBJ_EHFINALLYRET:
1919     case BBJ_EHCATCHRET:
1920         // These have no jump destination to update.
1921         break;
1922
1923     case BBJ_ALWAYS:
1924     case BBJ_LEAVE:
1925     case BBJ_CALLFINALLY:
1926     case BBJ_COND:
1927         // All of these have a single jump destination to update.
1928         if (redirectMap->Lookup(blk->bbJumpDest, &newJumpDest))
1929         {
1930             blk->bbJumpDest = newJumpDest;
1931         }
1932         break;
1933
1934     case BBJ_SWITCH:
1935         {
1936             bool redirected = false;
1937             for (unsigned i = 0; i < blk->bbJumpSwt->bbsCount; i++)
1938             {
1939                 if (redirectMap->Lookup(blk->bbJumpSwt->bbsDstTab[i], &newJumpDest))
1940                 {
1941                     blk->bbJumpSwt->bbsDstTab[i] = newJumpDest;
1942                     redirected = true;
1943                 }
1944             }
1945             // If any redirections happend, invalidate the switch table map for the switch.
1946             if (redirected)
1947                 GetSwitchDescMap()->Remove(blk);
1948         }
1949         break;
1950
1951     default:
1952         unreached();
1953     }
1954 }
1955
1956 // TODO-Cleanup: This should be a static member of the BasicBlock class.
1957 void Compiler::optCopyBlkDest(BasicBlock* from, BasicBlock* to)
1958 {
1959     assert(from->bbJumpKind == to->bbJumpKind); // Precondition.
1960
1961     // copy the jump destination(s) from "from" to "to".
1962     switch (to->bbJumpKind)
1963     {
1964     case BBJ_ALWAYS:
1965     case BBJ_LEAVE:
1966     case BBJ_CALLFINALLY:
1967     case BBJ_COND:
1968         // All of these have a single jump destination to update.
1969         to->bbJumpDest = from->bbJumpDest;
1970         break;
1971
1972     case BBJ_SWITCH:
1973         {
1974             to->bbJumpSwt = new (this, CMK_BasicBlock) BBswtDesc();
1975             to->bbJumpSwt->bbsCount = from->bbJumpSwt->bbsCount;
1976             to->bbJumpSwt->bbsDstTab = new (this, CMK_BasicBlock) BasicBlock*[from->bbJumpSwt->bbsCount];
1977
1978             for (unsigned i = 0; i < from->bbJumpSwt->bbsCount; i++)
1979             {
1980                 to->bbJumpSwt->bbsDstTab[i] = from->bbJumpSwt->bbsDstTab[i];
1981             }
1982         }
1983         break;
1984
1985     default:
1986         break;
1987     }
1988 }
1989
1990 // Canonicalize the loop nest rooted at parent loop 'loopInd'.
1991 // Returns 'true' if the flow graph is modified.
1992 bool Compiler::optCanonicalizeLoopNest(unsigned char loopInd)
1993 {
1994     bool modified = false;
1995
1996     // Is the top of the current loop not in any nested loop?
1997     if (optLoopTable[loopInd].lpTop->bbNatLoopNum != loopInd)
1998     {
1999         if (optCanonicalizeLoop(loopInd))
2000         {
2001             modified = true;
2002         }
2003     }
2004
2005     for (unsigned char child = optLoopTable[loopInd].lpChild; 
2006          child != BasicBlock::NOT_IN_LOOP; 
2007          child = optLoopTable[child].lpSibling)
2008     {
2009         if (optCanonicalizeLoopNest(child))
2010         {
2011             modified = true;
2012         }
2013     }
2014
2015     return modified;
2016 }
2017
2018 bool Compiler::optCanonicalizeLoop(unsigned char loopInd)
2019 {
2020     // Is the top uniquely part of the current loop?
2021     BasicBlock* t = optLoopTable[loopInd].lpTop;
2022
2023     if (t->bbNatLoopNum == loopInd)
2024         return false;
2025
2026     JITDUMP("in optCanonicalizeLoop: L%02u has top BB%02u (bottom BB%02u) with natural loop number L%02u: need to canonicalize\n",
2027             loopInd, t->bbNum, optLoopTable[loopInd].lpBottom->bbNum, t->bbNatLoopNum);
2028
2029     // Otherwise, the top of this loop is also part of a nested loop.
2030     //
2031     // Insert a new unique top for this loop. We must be careful to put this new
2032     // block in the correct EH region. Note that f->bbPrev might be in a different
2033     // EH region. For example:
2034     //
2035     // try {
2036     //      ...
2037     //      BB07
2038     // }
2039     // BB08 // "first"
2040     //
2041     // In this case, first->bbPrev is BB07, which is in a different 'try' region.
2042     // On the other hand, the first block of multiple loops might be the first
2043     // block of a 'try' region that is completely contained in the multiple loops.
2044     // for example:
2045     //
2046     // BB08 try { }
2047     // ...
2048     // BB10 BBJ_ALWAYS => BB08
2049     // ...
2050     // BB12 BBJ_ALWAYS => BB08
2051     //
2052     // Here, we have two loops, both with BB08 as the "first" block. Block BB08
2053     // is a single-block "try" region. Neither loop "bottom" block is in the same
2054     // "try" region as BB08. This is legal because you can jump to the first block
2055     // of a try region. With EH normalization, no two "try" regions will share
2056     // this block. In this case, we need to insert a new block for the outer loop
2057     // in the same EH region as the branch from the "bottom":
2058     //
2059     // BB30 BBJ_NONE
2060     // BB08 try { }
2061     // ...
2062     // BB10 BBJ_ALWAYS => BB08
2063     // ...
2064     // BB12 BBJ_ALWAYS => BB30
2065     //
2066     // Another possibility is that the "first" block of the loop nest can be the first block
2067     // of a "try" region that also has other predecessors than those in the loop, or even in
2068     // the "try" region (since blocks can target the first block of a "try" region). For example:
2069     //
2070     // BB08 try {
2071     // ...
2072     // BB10 BBJ_ALWAYS => BB08
2073     // ...
2074     // BB12 BBJ_ALWAYS => BB08
2075     // BB13 }
2076     // ...
2077     // BB20 BBJ_ALWAYS => BB08
2078     // ...
2079     // BB25 BBJ_ALWAYS => BB08
2080     //
2081     // Here, BB08 has 4 flow graph predecessors: BB10, BB12, BB20, BB25. These are all potential loop
2082     // bottoms, for four possible nested loops. However, we require all the loop bottoms to be in the
2083     // same EH region. For loops BB08..BB10 and BB08..BB12, we need to add a new "top" block within
2084     // the try region, immediately before BB08. The bottom of the loop BB08..BB10 loop will target the
2085     // old BB08, and the bottom of the BB08..BB12 loop will target the new loop header. The other branches
2086     // (BB20, BB25) must target the new loop header, both for correctness, and to avoid the illegal
2087     // situation of branching to a non-first block of a 'try' region.
2088     //
2089     // We can also have a loop nest where the "first" block is outside of a "try" region
2090     // and the back edges are inside a "try" region, for example:
2091     //
2092     // BB02 // "first"
2093     // ...
2094     // BB09 try { BBJ_COND => BB02
2095     // ...
2096     // BB15 BBJ_COND => BB02
2097     // ...
2098     // BB21 } // end of "try"
2099     //
2100     // In this case, both loop back edges were formed by "leave" instructions that were
2101     // imported into branches that were later made conditional. In this case, we don't
2102     // want to copy the EH region of the back edge, since that would create a block
2103     // outside of and disjoint with the "try" region of the back edge. However, to
2104     // simplify things, we disqualify this type of loop, so we should never see this here.
2105
2106     BasicBlock* h = optLoopTable[loopInd].lpHead;
2107     BasicBlock* f = optLoopTable[loopInd].lpFirst;
2108     BasicBlock* b = optLoopTable[loopInd].lpBottom;
2109
2110     // The loop must be entirely contained within a single handler region.
2111     assert(BasicBlock::sameHndRegion(f, b));
2112
2113     // If the bottom block is in the same "try" region, then we extend the EH
2114     // region. Otherwise, we add the new block outside the "try" region.
2115     bool extendRegion = BasicBlock::sameTryRegion(f, b);
2116     BasicBlock* newT = fgNewBBbefore(BBJ_NONE, f, extendRegion);
2117     if (!extendRegion)
2118     {
2119         // We need to set the EH region manually. Set it to be the same
2120         // as the bottom block.
2121         newT->copyEHRegion(b);
2122     }
2123
2124     BlockSetOps::Assign(this, newT->bbReach, t->bbReach);
2125
2126     // Redirect the "bottom" of the current loop to "newT".
2127     BlockToBlockMap* blockMap = new (getAllocatorLoopHoist()) BlockToBlockMap(getAllocatorLoopHoist());
2128     blockMap->Set(t, newT);
2129     optRedirectBlock(b, blockMap);
2130
2131     // Redirect non-loop preds of "t" to also go to "newT". Inner loops that also branch to "t" should continue
2132     // to do so. However, there maybe be other predecessors from outside the loop nest that need to be updated
2133     // to point to "newT". This normally wouldn't happen, since they too would be part of the loop nest. However,
2134     // they might have been prevented from participating in the loop nest due to different EH nesting, or some
2135     // other reason.
2136     //
2137     // Note that optRedirectBlock doesn't update the predecessors list. So, if the same 't' block is processed
2138     // multiple times while canonicalizing multiple loop nests, we'll attempt to redirect a predecessor multiple times.
2139     // This is ok, because after the first redirection, the topPredBlock branch target will no longer match the source
2140     // edge of the blockMap, so nothing will happen.
2141     for (flowList* topPred = t->bbPreds; topPred != nullptr; topPred = topPred->flNext)
2142     {
2143         BasicBlock* topPredBlock = topPred->flBlock;
2144
2145         // Skip if topPredBlock is in the loop.
2146         // Note that this uses block number to detect membership in the loop. We are adding blocks during
2147         // canonicalization, and those block numbers will be new, and larger than previous blocks. However, we work
2148         // outside-in, so we shouldn't encounter the new blocks at the loop boundaries, or in the predecessor lists.
2149         if (t->bbNum <= topPredBlock->bbNum && topPredBlock->bbNum <= b->bbNum)
2150         {
2151             JITDUMP("in optCanonicalizeLoop: 'top' predecessor BB%02u is in the range of L%02u (BB%02u..BB%02u); not redirecting its bottom edge\n",
2152                     topPredBlock->bbNum, loopInd, t->bbNum, b->bbNum);
2153             continue;
2154         }
2155
2156         JITDUMP("in optCanonicalizeLoop: redirect top predecessor BB%02u to BB%02u\n", topPredBlock->bbNum, newT->bbNum);
2157         optRedirectBlock(topPredBlock, blockMap);
2158     }
2159
2160     assert(newT->bbNext == f);
2161     if (f != t)
2162     {
2163         newT->bbJumpKind = BBJ_ALWAYS;
2164         newT->bbJumpDest = t;
2165         newT->bbTreeList = nullptr;
2166         fgInsertStmtAtEnd(newT, fgNewStmtFromTree(gtNewOperNode(GT_NOP, TYP_VOID, nullptr)));
2167     }
2168
2169     // If it had been a do-while loop (top == entry), update entry, as well.
2170     BasicBlock* origE = optLoopTable[loopInd].lpEntry;
2171     if (optLoopTable[loopInd].lpTop == origE)
2172         optLoopTable[loopInd].lpEntry = newT;
2173     optLoopTable[loopInd].lpTop = newT;
2174     optLoopTable[loopInd].lpFirst = newT;
2175
2176     newT->bbNatLoopNum = loopInd;
2177
2178     JITDUMP("in optCanonicalizeLoop: made new block BB%02u [%p] the new unique top of loop %d.\n", newT->bbNum, dspPtr(newT), loopInd);
2179
2180     // Make sure the head block still goes to the entry...
2181     if (h->bbJumpKind == BBJ_NONE &&
2182         h->bbNext != optLoopTable[loopInd].lpEntry)
2183     {
2184         h->bbJumpKind = BBJ_ALWAYS;
2185         h->bbJumpDest = optLoopTable[loopInd].lpEntry;
2186     }
2187     else if (h->bbJumpKind == BBJ_COND &&
2188              h->bbNext == newT &&
2189              newT != optLoopTable[loopInd].lpEntry)
2190     {
2191         BasicBlock* h2 = fgNewBBafter(BBJ_ALWAYS, h, /*extendRegion*/true);
2192         optLoopTable[loopInd].lpHead = h2;
2193         h2->bbJumpDest = optLoopTable[loopInd].lpEntry;
2194         h2->bbTreeList = nullptr;
2195         fgInsertStmtAtEnd(h2, fgNewStmtFromTree(gtNewOperNode(GT_NOP, TYP_VOID, nullptr)));
2196     }
2197
2198     // If any loops nested in "loopInd" have the same head and entry as "loopInd",
2199     // it must be the case that they were do-while's (since "h" fell through to the entry).
2200     // The new node "newT" becomes the head of such loops.
2201     for (unsigned char childLoop = optLoopTable[loopInd].lpChild;
2202          childLoop != BasicBlock::NOT_IN_LOOP;
2203          childLoop = optLoopTable[childLoop].lpSibling)
2204     {
2205         if (   optLoopTable[childLoop].lpEntry == origE 
2206             && optLoopTable[childLoop].lpHead == h
2207             && newT->bbJumpKind == BBJ_NONE 
2208             && newT->bbNext == origE)
2209         {
2210             optUpdateLoopHead(childLoop, h, newT);
2211         }
2212     }
2213     return true;
2214 }
2215
2216 bool Compiler::optLoopContains(unsigned l1, unsigned l2)
2217 {
2218     assert(l1 != BasicBlock::NOT_IN_LOOP);
2219     if (l1 == l2) return true;
2220     else if (l2 == BasicBlock::NOT_IN_LOOP) return false;
2221     else return optLoopContains(l1, optLoopTable[l2].lpParent);
2222 }
2223         
2224 void Compiler::optUpdateLoopHead(unsigned loopInd, BasicBlock* from, BasicBlock* to)
2225 {
2226     assert(optLoopTable[loopInd].lpHead == from);
2227     optLoopTable[loopInd].lpHead = to;
2228     for (unsigned char childLoop = optLoopTable[loopInd].lpChild;
2229          childLoop != BasicBlock::NOT_IN_LOOP;
2230          childLoop = optLoopTable[childLoop].lpSibling)
2231     {
2232         if (optLoopTable[childLoop].lpHead == from)
2233             optUpdateLoopHead(childLoop, from, to);
2234     }
2235 }
2236
2237 /*****************************************************************************
2238  * If the : i += const" will cause an overflow exception for the small types.
2239  */
2240
2241 bool                jitIterSmallOverflow(int iterAtExit, var_types incrType)
2242 {
2243     int            type_MAX;
2244
2245     switch (incrType)
2246     {
2247     case TYP_BYTE:  type_MAX = SCHAR_MAX;   break;
2248     case TYP_UBYTE: type_MAX = UCHAR_MAX;   break;
2249     case TYP_SHORT: type_MAX =  SHRT_MAX;   break;
2250     case TYP_CHAR:  type_MAX = USHRT_MAX;   break;
2251
2252     case TYP_UINT:                  // Detected by checking for 32bit ....
2253     case TYP_INT:   return false;   // ... overflow same as done for TYP_INT
2254
2255     default:        NO_WAY("Bad type");
2256     }
2257
2258     if (iterAtExit > type_MAX)
2259         return true;
2260     else
2261         return false;
2262 }
2263
2264 /*****************************************************************************
2265  * If the "i -= const" will cause an underflow exception for the small types
2266  */
2267
2268 bool                jitIterSmallUnderflow(int iterAtExit, var_types decrType)
2269 {
2270     int            type_MIN;
2271
2272     switch (decrType)
2273     {
2274     case TYP_BYTE:  type_MIN = SCHAR_MIN;   break;
2275     case TYP_SHORT: type_MIN =  SHRT_MIN;   break;
2276     case TYP_UBYTE: type_MIN =         0;   break;
2277     case TYP_CHAR:  type_MIN =         0;   break;
2278
2279     case TYP_UINT:                  // Detected by checking for 32bit ....
2280     case TYP_INT:   return false;   // ... underflow same as done for TYP_INT
2281
2282     default:        NO_WAY("Bad type");
2283     }
2284
2285     if (iterAtExit < type_MIN)
2286         return true;
2287     else
2288         return false;
2289 }
2290
2291 /*****************************************************************************
2292  *
2293  *  Helper for unroll loops - Computes the number of repetitions
2294  *  in a constant loop. If it cannot prove the number is constant returns false
2295  */
2296
2297 bool                Compiler::optComputeLoopRep(int             constInit,
2298                                                 int             constLimit,
2299                                                 int             iterInc,
2300                                                 genTreeOps      iterOper,
2301                                                 var_types       iterOperType,
2302                                                 genTreeOps      testOper,
2303                                                 bool            unsTest,
2304                                                 bool            dupCond,
2305                                                 unsigned *      iterCount)
2306 {
2307     noway_assert(genActualType(iterOperType) == TYP_INT);
2308
2309     __int64         constInitX;
2310     __int64         constLimitX;
2311
2312     unsigned        loopCount;
2313     int             iterSign;
2314
2315     // Using this, we can just do a signed comparison with other 32 bit values.
2316     if (unsTest)    constLimitX = (unsigned int)constLimit;
2317     else            constLimitX = (  signed int)constLimit;
2318
2319     switch (iterOperType)
2320     {
2321         // For small types, the iteration operator will narrow these values if big
2322
2323 #define INIT_ITER_BY_TYPE(type)      constInitX = (type)constInit; iterInc = (type)iterInc;
2324
2325     case TYP_BYTE:  INIT_ITER_BY_TYPE(  signed char );  break;
2326     case TYP_UBYTE: INIT_ITER_BY_TYPE(unsigned char );  break;
2327     case TYP_SHORT: INIT_ITER_BY_TYPE(  signed short);  break;
2328     case TYP_CHAR:  INIT_ITER_BY_TYPE(unsigned short);  break;
2329
2330         // For the big types, 32 bit arithmetic is performed
2331
2332     case TYP_INT:
2333     case TYP_UINT:  if (unsTest)    constInitX = (unsigned int)constInit;
2334                     else            constInitX = (  signed int)constInit;
2335                     break;
2336
2337     default:        
2338         noway_assert(!"Bad type");
2339         NO_WAY("Bad type");
2340     }
2341
2342     /* If iterInc is zero we have an infinite loop */
2343     if (iterInc == 0)
2344         return false;
2345
2346     /* Set iterSign to +1 for positive iterInc and -1 for negative iterInc */
2347     iterSign  = (iterInc > 0) ? +1 : -1;
2348
2349     /* Initialize loopCount to zero */
2350     loopCount = 0;
2351
2352     // If dupCond is true then the loop head contains a test which skips
2353     // this loop, if the constInit does not pass the loop test
2354     // Such a loop can execute zero times.
2355     // If dupCond is false then we have a true do-while loop which we
2356     // always execute the loop once before performing the loop test
2357     if (!dupCond)
2358     {
2359         loopCount  += 1;
2360         constInitX += iterInc;       
2361     }
2362
2363     // bail if count is based on wrap-around math
2364     if (iterInc > 0)
2365     {
2366         if (constLimitX < constInitX)
2367             return false;
2368     }
2369     else if (constLimitX > constInitX)
2370         return false;
2371
2372    /* Compute the number of repetitions */
2373
2374     switch (testOper)
2375     {
2376         __int64     iterAtExitX;
2377
2378     case GT_EQ:
2379         /* something like "for (i=init; i == lim; i++)" doesn't make any sense */
2380         return false;
2381
2382     case GT_NE:
2383         /*  "for (i=init; i != lim; i+=const)" - this is tricky since it may 
2384          *  have a constant number of iterations or loop forever - 
2385          *  we have to compute (lim-init) mod iterInc to see if it is zero.
2386          * If mod iterInc is not zero then the limit test will miss an a wrap will occur
2387          * which is probably not what the end user wanted, but it is legal.
2388          */
2389
2390         if (iterInc > 0)
2391         {
2392             /* Stepping by one, i.e. Mod with 1 is always zero */
2393             if (iterInc != 1)
2394             {
2395                 if (((constLimitX - constInitX) % iterInc) != 0)
2396                     return false;
2397             }
2398         }
2399         else
2400         {
2401             noway_assert(iterInc < 0);
2402             /* Stepping by -1, i.e. Mod with 1 is always zero */
2403             if (iterInc != -1)
2404             {
2405                 if (((constInitX - constLimitX) % (-iterInc)) != 0)
2406                     return false;
2407             }
2408         }
2409
2410         switch (iterOper)
2411         {
2412         case GT_ASG_SUB:
2413         case GT_SUB:
2414             iterInc = -iterInc;
2415             __fallthrough;
2416
2417         case GT_ASG_ADD:
2418         case GT_ADD:
2419             if (constInitX != constLimitX)
2420                 loopCount += (unsigned) ((constLimitX - constInitX - iterSign) / iterInc) + 1;
2421
2422             iterAtExitX = (int)(constInitX + iterInc * (int)loopCount);
2423                 
2424             if (unsTest)
2425                 iterAtExitX = (unsigned)iterAtExitX;
2426                  
2427             // Check if iteration incr will cause overflow for small types
2428             if (jitIterSmallOverflow((int)iterAtExitX, iterOperType))
2429                 return false;
2430                  
2431             // iterator with 32bit overflow. Bad for TYP_(U)INT
2432             if (iterAtExitX < constLimitX)
2433                 return false;
2434
2435             *iterCount = loopCount;
2436             return true;
2437
2438         case GT_ASG_MUL:
2439         case GT_MUL:
2440         case GT_ASG_DIV:
2441         case GT_DIV:
2442         case GT_ASG_RSH:
2443         case GT_RSH:
2444         case GT_ASG_LSH:
2445         case GT_LSH:
2446         case GT_ASG_UDIV:
2447         case GT_UDIV:
2448             return false;
2449
2450         default:
2451             noway_assert(!"Unknown operator for loop iterator");
2452             return false;
2453         }
2454
2455     case GT_LT:
2456         switch (iterOper)
2457         {
2458         case GT_ASG_SUB:
2459         case GT_SUB:
2460             iterInc = -iterInc;
2461             __fallthrough;
2462
2463         case GT_ASG_ADD:
2464         case GT_ADD:
2465             if (constInitX < constLimitX)
2466                 loopCount += (unsigned) ((constLimitX - constInitX - iterSign) / iterInc) + 1;
2467
2468             iterAtExitX = (int)(constInitX + iterInc * (int)loopCount);
2469                 
2470             if (unsTest)
2471                 iterAtExitX = (unsigned)iterAtExitX;
2472                 
2473             // Check if iteration incr will cause overflow for small types
2474             if (jitIterSmallOverflow((int)iterAtExitX, iterOperType))
2475                 return false;
2476                 
2477             // iterator with 32bit overflow. Bad for TYP_(U)INT
2478             if (iterAtExitX < constLimitX)
2479                 return false;
2480             
2481             *iterCount = loopCount;
2482             return true;
2483
2484         case GT_ASG_MUL:
2485         case GT_MUL:
2486         case GT_ASG_DIV:
2487         case GT_DIV:
2488         case GT_ASG_RSH:
2489         case GT_RSH:
2490         case GT_ASG_LSH:
2491         case GT_LSH:
2492         case GT_ASG_UDIV:
2493         case GT_UDIV:
2494             return false;
2495
2496         default:
2497             noway_assert(!"Unknown operator for loop iterator");
2498             return false;
2499         }
2500
2501     case GT_LE:
2502         switch (iterOper)
2503         {
2504         case GT_ASG_SUB:
2505         case GT_SUB:
2506             iterInc = -iterInc;
2507             __fallthrough;
2508
2509         case GT_ASG_ADD:
2510         case GT_ADD:
2511             if (constInitX <= constLimitX)
2512                 loopCount += (unsigned) ((constLimitX - constInitX) / iterInc) + 1;
2513                 
2514             iterAtExitX = (int)(constInitX + iterInc * (int)loopCount);
2515                 
2516             if (unsTest)
2517                 iterAtExitX = (unsigned)iterAtExitX;
2518                 
2519             // Check if iteration incr will cause overflow for small types
2520             if (jitIterSmallOverflow((int)iterAtExitX, iterOperType))
2521                 return false;
2522                 
2523             // iterator with 32bit overflow. Bad for TYP_(U)INT
2524             if (iterAtExitX <= constLimitX)
2525                 return false;
2526
2527             *iterCount = loopCount;
2528             return true;
2529
2530         case GT_ASG_MUL:
2531         case GT_MUL:
2532         case GT_ASG_DIV:
2533         case GT_DIV:
2534         case GT_ASG_RSH:
2535         case GT_RSH:
2536         case GT_ASG_LSH:
2537         case GT_LSH:
2538         case GT_ASG_UDIV:
2539         case GT_UDIV:
2540             return false;
2541
2542         default:
2543             noway_assert(!"Unknown operator for loop iterator");
2544             return false;
2545         }
2546
2547     case GT_GT:
2548         switch (iterOper)
2549         {
2550         case GT_ASG_SUB:
2551         case GT_SUB:
2552             iterInc = -iterInc;
2553             __fallthrough;
2554
2555         case GT_ASG_ADD:
2556         case GT_ADD:
2557             if (constInitX > constLimitX)
2558                 loopCount += (unsigned) ((constLimitX - constInitX - iterSign) / iterInc) + 1;
2559
2560             iterAtExitX = (int)(constInitX + iterInc * (int)loopCount);
2561                 
2562             if (unsTest)
2563                 iterAtExitX = (unsigned)iterAtExitX;
2564                 
2565             // Check if small types will underflow
2566             if (jitIterSmallUnderflow((int)iterAtExitX, iterOperType))
2567                 return false;
2568
2569             // iterator with 32bit underflow. Bad for TYP_INT and unsigneds
2570             if (iterAtExitX > constLimitX)
2571                 return false;
2572
2573             *iterCount = loopCount;
2574             return true;
2575
2576         case GT_ASG_MUL:
2577         case GT_MUL:
2578         case GT_ASG_DIV:
2579         case GT_DIV:
2580         case GT_ASG_RSH:
2581         case GT_RSH:
2582         case GT_ASG_LSH:
2583         case GT_LSH:
2584         case GT_ASG_UDIV:
2585         case GT_UDIV:
2586             return false;
2587
2588         default:
2589             noway_assert(!"Unknown operator for loop iterator");
2590             return false;
2591         }
2592
2593     case GT_GE:
2594         switch (iterOper)
2595         {
2596         case GT_ASG_SUB:
2597         case GT_SUB:
2598             iterInc = -iterInc;
2599             __fallthrough;
2600
2601         case GT_ASG_ADD:
2602         case GT_ADD:
2603             if (constInitX >= constLimitX)
2604                 loopCount += (unsigned) ((constLimitX - constInitX) / iterInc) + 1;
2605                 
2606             iterAtExitX = (int)(constInitX + iterInc * (int)loopCount);
2607             
2608             if (unsTest)
2609                 iterAtExitX = (unsigned)iterAtExitX;
2610             
2611             // Check if small types will underflow
2612             if (jitIterSmallUnderflow((int)iterAtExitX, iterOperType))
2613                 return false;
2614             
2615             // iterator with 32bit underflow. Bad for TYP_INT and unsigneds
2616             if (iterAtExitX >= constLimitX)
2617                 return false;
2618
2619             *iterCount = loopCount;
2620             return true;
2621
2622         case GT_ASG_MUL:
2623         case GT_MUL:
2624         case GT_ASG_DIV:
2625         case GT_DIV:
2626         case GT_ASG_RSH:
2627         case GT_RSH:
2628         case GT_ASG_LSH:
2629         case GT_LSH:
2630         case GT_ASG_UDIV:
2631         case GT_UDIV:
2632             return false;
2633
2634         default:
2635             noway_assert(!"Unknown operator for loop iterator");
2636             return false;
2637         }
2638
2639     default:
2640         noway_assert(!"Unknown operator for loop condition");
2641     }
2642
2643     return false;
2644 }
2645
2646
2647 /*****************************************************************************
2648  *
2649  *  Look for loop unrolling candidates and unroll them
2650  */
2651
2652 #ifdef _PREFAST_
2653 #pragma warning(push)
2654 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
2655 #endif
2656 void                Compiler::optUnrollLoops()
2657 {
2658     if (compCodeOpt() == SMALL_CODE)
2659         return;
2660
2661     if (optLoopCount == 0)
2662         return;
2663
2664 #ifdef DEBUG
2665     if (JitConfig.JitNoUnroll())
2666     {
2667         return;
2668     }
2669 #endif
2670
2671     if (optCanCloneLoops())
2672     {
2673         return;
2674     }
2675
2676 #ifdef DEBUG
2677     if  (verbose) 
2678         printf("*************** In optUnrollLoops()\n");
2679 #endif
2680     /* Look for loop unrolling candidates */
2681
2682     /*  Double loop so that after unrolling an inner loop we set change to true
2683      *  and we then go back over all of the loop candidates and try to unroll
2684      *  the next outer loop, until we don't unroll any loops, 
2685      *  then change will be false and we are done.
2686      */
2687     for (;;)
2688     {
2689         bool        change = false;
2690
2691         for (unsigned lnum = 0; lnum < optLoopCount; lnum++)
2692         {
2693             BasicBlock *    block;
2694             BasicBlock *    head;
2695             BasicBlock *    bottom;
2696
2697             GenTree *       loop;
2698             GenTree *       test;
2699             GenTree *       incr;
2700             GenTree *       phdr;
2701             GenTree *       init;
2702
2703             bool            dupCond;
2704             int             lval;
2705             int             lbeg;               // initial value for iterator
2706             int             llim;               // limit value for iterator
2707             unsigned        lvar;               // iterator lclVar #
2708             int             iterInc;            // value to increment the iterator
2709             genTreeOps      iterOper;           // type of iterator increment (i.e. ASG_ADD, ASG_SUB, etc.)
2710             var_types       iterOperType;       // type result of the oper (for overflow instrs)
2711             genTreeOps      testOper;           // type of loop test (i.e. GT_LE, GT_GE, etc.)
2712             bool            unsTest;            // Is the comparison u/int
2713
2714             unsigned        totalIter;          // total number of iterations in the constant loop
2715             unsigned        loopCostSz;         // Cost is size of one iteration
2716             unsigned        loopFlags;          // actual lpFlags
2717             unsigned        requiredFlags;      // required lpFlags
2718
2719             GenTree *       loopList;           // new stmt list of the unrolled loop
2720             GenTree *       loopLast;
2721
2722             static const int ITER_LIMIT[COUNT_OPT_CODE + 1] =
2723             {
2724                 10, // BLENDED_CODE
2725                 0,  // SMALL_CODE
2726                 20, // FAST_CODE
2727                 0   // COUNT_OPT_CODE
2728             };
2729
2730             noway_assert(ITER_LIMIT[    SMALL_CODE] == 0);
2731             noway_assert(ITER_LIMIT[COUNT_OPT_CODE] == 0);
2732
2733             unsigned iterLimit = (unsigned)ITER_LIMIT[compCodeOpt()];
2734
2735 #ifdef DEBUG
2736             if (compStressCompile(STRESS_UNROLL_LOOPS, 50))
2737                 iterLimit *= 10;
2738 #endif
2739
2740             static const int UNROLL_LIMIT_SZ[COUNT_OPT_CODE + 1] =
2741             {
2742                 30, // BLENDED_CODE
2743                 0,  // SMALL_CODE
2744                 60, // FAST_CODE
2745                 0   // COUNT_OPT_CODE
2746             };
2747
2748             noway_assert(UNROLL_LIMIT_SZ[    SMALL_CODE] == 0);
2749             noway_assert(UNROLL_LIMIT_SZ[COUNT_OPT_CODE] == 0);
2750
2751             int unrollLimitSz = (unsigned)UNROLL_LIMIT_SZ[compCodeOpt()];
2752
2753 #ifdef DEBUG
2754             if (compStressCompile(STRESS_UNROLL_LOOPS, 50))
2755                 unrollLimitSz *= 10;
2756 #endif
2757
2758             loopFlags     = optLoopTable[lnum].lpFlags;
2759             requiredFlags = LPFLG_DO_WHILE | LPFLG_ONE_EXIT | LPFLG_CONST;
2760
2761
2762             /* Ignore the loop if we don't have a do-while with a single exit
2763                that has a constant number of iterations */
2764
2765             if  ((loopFlags & requiredFlags) != requiredFlags)
2766                 continue;
2767
2768             /* ignore if removed or marked as not unrollable */
2769
2770             if  (optLoopTable[lnum].lpFlags & (LPFLG_DONT_UNROLL | LPFLG_REMOVED))
2771                 continue;
2772
2773             head   = optLoopTable[lnum].lpHead;   noway_assert(head);
2774             bottom = optLoopTable[lnum].lpBottom; noway_assert(bottom);
2775
2776             /* The single exit must be at the bottom of the loop */
2777             noway_assert(optLoopTable[lnum].lpExit);
2778             if  (optLoopTable[lnum].lpExit != bottom)
2779                 continue;
2780
2781             /* Unrolling loops with jumps in them is not worth the headache
2782              * Later we might consider unrolling loops after un-switching */
2783
2784             block = head;
2785             do
2786             {
2787                 block = block->bbNext; noway_assert(block);
2788
2789                 if  (block->bbJumpKind != BBJ_NONE)
2790                 {
2791                     if  (block != bottom)
2792                         goto DONE_LOOP;
2793                 }
2794             }
2795             while (block != bottom);
2796
2797             /* Get the loop data:
2798                 - initial constant
2799                 - limit constant
2800                 - iterator
2801                 - iterator increment
2802                 - increment operation type (i.e. ASG_ADD, ASG_SUB, etc...)
2803                 - loop test type (i.e. GT_GE, GT_LT, etc...)
2804              */
2805
2806             lbeg        = optLoopTable[lnum].lpConstInit;
2807             llim        = optLoopTable[lnum].lpConstLimit();
2808             testOper    = optLoopTable[lnum].lpTestOper();
2809
2810             lvar        = optLoopTable[lnum].lpIterVar();
2811             iterInc     = optLoopTable[lnum].lpIterConst();
2812             iterOper    = optLoopTable[lnum].lpIterOper();
2813
2814             iterOperType= optLoopTable[lnum].lpIterOperType();
2815             unsTest     =(optLoopTable[lnum].lpTestTree->gtFlags & GTF_UNSIGNED) != 0;
2816
2817             if (lvaTable[lvar].lvAddrExposed)    // If the loop iteration variable is address-exposed then bail
2818                 continue;
2819             if (lvaTable[lvar].lvIsStructField)  // If the loop iteration variable is a promoted field from a struct then bail
2820                 continue;             
2821
2822             /* Locate the pre-header and initialization and increment/test statements */
2823
2824             phdr = head->bbTreeList; noway_assert(phdr);
2825             loop = bottom->bbTreeList; noway_assert(loop);
2826
2827             init = head->lastStmt();   noway_assert(init && (init->gtNext == 0));
2828             test = bottom->lastStmt(); noway_assert(test && (test->gtNext == 0));
2829             incr = test->gtPrev;     noway_assert(incr);
2830
2831             if  (init->gtFlags & GTF_STMT_CMPADD)
2832             {
2833                 /* Must be a duplicated loop condition */
2834                 noway_assert(init->gtStmt.gtStmtExpr->gtOper == GT_JTRUE);
2835
2836                 dupCond = true;
2837                 init    = init->gtPrev; noway_assert(init);
2838             }
2839             else
2840                 dupCond = false;
2841
2842             /* Find the number of iterations - the function returns false if not a constant number */
2843
2844             if (!optComputeLoopRep(lbeg, llim,
2845                                    iterInc, iterOper, iterOperType,
2846                                    testOper, unsTest, dupCond,
2847                                    &totalIter))
2848                 continue;
2849
2850             /* Forget it if there are too many repetitions or not a constant loop */
2851
2852             if  (totalIter > iterLimit)
2853                 continue;
2854
2855             noway_assert(init->gtOper == GT_STMT); init = init->gtStmt.gtStmtExpr;
2856             noway_assert(test->gtOper == GT_STMT); test = test->gtStmt.gtStmtExpr;
2857             noway_assert(incr->gtOper == GT_STMT); incr = incr->gtStmt.gtStmtExpr;
2858
2859             // Don't unroll loops we don't understand.
2860             if (incr->gtOper == GT_ASG)
2861             {
2862                 continue;
2863             }
2864
2865             /* Make sure everything looks ok */
2866             if (
2867                  (init->gtOper                         != GT_ASG)     ||
2868                  (init->gtOp.gtOp1->gtOper             != GT_LCL_VAR) ||
2869                  (init->gtOp.gtOp1->gtLclVarCommon.gtLclNum  != lvar)       ||
2870                  (init->gtOp.gtOp2->gtOper             != GT_CNS_INT) ||
2871                  (init->gtOp.gtOp2->gtIntCon.gtIconVal != lbeg)       ||
2872
2873                 !((incr->gtOper == GT_ASG_ADD) || (incr->gtOper == GT_ASG_SUB)) ||
2874                  (incr->gtOp.gtOp1->gtOper             != GT_LCL_VAR) ||
2875                  (incr->gtOp.gtOp1->gtLclVarCommon.gtLclNum  != lvar)       ||
2876                  (incr->gtOp.gtOp2->gtOper             != GT_CNS_INT) ||
2877                  (incr->gtOp.gtOp2->gtIntCon.gtIconVal != iterInc)    ||
2878
2879                  (test->gtOper                         != GT_JTRUE)      )
2880             {
2881                 noway_assert(!"Bad precondition in Compiler::optUnrollLoops()");
2882                 continue;
2883             }
2884
2885             /* heuristic - Estimated cost in code size of the unrolled loop */
2886
2887             loopCostSz = 0;
2888
2889             block = head;
2890
2891             do
2892             {
2893                 block = block->bbNext;
2894
2895                 /* Visit all the statements in the block */
2896
2897                 for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
2898                 {
2899                     /* Get the expression and stop if end reached */
2900
2901                     GenTreePtr expr = stmt->gtStmtExpr;
2902                     if  (expr == incr)
2903                         break;
2904
2905                     /* Calculate gtCostSz */
2906                     gtSetStmtInfo(stmt);
2907
2908                     /* Update loopCostSz */
2909                     loopCostSz += stmt->gtCostSz;
2910                 }
2911             }
2912             while (block != bottom);
2913
2914             /* Compute the estimated increase in code size for the unrolled loop */
2915
2916             unsigned int fixedLoopCostSz; fixedLoopCostSz = 8;
2917
2918             int unrollCostSz; unrollCostSz  = (loopCostSz * totalIter) - (loopCostSz + fixedLoopCostSz);
2919
2920             /* Don't unroll if too much code duplication would result. */
2921
2922             if  (unrollCostSz > unrollLimitSz)
2923             {
2924                 /* prevent this loop from being revisited */
2925                 optLoopTable[lnum].lpFlags |= LPFLG_DONT_UNROLL;
2926                 goto DONE_LOOP;
2927             }
2928
2929             /* Looks like a good idea to unroll this loop, let's do it! */
2930             CLANG_FORMAT_COMMENT_ANCHOR;
2931
2932 #ifdef  DEBUG
2933             if (verbose)
2934             {
2935                 printf("\nUnrolling loop BB%02u", head->bbNext->bbNum);
2936                 if (head->bbNext->bbNum != bottom->bbNum)
2937                     printf("..BB%02u", bottom->bbNum);
2938                 printf(" over V%02u from %u to %u", lvar, lbeg, llim);
2939                 printf(" unrollCostSz = %d\n", unrollCostSz);
2940                 printf("\n");
2941             }
2942 #endif
2943
2944             /* Create the unrolled loop statement list */
2945
2946             loopList =
2947             loopLast = 0;
2948
2949             for (lval = lbeg; totalIter; totalIter--)
2950             {
2951                 block = head;
2952
2953                 do
2954                 {
2955                     GenTreeStmt *   stmt;
2956                     GenTree *       expr;
2957
2958                     block = block->bbNext; noway_assert(block);
2959
2960                     /* Visit all the statements in the block */
2961
2962                     for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
2963                     {
2964                         /* Stop if we've reached the end of the loop */
2965
2966                         if  (stmt->gtStmtExpr == incr)
2967                             break;
2968
2969                         /* Clone/substitute the expression */
2970
2971                         expr = gtCloneExpr(stmt, 0, lvar, lval);
2972
2973                         // cloneExpr doesn't handle everything
2974
2975                         if  (!expr)
2976                         {
2977                             optLoopTable[lnum].lpFlags |= LPFLG_DONT_UNROLL;
2978                             goto DONE_LOOP;
2979                         }
2980
2981                         /* Append the expression to our list */
2982
2983                         if  (loopList)
2984                             loopLast->gtNext = expr;
2985                         else
2986                             loopList         = expr;
2987
2988                         expr->gtPrev = loopLast;
2989                                        loopLast = expr;
2990                     }
2991                 }
2992                 while (block != bottom);
2993
2994                 /* update the new value for the unrolled iterator */
2995
2996                 switch (iterOper)
2997                 {
2998                     case GT_ASG_ADD:
2999                         lval += iterInc;
3000                         break;
3001
3002                     case GT_ASG_SUB:
3003                         lval -= iterInc;
3004                         break;
3005
3006                     case GT_ASG_RSH:
3007                     case GT_ASG_LSH:
3008                         noway_assert(!"Unrolling not implemented for this loop iterator");
3009                         goto DONE_LOOP;
3010
3011                     default:
3012                         noway_assert(!"Unknown operator for constant loop iterator");
3013                         goto DONE_LOOP;
3014                 }
3015             }
3016
3017             /* Finish the linked list */
3018
3019             if (loopList)
3020             {
3021                 loopList->gtPrev = loopLast;
3022                 loopLast->gtNext = 0;
3023             }
3024
3025             /* Replace the body with the unrolled one */
3026
3027             block = head;
3028
3029             do
3030             {
3031                 block             = block->bbNext; noway_assert(block);
3032                 block->bbTreeList = 0;
3033                 block->bbJumpKind = BBJ_NONE;
3034                 block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3035             }
3036             while (block != bottom);
3037
3038             bottom->bbJumpKind  = BBJ_NONE;
3039             bottom->bbTreeList  = loopList;
3040             bottom->bbFlags &= ~BBF_NEEDS_GCPOLL;
3041             bottom->modifyBBWeight(bottom->bbWeight / BB_LOOP_WEIGHT);
3042
3043             bool        dummy;
3044
3045             fgMorphStmts(bottom, &dummy, &dummy, &dummy);
3046
3047             /* Update bbRefs and bbPreds */
3048             /* Here head->bbNext is bottom !!! - Replace it */
3049
3050             fgRemoveRefPred(head->bbNext, bottom);
3051
3052             /* Now change the initialization statement in the HEAD to "lvar = lval;"
3053              * (the last value of the iterator in the loop)
3054              * and drop the jump condition since the unrolled loop will always execute */
3055
3056             init->gtOp.gtOp2->gtIntCon.gtIconVal =  lval;
3057
3058             /* if the HEAD is a BBJ_COND drop the condition (and make HEAD a BBJ_NONE block) */
3059
3060             if (head->bbJumpKind == BBJ_COND)
3061             {
3062                 phdr = head->bbTreeList; noway_assert(phdr);
3063                 test = phdr->gtPrev;
3064
3065                 noway_assert(test && (test->gtNext == 0));
3066                 noway_assert(test->gtOper == GT_STMT);
3067                 noway_assert(test->gtStmt.gtStmtExpr->gtOper == GT_JTRUE);
3068
3069                 init = test->gtPrev; noway_assert(init && (init->gtNext == test));
3070                 noway_assert(init->gtOper == GT_STMT);
3071
3072                 init->gtNext = 0;
3073                 phdr->gtPrev = init;
3074                 head->bbJumpKind = BBJ_NONE;
3075                 head->bbFlags &= ~BBF_NEEDS_GCPOLL;
3076
3077                 /* Update bbRefs and bbPreds */
3078
3079                 fgRemoveRefPred(head->bbJumpDest, head);
3080             }
3081             else
3082             {
3083                 /* the loop must execute */
3084                 noway_assert(head->bbJumpKind == BBJ_NONE);
3085             }
3086
3087 #ifdef  DEBUG
3088             if (verbose)
3089             {
3090                 printf("Whole unrolled loop:\n");
3091
3092                 GenTreePtr s = loopList;
3093
3094                 while (s)
3095                 {
3096                     noway_assert(s->gtOper == GT_STMT);
3097                     gtDispTree(s);
3098                     s = s->gtNext;
3099                 }
3100                 printf("\n");
3101
3102                 gtDispTree(init);
3103                 printf("\n");
3104             }
3105 #endif
3106
3107             /* Remember that something has changed */
3108
3109             change = true;
3110
3111             /* Make sure to update loop table */
3112
3113             /* Use the LPFLG_REMOVED flag and update the bbLoopMask acordingly
3114              * (also make head and bottom NULL - to hit an assert or GPF) */
3115
3116             optLoopTable[lnum].lpFlags |= LPFLG_REMOVED;
3117             optLoopTable[lnum].lpHead   =
3118             optLoopTable[lnum].lpBottom = nullptr;
3119
3120         DONE_LOOP:;
3121         }
3122
3123         if  (!change)
3124             break;
3125     }
3126
3127 #ifdef  DEBUG
3128     fgDebugCheckBBlist();
3129 #endif
3130 }
3131 #ifdef _PREFAST_
3132 #pragma warning(pop)
3133 #endif
3134
3135 /*****************************************************************************
3136  *
3137  *  Return non-zero if there is a code path from 'topBB' to 'botBB' that will
3138  *  not execute a method call.
3139  */
3140
3141 bool                Compiler::optReachWithoutCall(BasicBlock *topBB,
3142                                                   BasicBlock *botBB)
3143 {
3144     // TODO-Cleanup: Currently BBF_GC_SAFE_POINT is not set for helper calls, 
3145     // as some helper calls are neither interruptible nor hijackable.
3146     // When we can determine this, then we can set BBF_GC_SAFE_POINT for
3147     // those helpers too.
3148     
3149     noway_assert(topBB->bbNum <= botBB->bbNum);
3150
3151     // We can always check topBB and botBB for any gc safe points and early out
3152
3153     if ((topBB->bbFlags | botBB->bbFlags) & BBF_GC_SAFE_POINT)
3154         return false;
3155
3156     // Otherwise we will need to rely upon the dominator sets
3157
3158     if (!fgDomsComputed)
3159     {
3160         // return a conservative answer of true when we don't have the dominator sets
3161         return true;
3162     }
3163
3164     BasicBlock *curBB = topBB;
3165     for (;;)
3166     {
3167         noway_assert(curBB);
3168
3169         // If we added a loop pre-header block then we will
3170         //  have a bbNum greater than fgLastBB, and we won't have
3171         //  any dominator information about this block, so skip it.
3172         //
3173         if (curBB->bbNum <= fgLastBB->bbNum)
3174         {
3175             noway_assert(curBB->bbNum <= botBB->bbNum);
3176
3177             // Does this block contain a gc safe point?
3178
3179             if (curBB->bbFlags & BBF_GC_SAFE_POINT)
3180             {
3181                 // Will this block always execute on the way to botBB ?
3182                 //
3183                 // Since we are checking every block in [topBB .. botBB] and we are using 
3184                 // a lexical definition of a loop.
3185                 //  (all that we know is that is that botBB is a back-edge to topBB) 
3186                 // Thus while walking blocks in this range we may encounter some blocks
3187                 // that are not really part of the loop, and so we need to perform
3188                 // some additional checks:
3189                 //
3190                 // We will check that the current 'curBB' is reachable from 'topBB'
3191                 // and that it dominates the block containing the back-edge 'botBB'
3192                 // When both of these are true then we know that the gcsafe point in 'curBB'
3193                 // will be encountered in the loop and we can return false
3194                 //
3195                 if (fgDominate(curBB, botBB) && fgReachable(topBB, curBB))
3196                     return  false;
3197             }
3198             else
3199             {
3200                 // If we've reached the destination block, then we're done
3201
3202                 if (curBB == botBB)
3203                     break;
3204             }
3205         }
3206
3207         curBB = curBB->bbNext;
3208     }
3209
3210     // If we didn't find any blocks that contained a gc safe point and
3211     // also met the fgDominate and fgReachable criteria then we must return true
3212     //
3213     return  true;
3214 }
3215
3216 /*****************************************************************************
3217  *
3218  * Find the loop termination test at the bottom of the loop
3219  */
3220
3221 static
3222 GenTreePtr         optFindLoopTermTest(BasicBlock *bottom)
3223 {
3224     GenTreePtr      testt = bottom->bbTreeList;
3225
3226     assert(testt && testt->gtOper == GT_STMT);
3227
3228     GenTreePtr      result = testt->gtPrev;
3229
3230 #ifdef DEBUG
3231     while (testt->gtNext)
3232         testt = testt->gtNext;
3233
3234     assert(testt == result);
3235 #endif
3236
3237     return result;
3238 }
3239
3240 /*****************************************************************************
3241  * Optimize "jmp C; do{} C:while(cond);" loops to "if (cond){ do{}while(cond}; }"
3242  */
3243
3244 void                Compiler::fgOptWhileLoop(BasicBlock * block)
3245 {
3246     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
3247     noway_assert(compCodeOpt() != SMALL_CODE);
3248     
3249     /*
3250         Optimize while loops into do { } while loop
3251         Our loop hoisting logic requires do { } while loops.
3252         Specifically, we're looking for the following case:
3253
3254                 ...
3255                 jmp test
3256         loop:
3257                 ...
3258                 ...
3259         test:
3260                 cond
3261                 jtrue   loop
3262
3263         If we find this, and the condition is simple enough, we change
3264         the loop to the following:
3265
3266                 ...
3267                 cond
3268                 jfalse done
3269                 // else fall-through
3270         loop:
3271                 ...
3272                 ...
3273         test:
3274                 cond
3275                 jtrue   loop
3276         done:
3277
3278      */
3279
3280     /* Does the BB end with an unconditional jump? */
3281
3282     if  (block->bbJumpKind != BBJ_ALWAYS ||
3283          (block->bbFlags & BBF_KEEP_BBJ_ALWAYS)) // It can't be one of the ones we use for our exception magic
3284         return;
3285
3286     // It has to be a forward jump 
3287     //  TODO-CQ: Check if we can also optimize the backwards jump as well.
3288     //
3289     if (fgIsForwardBranch(block) == false)
3290         return;
3291
3292     // Get hold of the jump target
3293     BasicBlock * bTest = block->bbJumpDest; 
3294     
3295     // Does the block consist of 'jtrue(cond) block' ?
3296     if  (bTest->bbJumpKind != BBJ_COND)
3297         return;
3298
3299     // bTest must be a backwards jump to block->bbNext
3300     if  (bTest->bbJumpDest != block->bbNext)
3301         return;
3302
3303     // Since test is a BBJ_COND it will have a bbNext
3304     noway_assert(bTest->bbNext);
3305
3306     // 'block' must be in the same try region as the condition, since we're going to insert
3307     // a duplicated condition in 'block', and the condition might include exception throwing code.
3308     if (!BasicBlock::sameTryRegion(block, bTest))
3309         return;
3310
3311     // We're going to change 'block' to branch to bTest->bbNext, so that also better be in the
3312     // same try region (or no try region) to avoid generating illegal flow.
3313     BasicBlock* bTestNext = bTest->bbNext;
3314     if (bTestNext->hasTryIndex() && !BasicBlock::sameTryRegion(block, bTestNext))
3315         return;
3316
3317     GenTreePtr condStmt = optFindLoopTermTest(bTest);
3318
3319     // bTest must only contain only a jtrue with no other stmts, we will only clone
3320     // the conditional, so any other statements will not get cloned
3321     //  TODO-CQ: consider cloning the whole bTest block as inserting it after block.
3322     //
3323     if (bTest->bbTreeList != condStmt)
3324         return;
3325
3326     /* Get to the condition node from the statement tree */
3327
3328     noway_assert(condStmt->gtOper == GT_STMT);
3329     
3330     GenTreePtr condTree = condStmt->gtStmt.gtStmtExpr;
3331     noway_assert(condTree->gtOper == GT_JTRUE);
3332     
3333     condTree = condTree->gtOp.gtOp1;
3334
3335     // The condTree has to be a RelOp comparison
3336     //  TODO-CQ: Check if we can also optimize the backwards jump as well.
3337     //
3338     if (condTree->OperIsCompare() == false)
3339         return;
3340     
3341     /* We call gtPrepareCost to measure the cost of duplicating this tree */
3342     
3343     gtPrepareCost(condTree);
3344     unsigned estDupCostSz = condTree->gtCostSz;
3345
3346     double loopIterations = (double) BB_LOOP_WEIGHT;
3347
3348     bool   allProfileWeightsAreValid  = false;
3349     BasicBlock::weight_t weightBlock  = block->bbWeight;
3350     BasicBlock::weight_t weightTest   = bTest->bbWeight;
3351     BasicBlock::weight_t weightNext   = block->bbNext->bbWeight;
3352
3353     // If we have profile data then we calculate the number of time
3354     // the loop will iterate into loopIterations
3355     if (fgIsUsingProfileWeights())
3356     {
3357         // Only rely upon the profile weight when all three of these blocks
3358         // have good profile weights
3359         if ((block->bbFlags         & BBF_PROF_WEIGHT) &&
3360             (bTest->bbFlags         & BBF_PROF_WEIGHT) && 
3361             (block->bbNext->bbFlags & BBF_PROF_WEIGHT))
3362         {
3363             allProfileWeightsAreValid = true;
3364
3365             // If this while loop never iterates then don't bother transforming
3366             if (weightNext == 0)
3367                 return;
3368
3369             // with (weighNext > 0) we should also have (weightTest >= weightBlock)
3370             // if the profile weights are all valid.
3371             //
3372             //   weightNext is the number of time this loop iterates
3373             //   weightBlock is the number of times that we enter the while loop
3374             //   loopIterations is the average number of times that this loop iterates 
3375             //
3376             if (weightTest >= weightBlock)
3377             {
3378                 loopIterations = (double) block->bbNext->bbWeight / (double) block->bbWeight;
3379             }
3380         }
3381     }
3382
3383     unsigned maxDupCostSz = 32;
3384
3385     // optFastCodeOrBlendedLoop(bTest->bbWeight) does not work here as we have not
3386     // set loop weights yet
3387     if ((compCodeOpt() == FAST_CODE) || 
3388         compStressCompile(STRESS_DO_WHILE_LOOPS, 30))
3389     {
3390         maxDupCostSz *= 4;
3391     }
3392
3393     // If this loop iterates a lot then raise the maxDupCost
3394     if (loopIterations >= 12.0)
3395         maxDupCostSz *= 2;
3396     if (loopIterations >= 96.0)
3397         maxDupCostSz *= 2;
3398
3399     // If the loop condition has a shared static helper, we really want this loop converted
3400     // as not converting the loop will disable loop hoisting, meaning the shared helper will
3401     // be executed on every loop iteration.
3402     int countOfHelpers = 0;
3403     fgWalkTreePre(&condTree, CountSharedStaticHelper, &countOfHelpers);
3404
3405     if (countOfHelpers > 0 && compCodeOpt() != SMALL_CODE)
3406     {
3407         maxDupCostSz += 24 * min(countOfHelpers, (int) (loopIterations + 1.5));
3408     }
3409
3410     // If the compare has too high cost then we don't want to dup 
3411
3412     bool costIsTooHigh = (estDupCostSz > maxDupCostSz);
3413
3414 #ifdef  DEBUG
3415     if  (verbose)
3416     {
3417             printf("\nDuplication of loop condition [%06u] is %s, because the cost of duplication (%i) is %s than %i,"
3418                    "\n   loopIterations = %7.3f, countOfHelpers = %d, validProfileWeights = %s\n",
3419                       condTree->gtTreeID,
3420                       costIsTooHigh ? "not done" : "performed",
3421                       estDupCostSz, 
3422                       costIsTooHigh ? "greater" : "less or equal",
3423                       maxDupCostSz, 
3424                       loopIterations, countOfHelpers,
3425                       allProfileWeightsAreValid ? "true" : "false");
3426      }
3427 #endif
3428
3429     if (costIsTooHigh)
3430     {
3431         return;
3432     }
3433
3434     /* Looks good - duplicate the condition test */
3435
3436     condTree->gtFlags |= GTF_RELOP_ZTT;
3437
3438     condTree = gtCloneExpr(condTree);
3439     gtReverseCond(condTree);
3440
3441     // Make sure clone expr copied the flag
3442     assert(condTree->gtFlags & GTF_RELOP_ZTT);
3443
3444     condTree = gtNewOperNode(GT_JTRUE, TYP_VOID, condTree);
3445
3446     /* Create a statement entry out of the condition and
3447        append the condition test at the end of 'block' */
3448
3449     GenTreePtr copyOfCondStmt = fgInsertStmtAtEnd(block, condTree);
3450
3451     copyOfCondStmt->gtFlags |= GTF_STMT_CMPADD;
3452
3453 #ifdef DEBUGGING_SUPPORT
3454     if  (opts.compDbgInfo)
3455         copyOfCondStmt->gtStmt.gtStmtILoffsx = condStmt->gtStmt.gtStmtILoffsx;
3456 #endif
3457
3458     // If we have profile data for all blocks and we know that we are cloning the 
3459     //  bTest block into block and thus changing the control flow from block so
3460     //  that it no longer goes directly to bTest anymore, we have to adjust the 
3461     //  weight of bTest by subtracting out the weight of block.
3462     //
3463     if (allProfileWeightsAreValid)
3464     {
3465         //
3466         // Some additional sanity checks before adjusting the weight of bTest
3467         //
3468         if ((weightNext > 0) && (weightTest >= weightBlock) && (weightTest != BB_MAX_WEIGHT))
3469         {
3470             // Get the two edge that flow out of bTest
3471             flowList * edgeToNext = fgGetPredForBlock(bTest->bbNext, bTest);
3472             flowList * edgeToJump = fgGetPredForBlock(bTest->bbJumpDest, bTest);
3473
3474             // Calculate the new weight for block bTest
3475
3476             BasicBlock::weight_t newWeightTest = (weightTest > weightBlock)
3477                                                  ? (weightTest - weightBlock)
3478                                                  : BB_ZERO_WEIGHT;
3479             bTest->bbWeight = newWeightTest;
3480
3481             if (newWeightTest == BB_ZERO_WEIGHT)
3482             {
3483                 bTest->bbFlags |= BBF_RUN_RARELY;
3484                 // All out edge weights are set to zero
3485                 edgeToNext->flEdgeWeightMin = BB_ZERO_WEIGHT;
3486                 edgeToNext->flEdgeWeightMax = BB_ZERO_WEIGHT;
3487                 edgeToJump->flEdgeWeightMin = BB_ZERO_WEIGHT;
3488                 edgeToJump->flEdgeWeightMax = BB_ZERO_WEIGHT;
3489             }
3490             else
3491             {
3492                 // Update the our edge weights
3493                 edgeToNext->flEdgeWeightMin = BB_ZERO_WEIGHT;
3494                 edgeToNext->flEdgeWeightMax = min(edgeToNext->flEdgeWeightMax, newWeightTest); 
3495                 edgeToJump->flEdgeWeightMin = BB_ZERO_WEIGHT;
3496                 edgeToJump->flEdgeWeightMax = min(edgeToJump->flEdgeWeightMax, newWeightTest);    
3497             }
3498          }
3499     }
3500
3501     /* Change the block to end with a conditional jump */
3502
3503     block->bbJumpKind = BBJ_COND;
3504     block->bbJumpDest = bTest->bbNext;
3505
3506     /* Mark the jump dest block as being a jump target */
3507     block->bbJumpDest->bbFlags |= BBF_JMP_TARGET|BBF_HAS_LABEL;
3508
3509     /* Update bbRefs and bbPreds for 'block->bbNext' 'bTest' and 'bTest->bbNext' */
3510
3511     fgAddRefPred(block->bbNext, block);
3512
3513     fgRemoveRefPred(bTest, block);
3514     fgAddRefPred(bTest->bbNext, block);
3515
3516 #ifdef  DEBUG
3517     if  (verbose)
3518     {
3519         printf("\nDuplicating loop condition in BB%02u for loop (BB%02u - BB%02u)",
3520                block->bbNum, block->bbNext->bbNum, bTest->bbNum);
3521         printf("\nEstimated code size expansion is %d\n ", estDupCostSz);
3522
3523         gtDispTree(copyOfCondStmt);
3524     }
3525
3526 #endif
3527 }
3528
3529 /*****************************************************************************
3530  *
3531  *  Optimize the BasicBlock layout of the method
3532  */
3533
3534 void                Compiler::optOptimizeLayout()
3535 {
3536     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
3537
3538 #ifdef DEBUG
3539     if  (verbose) 
3540     {
3541         printf("*************** In optOptimizeLayout()\n");
3542         fgDispHandlerTab();
3543     }
3544
3545     /* Check that the flowgraph data (bbNum, bbRefs, bbPreds) is up-to-date */
3546     fgDebugCheckBBlist();
3547 #endif
3548
3549     noway_assert(fgModified == false);
3550
3551     for (BasicBlock *block = fgFirstBB; block; block = block->bbNext)
3552     {
3553         /* Make sure the appropriate fields are initialized */
3554
3555         if (block->bbWeight == BB_ZERO_WEIGHT)
3556         {
3557             /* Zero weighted block can't have a LOOP_HEAD flag */
3558             noway_assert(block->isLoopHead() == false);
3559             continue;
3560         }
3561         
3562         assert(block->bbLoopNum  == 0);
3563
3564         if (compCodeOpt() != SMALL_CODE)
3565         {
3566             /* Optimize "while(cond){}" loops to "cond; do{}while(cond);" */
3567
3568             fgOptWhileLoop(block);
3569         }
3570     }
3571
3572     if  (fgModified)
3573     {
3574         // Recompute the edge weight if we have modified the flow graph in fgOptWhileLoop
3575         fgComputeEdgeWeights();
3576     }
3577
3578     fgUpdateFlowGraph(true);
3579     fgReorderBlocks();
3580     fgUpdateFlowGraph();
3581 }
3582
3583 /*****************************************************************************
3584  *
3585  *  Perform loop inversion, find and classify natural loops
3586  */
3587
3588 void                Compiler::optOptimizeLoops()
3589 {
3590     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
3591
3592 #ifdef DEBUG
3593     if  (verbose) 
3594         printf("*************** In optOptimizeLoops()\n");
3595 #endif
3596
3597     optSetBlockWeights();
3598
3599     /* Were there any loops in the flow graph? */
3600
3601     if  (fgHasLoops)
3602     {
3603         /* now that we have dominator information we can find loops */
3604
3605         optFindNaturalLoops();
3606
3607         unsigned loopNum = 0;
3608
3609         /* Iterate over the flow graph, marking all loops */
3610
3611         /* We will use the following terminology:
3612          * top        - the first basic block in the loop (i.e. the head of the backward edge)
3613          * bottom     - the last block in the loop (i.e. the block from which we jump to the top)
3614          * lastBottom - used when we have multiple back-edges to the same top
3615          */
3616
3617         flowList *      pred;
3618
3619         BasicBlock *    top;
3620
3621         for (top = fgFirstBB; top; top = top->bbNext)
3622         {
3623             BasicBlock * foundBottom = NULL;
3624
3625             for (pred = top->bbPreds; pred; pred = pred->flNext)
3626             {
3627                 /* Is this a loop candidate? - We look for "back edges" */
3628
3629                 BasicBlock * bottom = pred->flBlock;
3630
3631                 /* is this a backward edge? (from BOTTOM to TOP) */
3632
3633                 if (top->bbNum > bottom->bbNum)
3634                     continue;
3635
3636                 /* 'top' also must have the BBF_LOOP_HEAD flag set */
3637
3638                 if (top->isLoopHead() == false)
3639                     continue;
3640
3641                 /* We only consider back-edges that are BBJ_COND or BBJ_ALWAYS for loops */
3642
3643                 if ((bottom->bbJumpKind != BBJ_COND)   &&
3644                     (bottom->bbJumpKind != BBJ_ALWAYS)    )
3645                     continue;
3646
3647                 /* the top block must be able to reach the bottom block */
3648                 if (!fgReachable(top, bottom))
3649                     continue;
3650
3651                 /* Found a new loop, record the longest backedge in foundBottom */
3652
3653                 if ((foundBottom == NULL) || (bottom->bbNum > foundBottom->bbNum))
3654                 {
3655                     foundBottom = bottom;
3656                 }
3657             }
3658
3659             if (foundBottom)
3660             {
3661                 loopNum++;
3662 #ifdef DEBUG
3663                 /* Mark the loop header as such */
3664                 assert(FitsIn<unsigned char>(loopNum));
3665                 top->bbLoopNum = (unsigned char) loopNum;
3666 #endif
3667
3668                 /* Mark all blocks between 'top' and 'bottom' */
3669                 
3670                 optMarkLoopBlocks(top, foundBottom, false);
3671             }
3672
3673             // We track at most 255 loops
3674             if (loopNum == 255)
3675             {
3676 #if COUNT_LOOPS
3677                 totalUnnatLoopOverflows++;
3678 #endif
3679                 break;
3680             }
3681         }
3682
3683 #if COUNT_LOOPS
3684         totalUnnatLoopCount += loopNum;
3685 #endif
3686
3687 #ifdef  DEBUG
3688         if  (verbose)
3689         {
3690             if  (loopNum > 0)
3691             {
3692                 printf("\nFound a total of %d loops.", loopNum);
3693                 printf("\nAfter loop weight marking:\n");
3694                 fgDispBasicBlocks();
3695                 printf("\n");
3696             }
3697         }
3698 #endif
3699         optLoopsMarked = true;
3700     }
3701 }
3702
3703 //------------------------------------------------------------------------
3704 // optDeriveLoopCloningConditions: Derive loop cloning conditions.
3705 //
3706 // Arguments:
3707 //     loopNum     -  the current loop index for which conditions are derived.
3708 //     context     -  data structure where all loop cloning info is kept.
3709 //
3710 // Return Value:
3711 //     "false" if conditions cannot be obtained. "true" otherwise.
3712 //     The cloning conditions are updated in the "conditions"[loopNum] field
3713 //     of the "context" parameter.
3714 //
3715 // Operation:
3716 //     Inspect the loop cloning optimization candidates and populate the conditions necessary
3717 //     for each optimization candidate. Checks if the loop stride is "> 0" if the loop
3718 //     condition is "less than". If the initializer is "var" init then adds condition
3719 //     "var >= 0", and if the loop is var limit then, "var >= 0" and "var <= a.len"
3720 //     are added to "context". These conditions are checked in the pre-header block
3721 //     and the cloning choice is made.
3722 //
3723 // Assumption:
3724 //      Callers should assume AND operation is used i.e., if all conditions are
3725 //      true, then take the fast path.
3726 //
3727 bool                Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext* context)
3728 {
3729     JITDUMP("------------------------------------------------------------\n");
3730     JITDUMP("Deriving cloning conditions for L%02u\n", loopNum);
3731
3732     LoopDsc* loop = &optLoopTable[loopNum];
3733     ExpandArrayStack<LcOptInfo*>* optInfos = context->GetLoopOptInfo(loopNum);
3734
3735     if (loop->lpTestOper() == GT_LT)
3736     {
3737         // Stride conditions
3738         if (loop->lpIterConst() <= 0)
3739         {
3740             JITDUMP("> Stride %d is invalid\n", loop->lpIterConst());
3741             return false;
3742         }
3743
3744         // Init conditions
3745         if (loop->lpFlags & LPFLG_CONST_INIT)
3746         {
3747             // Only allowing const init at this time.
3748             if (loop->lpConstInit < 0)
3749             {
3750                 JITDUMP("> Init %d is invalid\n", loop->lpConstInit);
3751                 return false;
3752             }
3753         }
3754         else if (loop->lpFlags & LPFLG_VAR_INIT)
3755         {
3756             // limitVar >= 0
3757             LC_Condition geZero(GT_GE,
3758                    LC_Expr(LC_Ident(loop->lpVarInit, LC_Ident::Var)),
3759                    LC_Expr(LC_Ident(0, LC_Ident::Const)));
3760             context->EnsureConditions(loopNum)->Push(geZero);
3761         }
3762         else
3763         {
3764             JITDUMP("> Not variable init\n");
3765             return false;
3766         }
3767
3768         // Limit Conditions
3769         LC_Ident ident;
3770         if (loop->lpFlags & LPFLG_CONST_LIMIT)
3771         {
3772             int limit = loop->lpConstLimit();
3773             if (limit < 0)
3774             {
3775                 JITDUMP("> limit %d is invalid\n", limit);
3776                 return false;
3777             }
3778             ident = LC_Ident(limit, LC_Ident::Const);
3779         }
3780         else if (loop->lpFlags & LPFLG_VAR_LIMIT)
3781         {
3782             unsigned limitLcl = loop->lpVarLimit();
3783             ident = LC_Ident(limitLcl, LC_Ident::Var);
3784
3785             LC_Condition geZero(GT_GE,
3786                    LC_Expr(ident),
3787                    LC_Expr(LC_Ident(0, LC_Ident::Const)));
3788
3789             context->EnsureConditions(loopNum)->Push(geZero);
3790         }
3791         else if (loop->lpFlags & LPFLG_ARRLEN_LIMIT)
3792         {
3793             ArrIndex* index = new (getAllocator()) ArrIndex(getAllocator());
3794             if (!loop->lpArrLenLimit(this, index))
3795             {
3796                 JITDUMP("> ArrLen not matching");
3797                 return false;
3798             }
3799             ident = LC_Ident(LC_Array(LC_Array::Jagged, index, LC_Array::ArrLen));
3800
3801             // Ensure that this array must be dereference-able, before executing the actual condition.
3802             LC_Array array(LC_Array::Jagged, index, LC_Array::None);
3803             context->EnsureDerefs(loopNum)->Push(array);
3804         }
3805         else
3806         {
3807             JITDUMP("> Undetected limit\n");
3808             return false;
3809         }
3810
3811         for (unsigned i = 0; i < optInfos->Size(); ++i)
3812         {
3813             LcOptInfo* optInfo = optInfos->GetRef(i);
3814             switch (optInfo->GetOptType())
3815             {
3816             case LcOptInfo::LcJaggedArray:
3817                 {
3818                     // limit <= arrLen
3819                     LcJaggedArrayOptInfo* arrIndexInfo = optInfo->AsLcJaggedArrayOptInfo();
3820                     LC_Array arrLen(LC_Array::Jagged, &arrIndexInfo->arrIndex, arrIndexInfo->dim, LC_Array::ArrLen);
3821                     LC_Ident arrLenIdent = LC_Ident(arrLen);
3822
3823                     LC_Condition cond(GT_LE, LC_Expr(ident), LC_Expr(arrLenIdent));
3824                     context->EnsureConditions(loopNum)->Push(cond);
3825
3826                     // Ensure that this array must be dereference-able, before executing the actual condition.
3827                     LC_Array array(LC_Array::Jagged, &arrIndexInfo->arrIndex, arrIndexInfo->dim, LC_Array::None);
3828                     context->EnsureDerefs(loopNum)->Push(array);
3829                 }
3830                 break;
3831             case LcOptInfo::LcMdArray:
3832                 {
3833                     // limit <= mdArrLen
3834                     LcMdArrayOptInfo* mdArrInfo = optInfo->AsLcMdArrayOptInfo();
3835                     LC_Condition cond(GT_LE,
3836                             LC_Expr(ident),
3837                             LC_Expr(LC_Ident(
3838                                     LC_Array(
3839                                         LC_Array::MdArray, mdArrInfo->GetArrIndexForDim(getAllocator()), mdArrInfo->dim, LC_Array::None)
3840                                     )));
3841                     context->EnsureConditions(loopNum)->Push(cond);
3842                 }
3843                 break;
3844
3845             default:
3846                 JITDUMP("Unknown opt\n");
3847                 return false;
3848             }
3849         }
3850         JITDUMP("Conditions: (");
3851         DBEXEC(verbose, context->PrintConditions(loopNum));
3852         JITDUMP(")\n");
3853         return true;
3854     }
3855     return false;
3856 }
3857
3858 //------------------------------------------------------------------------------------
3859 // optComputeDerefConditions: Derive loop cloning conditions for dereferencing arrays.
3860 //
3861 // Arguments:
3862 //     loopNum     -  the current loop index for which conditions are derived.
3863 //     context     -  data structure where all loop cloning info is kept.
3864 //
3865 // Return Value:
3866 //     "false" if conditions cannot be obtained. "true" otherwise.
3867 //     The deref conditions are updated in the "derefConditions"[loopNum] field
3868 //     of the "context" parameter.
3869 //
3870 // Definition of Deref Conditions:
3871 //     To be able to check for the loop cloning condition that (limitVar <= a.len)
3872 //     we should first be able to dereference "a". i.e., "a" is non-null.
3873 //
3874 //     Example:
3875 //
3876 //     for (i in 0..n)
3877 //       for (j in 0..n)
3878 //         for (k in 0..n)      // Inner most loop is being cloned. Cloning needs to check if
3879 //                              // (n <= a[i][j].len) and other safer conditions to take the fast path
3880 //           a[i][j][k] = 0;
3881 //
3882 //     Now, we want to deref a[i][j] to invoke length operator on it to perform the cloning fast path check.
3883 //     This involves deref of (a), (a[i]), (a[i][j]), therefore, the following should first
3884 //     be true to do the deref.
3885 //
3886 //     (a != null) && (i < a.len) && (a[i] != null) && (j < a[i].len) && (a[i][j] != null) --> (1)
3887 //
3888 //     Note the short circuiting AND. Implication: these conditions should be performed in separate
3889 //     blocks each of which will branch to slow path if the condition evaluates to false.
3890 //
3891 //     Now, imagine a situation where we have
3892 //      a[x][y][k] = 20 and a[i][j][k] = 0
3893 //     also in the inner most loop where x, y are parameters, then our conditions will have
3894 //     to include
3895 //     (x < a.len) &&
3896 //     (y < a[x].len)
3897 //     in addition to the above conditions (1) to get rid of bounds check on index 'k'
3898 //
3899 //     But these conditions can be checked together with conditions
3900 //     (i < a.len) without a need for a separate block. In summary, the conditions will be:
3901 //     
3902 //     (a != null) &&
3903 //     ((i < a.len) & (x < a.len)) &&      <-- Note the bitwise AND here.
3904 //     (a[i] != null & a[x] != null) &&    <-- Note the bitwise AND here.
3905 //     (j < a[i].len & y < a[x].len) &&    <-- Note the bitwise AND here.
3906 //     (a[i][j] != null & a[x][y] != null) <-- Note the bitwise AND here.
3907 //
3908 //     This naturally yields a tree style pattern, where the nodes of the tree are
3909 //     the array and indices respectively.
3910 //     
3911 //     Example:
3912 //         a => {
3913 //             i => {
3914 //                 j => {
3915 //                     k => {}
3916 //                 }
3917 //             },
3918 //             x => {
3919 //                 y => {
3920 //                     k => {}
3921 //                 }
3922 //             }
3923 //         }
3924 //
3925 //         Notice that the variables in the same levels can have their conditions combined in the
3926 //         same block with a bitwise AND. Whereas, the conditions in consecutive levels will be
3927 //         combined with a short-circuiting AND (i.e., different basic blocks).
3928 //
3929 //  Operation:
3930 //      Construct a tree of array indices and the array which will generate the optimal
3931 //      conditions for loop cloning.
3932 //
3933 //      a[i][j][k], b[i] and a[i][y][k] are the occurrences in the loop. Then, the tree should be:
3934 //
3935 //      a => {
3936 //          i => {
3937 //              j => {
3938 //                  k => {}
3939 //              },
3940 //              y => {
3941 //                  k => {}
3942 //              },
3943 //          }
3944 //      },
3945 //      b => {
3946 //          i => {}
3947 //      }
3948 //      In this method, we will construct such a tree by descending depth first into the array
3949 //      index operation and forming a tree structure as we encounter the array or the index variables.
3950 //
3951 //      This tree structure will then be used to generate conditions like below:
3952 //      (a != null) & (b != null) &&       // from the first level of the tree.
3953 //
3954 //      (i < a.len) & (i < b.len) &&       // from the second level of the tree. Levels can be combined.
3955 //      (a[i] != null) & (b[i] != null) && // from the second level of the tree.
3956 //      
3957 //      (j < a[i].len) & (y < a[i].len) &&       // from the third level.
3958 //      (a[i][j] != null) & (a[i][y] != null) && // from the third level.
3959 //
3960 //      and so on.
3961 //
3962 //
3963 bool Compiler::optComputeDerefConditions(unsigned loopNum, LoopCloneContext* context)
3964 {
3965     ExpandArrayStack<LC_Deref*> nodes(getAllocator());
3966     int maxRank = -1;
3967
3968     // Get the dereference-able arrays.
3969     ExpandArrayStack<LC_Array>* deref = context->EnsureDerefs(loopNum);
3970
3971     // For each array in the dereference list, construct a tree,
3972     // where the nodes are array and index variables and an edge 'u-v'
3973     // exists if a node 'v' indexes node 'u' directly as in u[v] or an edge
3974     // 'u-v-w' transitively if u[v][w] occurs.
3975     for (unsigned i = 0; i < deref->Size(); ++i)
3976     {
3977         LC_Array& array = (*deref)[i];
3978
3979         // First populate the array base variable.
3980         LC_Deref* node = LC_Deref::Find(&nodes, array.arrIndex->arrLcl);
3981         if (node == nullptr)
3982         {
3983             node = new (getAllocator()) LC_Deref(array, 0 /*level*/);
3984             nodes.Push(node);
3985         }
3986
3987         // For each dimension (level) for the array, populate the tree with the variable
3988         // from that dimension.
3989         unsigned rank = (unsigned) array.GetDimRank();
3990         for (unsigned i = 0; i < rank; ++i)
3991         {
3992             node->EnsureChildren(getAllocator());
3993             LC_Deref* tmp = node->Find(array.arrIndex->indLcls[i]);
3994             if (tmp == nullptr)
3995             {
3996                 tmp = new (getAllocator()) LC_Deref(array, node->level + 1);
3997                 node->children->Push(tmp);
3998             }
3999
4000             // Descend one level down.
4001             node = tmp;
4002         }
4003
4004         // Keep the maxRank of all array dereferences.
4005         maxRank = max((int) rank, maxRank);
4006     }
4007
4008 #ifdef DEBUG
4009     if (verbose)
4010     {
4011         for (unsigned i = 0; i < nodes.Size(); ++i)
4012         {
4013             if (i != 0) printf(",");
4014             nodes[i]->Print();
4015             printf("\n");
4016         }
4017     }
4018 #endif
4019
4020     if (maxRank == -1)
4021     {
4022         return false;
4023     }
4024
4025     // First level will always yield the null-check, since it is made of the array base variables.
4026     // All other levels (dimensions) will yield two conditions ex: (i < a.length && a[i] != null)
4027     // So add 1 after rank * 2.
4028     unsigned condBlocks = (unsigned) maxRank * 2 + 1;
4029
4030     // Heuristic to not create too many blocks;
4031     if (condBlocks > 4)
4032     {
4033         return false;
4034     }
4035
4036     // Derive conditions into an 'array of level x array of conditions' i.e., levelCond[levels][conds]
4037     ExpandArrayStack<ExpandArrayStack<LC_Condition>*>* levelCond = context->EnsureBlockConditions(loopNum, condBlocks);
4038     for (unsigned i = 0; i < nodes.Size(); ++i)
4039     {
4040         nodes[i]->DeriveLevelConditions(levelCond);
4041     }
4042
4043     DBEXEC(verbose, context->PrintBlockConditions(loopNum));
4044     return true;
4045 }
4046
4047 #ifdef DEBUG
4048 //----------------------------------------------------------------------------
4049 // optDebugLogLoopCloning:  Insert a call to jithelper that prints a message.
4050 //
4051 // Arguments:
4052 //      block        - the block in which the helper call needs to be inserted.
4053 //      insertBefore - the tree before which the helper call will be inserted.
4054 //
4055 void                Compiler::optDebugLogLoopCloning(BasicBlock* block, GenTreePtr insertBefore)
4056 {
4057     if (JitConfig.JitDebugLogLoopCloning() == 0)
4058     {
4059         return;
4060     }
4061     GenTreePtr logCall = gtNewHelperCallNode(CORINFO_HELP_DEBUG_LOG_LOOP_CLONING, TYP_VOID);
4062     GenTreePtr stmt = fgNewStmtFromTree(logCall);
4063     fgInsertStmtBefore(block, insertBefore, stmt);
4064     fgMorphBlockStmt(block, stmt DEBUGARG("Debug log loop cloning"));
4065 }
4066 #endif
4067
4068 //------------------------------------------------------------------------
4069 // optPerformStaticOptimizations: Perform the optimizations for the optimization
4070 //      candidates gathered during the cloning phase.
4071 //
4072 // Arguments:
4073 //     loopNum     -  the current loop index for which the optimizations are performed.
4074 //     context     -  data structure where all loop cloning info is kept.
4075 //     dynamicPath -  If true, the optimization is performed in the fast path among the
4076 //                    cloned loops. If false, it means this is the only path (i.e.,
4077 //                    there is no slow path.)
4078 //
4079 // Operation:
4080 //      Perform the optimizations on the fast path i.e., the path in which the 
4081 //      optimization candidates were collected at the time of identifying them.
4082 //      The candidates store all the information necessary (the tree/stmt/block
4083 //      they are from) to perform the optimization.
4084 //
4085 // Assumption:
4086 //      The unoptimized path is either already cloned when this method is called or
4087 //      there is no unoptimized path (got eliminated statically.) So this method
4088 //      performs the optimizations assuming that the path in which the candidates
4089 //      were collected is the fast path in which the optimizations will be performed.
4090 //
4091 void                Compiler::optPerformStaticOptimizations(unsigned loopNum, LoopCloneContext* context DEBUGARG(bool dynamicPath))
4092 {
4093     ExpandArrayStack<LcOptInfo*>* optInfos = context->GetLoopOptInfo(loopNum);
4094     for (unsigned i = 0; i < optInfos->Size(); ++i)
4095     {
4096         LcOptInfo* optInfo = optInfos->GetRef(i);
4097         switch (optInfo->GetOptType())
4098         {
4099         case LcOptInfo::LcJaggedArray:
4100             {
4101                 LcJaggedArrayOptInfo* arrIndexInfo = optInfo->AsLcJaggedArrayOptInfo();
4102                 compCurBB = arrIndexInfo->arrIndex.useBlock;
4103                 optRemoveRangeCheck(
4104                     arrIndexInfo->arrIndex.bndsChks[arrIndexInfo->dim],
4105                     arrIndexInfo->stmt, true, GTF_ASG, true);
4106                 DBEXEC(dynamicPath, optDebugLogLoopCloning(arrIndexInfo->arrIndex.useBlock, arrIndexInfo->stmt));
4107             }
4108             break;
4109         case LcOptInfo::LcMdArray:
4110             // TODO-CQ: CLONE: Implement.
4111             break;
4112         default:
4113             break;
4114         }
4115     }
4116 }
4117
4118
4119 //----------------------------------------------------------------------------
4120 //  optCanCloneLoops: Use the environment flag to determine whether loop
4121 //      cloning is allowed to be performed.
4122 //
4123 //  Return Value:
4124 //      Returns true in debug builds if COMPlus_JitCloneLoops flag is set.
4125 //      Disabled for retail for now.
4126 //
4127 bool                Compiler::optCanCloneLoops()
4128 {
4129     // Enabled for retail builds now.
4130     unsigned cloneLoopsFlag = 1;
4131 #ifdef DEBUG
4132     cloneLoopsFlag = JitConfig.JitCloneLoops();
4133 #endif
4134     return (cloneLoopsFlag != 0);
4135 }
4136
4137
4138 //----------------------------------------------------------------------------
4139 //  optIsLoopClonable: Determine whether this loop can be cloned.
4140 //
4141 //  Arguments:
4142 //      loopInd     loop index which needs to be checked if it can be cloned.
4143 //
4144 //  Return Value:
4145 //      Returns true if the loop can be cloned. If it returns false
4146 //      prints a message in debug as why the loop can't be cloned.
4147 //
4148 bool                Compiler::optIsLoopClonable(unsigned loopInd)
4149 {
4150     // First, for now, make sure the loop doesn't have any embedded exception handling -- I don't want to tackle
4151     // inserting new EH regions in the exception table yet.
4152     BasicBlock* stopAt = optLoopTable[loopInd].lpBottom->bbNext;
4153     unsigned loopRetCount = 0;
4154     for (BasicBlock* blk = optLoopTable[loopInd].lpFirst; blk != stopAt; blk = blk->bbNext)
4155     {
4156         if (blk->bbJumpKind == BBJ_RETURN) loopRetCount++;
4157         if (bbIsTryBeg(blk)) 
4158         {
4159             JITDUMP("Loop cloning: rejecting loop %d in %s, because it has a try begin.\n", 
4160                     loopInd, info.compFullName);
4161             return false;
4162         }
4163     }
4164
4165     // Is the entry block a handler or filter start?  If so, then if we cloned, we could create a jump
4166     // into the middle of a handler (to go to the cloned copy.)  Reject.
4167     if (bbIsHandlerBeg(optLoopTable[loopInd].lpEntry))
4168     {
4169         JITDUMP("Loop cloning: rejecting loop because entry block is a handler start.\n");
4170         return false;
4171     }
4172
4173     // If the head and entry are in different EH regions, reject.
4174     if (!BasicBlock::sameEHRegion(optLoopTable[loopInd].lpHead, optLoopTable[loopInd].lpEntry))
4175     {
4176         JITDUMP("Loop cloning: rejecting loop because head and entry blocks are in different EH regions.\n");
4177         return false;
4178     }
4179
4180     // Is the first block after the last block of the loop a handler or filter start?
4181     // Usually, we create a dummy block after the orginal loop, to skip over the loop clone
4182     // and go to where the original loop did.  That raises problems when we don't actually go to
4183     // that block; this is one of those cases.  This could be fixed fairly easily; for example,
4184     // we could add a dummy nop block after the (cloned) loop bottom, in the same handler scope as the
4185     // loop.  This is just a corner to cut to get this working faster.
4186     BasicBlock* bbAfterLoop = optLoopTable[loopInd].lpBottom->bbNext;
4187     if (bbAfterLoop != nullptr && bbIsHandlerBeg(bbAfterLoop))
4188     {
4189         JITDUMP("Loop cloning: rejecting loop because next block after bottom is a handler start.\n");
4190         return false;
4191     }
4192
4193     // We've previously made a decision whether to have separate return epilogs, or branch to one.
4194     // There's a GCInfo limitation in the x86 case, so that there can be no more than 4 separate epilogs.
4195     // (I thought this was x86-specific, but it's not if-d.  On other architectures, the decision should be made as a
4196     // heuristic tradeoff; perhaps we're just choosing to live with 4 as the limit.)
4197     if (fgReturnCount + loopRetCount > 4)
4198     {
4199         JITDUMP("Loop cloning: rejecting loop because it has %d returns; if added to previously-existing %d returns, would exceed the limit of 4.\n", loopRetCount, fgReturnCount);
4200         return false;
4201     }
4202
4203     // Otherwise, we're going to add those return blocks.
4204     fgReturnCount += loopRetCount;
4205
4206     return true;
4207 }
4208
4209 /*****************************************************************************
4210  *
4211  *  Identify loop cloning opportunities, derive loop cloning conditions,
4212  *  perform loop cloning, use the derived conditions to choose which
4213  *  path to take.
4214  */
4215 void                Compiler::optCloneLoops()
4216 {
4217     JITDUMP("\n*************** In optCloneLoops()\n");
4218     if (optLoopCount == 0 || !optCanCloneLoops())
4219     {
4220         return;
4221     }
4222
4223 #ifdef DEBUG
4224     if (verbose)
4225     {
4226         printf("Blocks/Trees at start of phase\n");
4227         fgDispBasicBlocks(true);
4228     }
4229 #endif
4230
4231     LoopCloneContext context(optLoopCount, getAllocator());
4232
4233     // Obtain array optimization candidates in the context.
4234     optObtainLoopCloningOpts(&context);
4235
4236     // For each loop, derive cloning conditions for the optimization candidates.
4237     for (unsigned i = 0; i < optLoopCount; ++i)
4238     {
4239         ExpandArrayStack<LcOptInfo*>* optInfos = context.GetLoopOptInfo(i);
4240         if (optInfos == nullptr)
4241         {
4242             continue;
4243         }
4244
4245         if (!optDeriveLoopCloningConditions(i, &context) || !optComputeDerefConditions(i, &context))
4246         {
4247             JITDUMP("> Conditions could not be obtained\n");
4248             context.CancelLoopOptInfo(i);
4249         }
4250         else
4251         {
4252             bool allTrue = false;
4253             bool anyFalse = false;
4254             context.EvaluateConditions(i, &allTrue, &anyFalse DEBUGARG(verbose));
4255             if (anyFalse)
4256             {
4257                 context.CancelLoopOptInfo(i);
4258             }
4259             if (allTrue)
4260             {
4261                 // Perform static optimizations on the fast path since we always
4262                 // have to take the cloned path.
4263                 optPerformStaticOptimizations(i, &context DEBUGARG(false));
4264
4265                 // No need to clone.
4266                 context.CancelLoopOptInfo(i);
4267             }
4268         }
4269     }
4270
4271
4272 #if 0
4273     // The code in this #if has been useful in debugging loop cloning issues, by
4274     // enabling selective enablement of the loop cloning optimization according to
4275     // method hash.
4276 #ifdef DEBUG
4277     unsigned methHash = info.compMethodHash();
4278     char* lostr = getenv("loopclonehashlo");
4279     unsigned methHashLo = 0;
4280     if (lostr != NULL) 
4281     {
4282         sscanf_s(lostr, "%x", &methHashLo);
4283         // methHashLo = (unsigned(atoi(lostr)) << 2);  // So we don't have to use negative numbers.
4284     }
4285     char* histr = getenv("loopclonehashhi");
4286     unsigned methHashHi = UINT32_MAX;
4287     if (histr != NULL) 
4288     {
4289         sscanf_s(histr, "%x", &methHashHi);
4290         // methHashHi = (unsigned(atoi(histr)) << 2);  // So we don't have to use negative numbers.
4291     }
4292     if (methHash < methHashLo || methHash > methHashHi)
4293         return;
4294 #endif
4295 #endif
4296
4297     for (unsigned i = 0; i < optLoopCount; ++i)
4298     {
4299         if (context.GetLoopOptInfo(i) != nullptr)
4300         {
4301             optLoopsCloned++;
4302             context.OptimizeConditions(i DEBUGARG(verbose));
4303             context.OptimizeBlockConditions(i DEBUGARG(verbose));
4304             optCloneLoop(i, &context);
4305         }
4306     }
4307
4308 #ifdef DEBUG
4309     if (verbose)
4310     {
4311         printf("\nAfter loop cloning:\n");
4312         fgDispBasicBlocks(/*dumpTrees*/true);
4313     }
4314 #endif
4315 }
4316
4317 void                Compiler::optCloneLoop(unsigned loopInd, LoopCloneContext* context)
4318 {
4319     assert(loopInd < optLoopCount);
4320
4321     JITDUMP("\nCloning loop %d: [h: %d, f: %d, t: %d, e: %d, b: %d].\n",
4322             loopInd,
4323             optLoopTable[loopInd].lpHead->bbNum,
4324             optLoopTable[loopInd].lpFirst->bbNum,
4325             optLoopTable[loopInd].lpTop->bbNum,
4326             optLoopTable[loopInd].lpEntry->bbNum,
4327             optLoopTable[loopInd].lpBottom->bbNum);
4328
4329     // Determine the depth of the loop, so we can properly weight blocks added (outside the cloned loop blocks).
4330     unsigned depth = optLoopDepth(loopInd);
4331     unsigned ambientWeight = 1;
4332     for (unsigned j = 0; j < depth; j++)
4333     {
4334         unsigned lastWeight = ambientWeight;
4335         ambientWeight *= BB_LOOP_WEIGHT;
4336         // If the multiplication overflowed, stick at max.
4337         // (Strictly speaking, a multiplication could overflow and still have a result
4338         // that is >= lastWeight...but if so, the original weight must be pretty large,
4339         // and it got bigger, so that's OK.)
4340         if (ambientWeight < lastWeight)
4341         {
4342             ambientWeight = BB_MAX_WEIGHT;
4343             break;
4344         }
4345     }
4346
4347     // If we're in a non-natural loop, the ambient weight might be higher than we computed above.
4348     // Be safe by taking the max with the head block's weight.
4349     ambientWeight = max(ambientWeight, optLoopTable[loopInd].lpHead->bbWeight);
4350
4351     // This is the containing loop, if any -- to label any blocks we create that are outside
4352     // the loop being cloned.
4353     unsigned char ambientLoop = optLoopTable[loopInd].lpParent;
4354
4355     // First, make sure that the loop has a unique header block, creating an empty one if necessary.
4356     optEnsureUniqueHead(loopInd, ambientWeight);
4357
4358     // We're going to make
4359
4360     // H --> E
4361     // F  
4362     // T  
4363     // E
4364     // B  ?-> T  
4365     // X
4366     //
4367     //   become
4368     //
4369     // H ?-> E2
4370     // H2--> E    (Optional; if E == T == F, let H fall through to F/T/E)
4371     // F  
4372     // T  
4373     // E
4374     // B  ?-> T  
4375     // X2--> X
4376     // F2
4377     // T2
4378     // E2
4379     // B2 ?-> T2
4380     // X
4381
4382     BasicBlock* h = optLoopTable[loopInd].lpHead;
4383     if (h->bbJumpKind != BBJ_NONE && h->bbJumpKind != BBJ_ALWAYS)
4384     {
4385         // Make a new block to be the unique entry to the loop.
4386         assert(h->bbJumpKind == BBJ_COND && h->bbNext == optLoopTable[loopInd].lpEntry);
4387         BasicBlock* newH = fgNewBBafter(BBJ_NONE,
4388                                         h,
4389                                         /*extendRegion*/true);
4390         newH->bbWeight = (newH->isRunRarely() ? 0 : ambientWeight);
4391         BlockSetOps::Assign(this, newH->bbReach, h->bbReach);
4392         // This is in the scope of a surrounding loop, if one exists -- the parent of the loop we're cloning.
4393         newH->bbNatLoopNum = ambientLoop;
4394         h = newH;
4395         optUpdateLoopHead(loopInd, optLoopTable[loopInd].lpHead, h);
4396     }
4397
4398     // First, make X2 after B, if necessary.  (Not necessary if b is a BBJ_ALWAYS.)
4399     // "newPred" will be the predecessor of the blocks of the cloned loop.
4400     BasicBlock* b = optLoopTable[loopInd].lpBottom;
4401     BasicBlock* newPred = b;
4402     if (b->bbJumpKind != BBJ_ALWAYS)
4403     {
4404         BasicBlock* x = b->bbNext;
4405         if (x != nullptr)
4406         {
4407             BasicBlock* x2 = fgNewBBafter(BBJ_ALWAYS, b, /*extendRegion*/true);
4408             x2->bbWeight = (x2->isRunRarely() ? 0 : ambientWeight);
4409
4410             // This is in the scope of a surrounding loop, if one exists -- the parent of the loop we're cloning.
4411             x2->bbNatLoopNum = ambientLoop;
4412
4413             x2->bbJumpDest = x;
4414             BlockSetOps::Assign(this, x2->bbReach, h->bbReach);
4415             newPred = x2;
4416         }
4417     }
4418
4419     // Now we'll make "h2", after "h" to go to "e" -- unless the loop is a do-while,
4420     // so that "h" already falls through to "e" (e == t == f).
4421     BasicBlock* h2 = nullptr;
4422     if (optLoopTable[loopInd].lpHead->bbNext != optLoopTable[loopInd].lpEntry)
4423     {
4424         BasicBlock* h2 = fgNewBBafter(BBJ_ALWAYS,
4425                                       optLoopTable[loopInd].lpHead,
4426                                       /*extendRegion*/true);
4427         h2->bbWeight = (h2->isRunRarely() ? 0 : ambientWeight);
4428
4429         // This is in the scope of a surrounding loop, if one exists -- the parent of the loop we're cloning.
4430         h2->bbNatLoopNum = ambientLoop;
4431
4432         h2->bbJumpDest = optLoopTable[loopInd].lpEntry;
4433         optUpdateLoopHead(loopInd,optLoopTable[loopInd].lpHead, h2);
4434     }
4435
4436     // Now we'll clone the blocks of the loop body.
4437     BasicBlock* newFirst = nullptr;
4438     BasicBlock* newBot = nullptr;
4439
4440     BlockToBlockMap* blockMap = new (getAllocator()) BlockToBlockMap(getAllocator());
4441     for (BasicBlock* blk = optLoopTable[loopInd].lpFirst; 
4442          blk != optLoopTable[loopInd].lpBottom->bbNext; 
4443          blk = blk->bbNext)
4444     {
4445         BasicBlock* newBlk = fgNewBBafter(blk->bbJumpKind,
4446                                           newPred,
4447                                           /*extendRegion*/true);
4448
4449         BasicBlock::CloneBlockState(this, newBlk, blk);
4450         // TODO-Cleanup: The above clones the bbNatLoopNum, which is incorrect.  Eventually, we should probably insert
4451         // the cloned loop in the loop table.  For now, however, we'll just make these blocks be part of the surrounding
4452         // loop, if one exists -- the parent of the loop we're cloning.
4453         newBlk->bbNatLoopNum = optLoopTable[loopInd].lpParent;
4454
4455         if (newFirst == nullptr) newFirst = newBlk;
4456         newBot = newBlk; // Continually overwrite to make sure we get the last one.
4457         newPred = newBlk;
4458         blockMap->Set(blk, newBlk);
4459     }
4460
4461     // Perform the static optimizations on the fast path.
4462     optPerformStaticOptimizations(loopInd, context DEBUGARG(true));
4463
4464     // Now go through the new blocks, remapping their jump targets within the loop.
4465     for (BasicBlock* blk = optLoopTable[loopInd].lpFirst; 
4466          blk != optLoopTable[loopInd].lpBottom->bbNext; 
4467          blk = blk->bbNext)
4468     {
4469
4470         BasicBlock* newblk = nullptr;
4471         bool b = blockMap->Lookup(blk, &newblk);
4472         assert(b && newblk != nullptr);
4473
4474         assert(blk->bbJumpKind == newblk->bbJumpKind);
4475
4476         // First copy the jump destination(s) from "blk".
4477         optCopyBlkDest(blk, newblk);
4478         
4479         // Now redirect the new block according to "blockMap".
4480         optRedirectBlock(newblk, blockMap);
4481     }
4482
4483     assert((h->bbJumpKind == BBJ_NONE && (h->bbNext == h2 || h->bbNext == optLoopTable[loopInd].lpEntry))
4484            || (h->bbJumpKind == BBJ_ALWAYS));
4485
4486     // If all the conditions are true, go to E2.
4487     BasicBlock* e2 = nullptr;
4488     bool foundIt = blockMap->Lookup(optLoopTable[loopInd].lpEntry, &e2);
4489
4490     h->bbJumpKind = BBJ_COND;
4491
4492     // We will create the following structure
4493     //
4494     // cond0 (in h)  -?> cond1
4495     // slow          --> e2 (slow) always
4496     // !cond1        -?> slow
4497     // !cond2        -?> slow
4498     // ...
4499     // !condn        -?> slow
4500     // h2/entry (fast)
4501     //
4502     // We should always have block conditions, at the minimum, the array should be deref-able
4503     assert(context->HasBlockConditions(loopInd));
4504
4505     // Create a unique header for the slow path.
4506     BasicBlock* slowHead = fgNewBBafter(BBJ_ALWAYS, h, true);
4507     slowHead->bbWeight = (h->isRunRarely() ? 0 : ambientWeight);
4508     slowHead->bbNatLoopNum = ambientLoop;
4509     slowHead->bbJumpDest = e2;
4510
4511     BasicBlock* condLast = optInsertLoopChoiceConditions(context, loopInd, h, slowHead);
4512     condLast->bbJumpDest = slowHead;
4513
4514     // If h2 is present it is already the head or replace 'h' by 'condLast'.
4515     if (h2 == nullptr)
4516     {
4517         optUpdateLoopHead(loopInd, optLoopTable[loopInd].lpHead, condLast);
4518     }
4519     assert(foundIt && e2 != NULL);
4520
4521     fgUpdateChangedFlowGraph();
4522 }
4523
4524 //--------------------------------------------------------------------------------------------------
4525 // optInsertLoopChoiceConditions - Insert the loop conditions for a loop between loop head and entry
4526 //
4527 // Arguments:
4528 //      context     loop cloning context variable
4529 //      loopNum     the loop index
4530 //      head        loop head for "loopNum"
4531 //      slowHead    the slow path loop head
4532 //
4533 // Return Values:
4534 //      None.
4535 //
4536 // Operation:
4537 //      Create the following structure.
4538 //
4539 //      Note below that the cond0 is inverted in head i.e., if true jump to cond1. This is because
4540 //      condn cannot jtrue to loop head h2. It has to be from a direct pred block.
4541 //
4542 //      cond0 (in h)  -?> cond1
4543 //      slowHead      --> e2 (slowHead) always
4544 //      !cond1        -?> slowHead
4545 //      !cond2        -?> slowHead
4546 //      ...
4547 //      !condn        -?> slowHead
4548 //      h2/entry (fast)
4549 //
4550 //      Insert condition 0 in 'h' and create other condition blocks and insert conditions in them.
4551 //
4552 BasicBlock* Compiler::optInsertLoopChoiceConditions(LoopCloneContext* context, unsigned loopNum, BasicBlock* head, BasicBlock* slowHead)
4553 {
4554     JITDUMP("Inserting loop cloning conditions\n");
4555     assert(context->HasBlockConditions(loopNum));
4556
4557     BasicBlock* curCond = head;
4558     ExpandArrayStack<ExpandArrayStack<LC_Condition>*>* levelCond = context->GetBlockConditions(loopNum);
4559     for (unsigned i = 0; i < levelCond->Size(); ++i)
4560     {
4561         bool isHeaderBlock = (curCond == head);
4562
4563         // Flip the condition if header block.
4564         context->CondToStmtInBlock(this, *((*levelCond)[i]), curCond, isHeaderBlock);
4565
4566         // Create each condition block ensuring wiring between them.
4567         BasicBlock* tmp = fgNewBBafter(BBJ_COND, isHeaderBlock ? slowHead : curCond, true);
4568         curCond->bbJumpDest = isHeaderBlock ? tmp : slowHead;
4569         curCond = tmp;
4570
4571         curCond->inheritWeight(head);
4572         curCond->bbNatLoopNum = head->bbNatLoopNum;
4573         JITDUMP("Created new block %02d for new level\n", curCond->bbNum);
4574     }
4575
4576     // Finally insert cloning conditions after all deref conditions have been inserted.
4577     context->CondToStmtInBlock(this, *(context->GetConditions(loopNum)), curCond, false);
4578     return curCond;
4579 }
4580
4581 void Compiler::optEnsureUniqueHead(unsigned loopInd, unsigned ambientWeight)
4582 {
4583     BasicBlock* h = optLoopTable[loopInd].lpHead;
4584     BasicBlock* t = optLoopTable[loopInd].lpTop;
4585     BasicBlock* e = optLoopTable[loopInd].lpEntry;
4586     BasicBlock* b = optLoopTable[loopInd].lpBottom;
4587
4588     // If "h" dominates the entry block, then it is the unique header.
4589     if (fgDominate(h, e)) return;
4590
4591     // Otherwise, create a new empty header block, make it the pred of the entry block,
4592     // and redirect the preds of the entry block to go to this.
4593
4594     BasicBlock* beforeTop = t->bbPrev;
4595     // Make sure that the new block is in the same region as the loop.
4596     // (We will only create loops that are entirely within a region.)
4597     BasicBlock * h2 = fgNewBBafter(BBJ_ALWAYS, beforeTop, true);
4598     // This is in the containing loop.
4599     h2->bbNatLoopNum = optLoopTable[loopInd].lpParent;
4600     h2->bbWeight = (h2->isRunRarely() ? 0 : ambientWeight);
4601
4602     // We don't care where it was put; splice it between beforeTop and top.
4603     if (beforeTop->bbNext != h2)
4604     {
4605         h2->bbPrev->setNext(h2->bbNext);  // Splice h2 out.
4606         beforeTop->setNext(h2);           // Splice h2 in, between beforeTop and t.
4607         h2->setNext(t);
4608     }
4609
4610     if (h2->bbNext != e)
4611     {
4612         h2->bbJumpKind = BBJ_ALWAYS;
4613         h2->bbJumpDest = e;
4614     }
4615     BlockSetOps::Assign(this, h2->bbReach, e->bbReach);
4616
4617     // Redirect paths from preds of "e" to go to "h2" instead of "e".
4618     BlockToBlockMap* blockMap = new (getAllocator()) BlockToBlockMap(getAllocator());
4619     blockMap->Set(e, h2);
4620
4621     for (flowList* predEntry = e->bbPreds; predEntry; predEntry = predEntry->flNext)
4622     {
4623         BasicBlock* predBlock = predEntry->flBlock;
4624
4625         // Skip if predBlock is in the loop.
4626         if (t->bbNum <= predBlock->bbNum && predBlock->bbNum <= b->bbNum) continue;
4627         optRedirectBlock(predBlock, blockMap);
4628     }
4629
4630     optUpdateLoopHead(loopInd, optLoopTable[loopInd].lpHead, h2); 
4631 }
4632
4633 /*****************************************************************************
4634  *
4635  *  Determine the kind of interference for the call.
4636  */
4637
4638 /* static */ inline
4639 Compiler::callInterf    Compiler::optCallInterf(GenTreePtr call)
4640 {
4641     assert(call->gtOper == GT_CALL);
4642
4643     // if not a helper, kills everything
4644     if  (call->gtCall.gtCallType != CT_HELPER)
4645         return CALLINT_ALL;
4646
4647     // setfield and array address store kill all indirections
4648     switch (eeGetHelperNum(call->gtCall.gtCallMethHnd))
4649     {
4650     case CORINFO_HELP_ASSIGN_REF:            // Not strictly needed as we don't make a GT_CALL with this
4651     case CORINFO_HELP_CHECKED_ASSIGN_REF:    // Not strictly needed as we don't make a GT_CALL with this
4652     case CORINFO_HELP_ASSIGN_BYREF:          // Not strictly needed as we don't make a GT_CALL with this
4653     case CORINFO_HELP_SETFIELDOBJ:
4654     case CORINFO_HELP_ARRADDR_ST:
4655
4656         return CALLINT_REF_INDIRS;
4657
4658     case CORINFO_HELP_SETFIELDFLOAT:
4659     case CORINFO_HELP_SETFIELDDOUBLE:
4660     case CORINFO_HELP_SETFIELD8:
4661     case CORINFO_HELP_SETFIELD16:
4662     case CORINFO_HELP_SETFIELD32:
4663     case CORINFO_HELP_SETFIELD64:
4664
4665         return CALLINT_SCL_INDIRS;
4666
4667     case CORINFO_HELP_ASSIGN_STRUCT:         // Not strictly needed as we don't use this in Jit32
4668     case CORINFO_HELP_MEMSET:                // Not strictly needed as we don't make a GT_CALL with this
4669     case CORINFO_HELP_MEMCPY:                // Not strictly needed as we don't make a GT_CALL with this
4670     case CORINFO_HELP_SETFIELDSTRUCT:
4671
4672         return CALLINT_ALL_INDIRS;
4673
4674     default:
4675       break;
4676     }
4677
4678     // other helpers kill nothing
4679     return CALLINT_NONE;
4680 }
4681
4682 /*****************************************************************************
4683  *
4684  *  See if the given tree can be computed in the given precision (which must
4685  *  be smaller than the type of the tree for this to make sense). If 'doit'
4686  *  is false, we merely check to see whether narrowing is possible; if we
4687  *  get called with 'doit' being true, we actually perform the narrowing.
4688  */
4689
4690 bool                Compiler::optNarrowTree(GenTreePtr     tree,
4691                                             var_types      srct,
4692                                             var_types      dstt,
4693                                             ValueNumPair   vnpNarrow,
4694                                             bool           doit)
4695 {
4696     genTreeOps      oper;
4697     unsigned        kind;
4698
4699     noway_assert(tree);
4700     noway_assert(genActualType(tree->gtType) == genActualType(srct));
4701
4702     /* Assume we're only handling integer types */
4703     noway_assert(varTypeIsIntegral(srct));
4704     noway_assert(varTypeIsIntegral(dstt));
4705
4706     unsigned srcSize      = genTypeSize(srct);
4707     unsigned dstSize      = genTypeSize(dstt);
4708
4709     /* dstt must be smaller than srct to narrow */
4710     if (dstSize >= srcSize)
4711         return false;
4712
4713     /* Figure out what kind of a node we have */
4714     oper = tree->OperGet();
4715     kind = tree->OperKind();
4716
4717     if  (kind & GTK_ASGOP)
4718     {
4719         noway_assert(doit == false);
4720         return  false;
4721     }
4722
4723     ValueNumPair NoVNPair = ValueNumPair();
4724
4725     if  (kind & GTK_LEAF)
4726     {
4727         switch (oper)
4728         {
4729         /* Constants can usually be narrowed by changing their value */
4730         CLANG_FORMAT_COMMENT_ANCHOR;
4731
4732 #ifndef _TARGET_64BIT_
4733             __int64  lval;  
4734             __int64  lmask;
4735
4736         case GT_CNS_LNG:
4737             lval  = tree->gtIntConCommon.LngValue();
4738             lmask = 0;
4739
4740             switch (dstt)
4741             {
4742                 case TYP_BYTE : lmask = 0x0000007F; break;
4743                 case TYP_BOOL :
4744                 case TYP_UBYTE: lmask = 0x000000FF; break;
4745                 case TYP_SHORT: lmask = 0x00007FFF; break;
4746                 case TYP_CHAR : lmask = 0x0000FFFF; break;
4747                 case TYP_INT  : lmask = 0x7FFFFFFF; break;
4748                 case TYP_UINT : lmask = 0xFFFFFFFF; break;
4749
4750                 default:        return false; 
4751             }
4752
4753             if  ((lval & lmask) != lval)
4754                 return false;
4755
4756             if  (doit)
4757             {
4758                 tree->ChangeOperConst     (GT_CNS_INT);
4759                 tree->gtType             = TYP_INT;
4760                 tree->gtIntCon.gtIconVal = (int) lval;
4761                 if (vnStore != nullptr)
4762                 {
4763                     fgValueNumberTreeConst(tree);
4764                 }
4765             }
4766
4767             return  true;
4768 #endif
4769
4770         case GT_CNS_INT:
4771
4772             ssize_t  ival;  ival  = tree->gtIntCon.gtIconVal;
4773             ssize_t  imask; imask = 0;
4774
4775             switch (dstt)
4776             {
4777                 case TYP_BYTE : imask = 0x0000007F; break;
4778                 case TYP_BOOL :
4779                 case TYP_UBYTE: imask = 0x000000FF; break;
4780                 case TYP_SHORT: imask = 0x00007FFF; break;
4781                 case TYP_CHAR : imask = 0x0000FFFF; break;
4782 #ifdef _TARGET_64BIT_
4783                 case TYP_INT  : imask = 0x7FFFFFFF; break;
4784                 case TYP_UINT : imask = 0xFFFFFFFF; break;
4785 #endif // _TARGET_64BIT_
4786                 default:        return false; 
4787             }
4788
4789             if  ((ival & imask) != ival)
4790                 return false;
4791
4792 #ifdef _TARGET_64BIT_
4793             if  (doit)
4794             {
4795                 tree->gtType = TYP_INT;
4796                 tree->gtIntCon.gtIconVal = (int) ival;
4797                 if (vnStore != nullptr)
4798                 {
4799                     fgValueNumberTreeConst(tree);
4800                 }
4801             }
4802 #endif // _TARGET_64BIT_
4803
4804             return  true;
4805
4806         /* Operands that are in memory can usually be narrowed 
4807            simply by changing their gtType */
4808
4809         case GT_LCL_VAR:
4810             /* We only allow narrowing long -> int for a GT_LCL_VAR */
4811             if (dstSize == sizeof(int))
4812                 goto NARROW_IND;
4813             break;
4814
4815         case GT_CLS_VAR:
4816         case GT_LCL_FLD:
4817             goto NARROW_IND;
4818         default:
4819         break;
4820         }
4821
4822         noway_assert(doit == false);
4823         return  false;
4824
4825     }
4826
4827     if (kind & (GTK_BINOP|GTK_UNOP))
4828     {
4829         GenTreePtr      op1; op1 = tree->gtOp.gtOp1;
4830         GenTreePtr      op2; op2 = tree->gtOp.gtOp2;
4831
4832         switch (tree->gtOper)
4833         {
4834         case GT_AND:
4835             noway_assert(genActualType(tree->gtType) == genActualType(op2->gtType));
4836
4837             // Is op2 a small constant than can be narrowed into dstt?
4838             // if so the result of the GT_AND will also fit into 'dstt' and can be narrowed
4839             if ((op2->gtOper == GT_CNS_INT)  &&  optNarrowTree(op2, srct, dstt, NoVNPair, false))
4840             {               
4841                 // We will change the type of the tree and narrow op2
4842                 //
4843                 if  (doit)
4844                 {
4845                     tree->gtType = genActualType(dstt);
4846                     tree->SetVNs(vnpNarrow);
4847
4848                     optNarrowTree(op2, srct, dstt, NoVNPair, true);
4849                     // We may also need to cast away the upper bits of op1
4850                     if (srcSize == 8) 
4851                     {
4852                         assert(tree->gtType == TYP_INT);
4853                         op1 = gtNewCastNode(TYP_INT, op1, TYP_INT);
4854 #ifdef DEBUG
4855                         op1->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED;
4856 #endif
4857                         tree->gtOp.gtOp1 = op1;
4858                     }
4859                 }
4860                 return true;
4861             }
4862             
4863             goto COMMON_BINOP;
4864
4865         case GT_ADD:
4866         case GT_MUL:
4867
4868             if (tree->gtOverflow() || varTypeIsSmall(dstt))
4869             {
4870                 noway_assert(doit == false);
4871                 return false;
4872             }
4873             __fallthrough;
4874
4875         case GT_OR:
4876         case GT_XOR:
4877 COMMON_BINOP:
4878             noway_assert(genActualType(tree->gtType) == genActualType(op1->gtType));
4879             noway_assert(genActualType(tree->gtType) == genActualType(op2->gtType));
4880
4881             if (gtIsActiveCSE_Candidate(op1)          ||
4882                 gtIsActiveCSE_Candidate(op2)          ||
4883                 !optNarrowTree(op1, srct, dstt, NoVNPair, doit) ||
4884                 !optNarrowTree(op2, srct, dstt, NoVNPair, doit)   )
4885             {
4886                 noway_assert(doit == false);
4887                 return  false;
4888             }
4889
4890             /* Simply change the type of the tree */
4891
4892             if  (doit)
4893             {
4894                 if  (tree->gtOper == GT_MUL && (tree->gtFlags & GTF_MUL_64RSLT))
4895                     tree->gtFlags &= ~GTF_MUL_64RSLT;
4896
4897                 tree->gtType = genActualType(dstt);
4898                 tree->SetVNs(vnpNarrow);
4899             }
4900
4901             return true;
4902
4903         case GT_IND:
4904
4905 NARROW_IND:
4906             /* Simply change the type of the tree */
4907
4908             if  (doit && (dstSize <= genTypeSize(tree->gtType)))
4909             {
4910                 tree->gtType = genSignedType(dstt);
4911                 tree->SetVNs(vnpNarrow);
4912
4913                 /* Make sure we don't mess up the variable type */
4914                 if  ((oper == GT_LCL_VAR) || (oper == GT_LCL_FLD))
4915                     tree->gtFlags |= GTF_VAR_CAST;
4916             }
4917
4918             return  true;
4919
4920         case GT_EQ:
4921         case GT_NE:
4922         case GT_LT:
4923         case GT_LE:
4924         case GT_GT:
4925         case GT_GE:
4926
4927             /* These can always be narrowed since they only represent 0 or 1 */
4928             return  true;
4929
4930         case GT_CAST:
4931             {
4932                 var_types       cast    = tree->CastToType();
4933                 var_types       oprt    = op1->TypeGet();
4934                 unsigned        oprSize = genTypeSize(oprt);
4935
4936                 if (cast != srct)
4937                     return false;
4938
4939                 if (varTypeIsIntegralOrI(dstt) != varTypeIsIntegralOrI(oprt))
4940                     return false;
4941
4942                 if (tree->gtOverflow())
4943                     return false;
4944
4945                 /* Is this a cast from the type we're narrowing to or a smaller one? */
4946
4947                 if  (oprSize <= dstSize)
4948                 {
4949                     /* Bash the target type of the cast */
4950
4951                     if  (doit)
4952                     {
4953                         dstt = genSignedType(dstt);
4954
4955                         if  (oprSize == dstSize)
4956                         {
4957                             // Same size: change the CAST into a NOP
4958                             tree->ChangeOper         (GT_NOP);
4959                             tree->gtType            = dstt;
4960                             tree->gtOp.gtOp2        = nullptr;
4961                             tree->gtVNPair          = op1->gtVNPair;   // Set to op1's ValueNumber
4962                         }
4963                         else
4964                         {
4965                             // oprSize is smaller
4966                             assert(oprSize < dstSize);
4967
4968                             // Change the CastToType in the GT_CAST node
4969                             tree->CastToType() = dstt;
4970
4971                             // The result type of a GT_CAST is never a small type.
4972                             // Use genActualType to widen dstt when it is a small types.
4973                             tree->gtType = genActualType(dstt);
4974                             tree->SetVNs(vnpNarrow);
4975                         }
4976                     }
4977
4978                     return  true;
4979                 }
4980             }
4981             return  false;
4982
4983         case GT_COMMA:
4984             if (!gtIsActiveCSE_Candidate(op2)  &&
4985                 optNarrowTree(op2, srct, dstt, vnpNarrow, doit))
4986             {               
4987                 /* Simply change the type of the tree */
4988
4989                 if  (doit)
4990                 {
4991                     tree->gtType = genActualType(dstt);
4992                     tree->SetVNs(vnpNarrow);
4993                 }
4994                 return true;
4995             }
4996             return false;
4997
4998         default:
4999             noway_assert(doit == false);
5000             return  false;
5001         }
5002
5003     }
5004
5005     return  false;
5006 }
5007
5008
5009 /*****************************************************************************
5010  *
5011  *  The following logic figures out whether the given variable is assigned
5012  *  somewhere in a list of basic blocks (or in an entire loop).
5013  */
5014
5015
5016 Compiler::fgWalkResult      Compiler::optIsVarAssgCB(GenTreePtr *pTree, fgWalkData *data)
5017 {
5018     GenTreePtr tree = *pTree;
5019
5020     if  (tree->OperKind() & GTK_ASGOP)
5021     {
5022         GenTreePtr      dest     = tree->gtOp.gtOp1;
5023         genTreeOps      destOper = dest->OperGet();
5024
5025         isVarAssgDsc *  desc = (isVarAssgDsc*)data->pCallbackData;
5026         assert(desc && desc->ivaSelf == desc);
5027
5028         if  (destOper == GT_LCL_VAR)
5029         {
5030             unsigned        tvar = dest->gtLclVarCommon.gtLclNum;
5031             if  (tvar < lclMAX_ALLSET_TRACKED)
5032                 AllVarSetOps::AddElemD(data->compiler, desc->ivaMaskVal, tvar);
5033             else
5034                 desc->ivaMaskIncomplete  = true;
5035
5036             if  (tvar == desc->ivaVar)
5037             {
5038                 if  (tree != desc->ivaSkip)
5039                     return  WALK_ABORT;
5040             }
5041         }
5042         else if (destOper == GT_LCL_FLD)
5043         {
5044             /* We can't track every field of every var. Moreover, indirections
5045                may access different parts of the var as different (but
5046                overlapping) fields. So just treat them as indirect accesses */
5047
5048             // unsigned    lclNum = dest->gtLclFld.gtLclNum;
5049             // noway_assert(lvaTable[lclNum].lvAddrTaken);
5050
5051             varRefKinds     refs = varTypeIsGC(tree->TypeGet()) ? VR_IND_REF
5052                                                                 : VR_IND_SCL;
5053             desc->ivaMaskInd = varRefKinds(desc->ivaMaskInd | refs);
5054         }
5055         else if (destOper == GT_CLS_VAR)
5056         {
5057             desc->ivaMaskInd = varRefKinds(desc->ivaMaskInd | VR_GLB_VAR);
5058         }
5059         else if (destOper == GT_IND)
5060         {
5061             /* Set the proper indirection bits */
5062
5063             varRefKinds refs = varTypeIsGC(tree->TypeGet()) ? VR_IND_REF
5064                                                             : VR_IND_SCL;
5065             desc->ivaMaskInd = varRefKinds(desc->ivaMaskInd | refs);
5066         }
5067     }
5068     else if (tree->gtOper == GT_CALL)
5069     {
5070         isVarAssgDsc *  desc = (isVarAssgDsc*)data->pCallbackData;
5071         assert(desc && desc->ivaSelf == desc);
5072
5073         desc->ivaMaskCall = optCallInterf(tree);
5074     }
5075
5076     return  WALK_CONTINUE;
5077 }
5078
5079 /*****************************************************************************/
5080
5081 bool                Compiler::optIsVarAssigned(BasicBlock *   beg,
5082                                                BasicBlock *   end,
5083                                                GenTreePtr     skip,
5084                                                unsigned       var)
5085 {
5086     bool            result;
5087     isVarAssgDsc    desc;
5088
5089     desc.ivaSkip     = skip;
5090 #ifdef DEBUG
5091     desc.ivaSelf     = &desc;
5092 #endif
5093     desc.ivaVar      = var;
5094     desc.ivaMaskCall = CALLINT_NONE;
5095     AllVarSetOps::AssignNoCopy(this, desc.ivaMaskVal, AllVarSetOps::MakeEmpty(this));
5096
5097     for (;;)
5098     {
5099         noway_assert(beg);
5100
5101         for (GenTreeStmt* stmt = beg->firstStmt(); stmt; stmt = stmt->gtNextStmt)
5102         {
5103             noway_assert(stmt->gtOper == GT_STMT);
5104             if  (fgWalkTreePre(&stmt->gtStmtExpr, optIsVarAssgCB, &desc))
5105             {
5106                 result = true;
5107                 goto DONE;
5108             }
5109         }
5110
5111         if  (beg == end)
5112             break;
5113
5114         beg = beg->bbNext;
5115     }
5116
5117     result = false;
5118
5119 DONE:
5120
5121     return  result;
5122 }
5123
5124 /*****************************************************************************/
5125 int                 Compiler::optIsSetAssgLoop(unsigned            lnum,
5126                                                ALLVARSET_VALARG_TP vars,
5127                                                varRefKinds         inds)
5128 {
5129     LoopDsc *       loop;
5130
5131     /* Get hold of the loop descriptor */
5132
5133     noway_assert(lnum < optLoopCount);
5134     loop = optLoopTable + lnum;
5135
5136     /* Do we already know what variables are assigned within this loop? */
5137
5138     if  (!(loop->lpFlags & LPFLG_ASGVARS_YES))
5139     {
5140         isVarAssgDsc    desc;
5141
5142         BasicBlock  *   beg;
5143         BasicBlock  *   end;
5144
5145         /* Prepare the descriptor used by the tree walker call-back */
5146
5147         desc.ivaVar     = (unsigned)-1;
5148         desc.ivaSkip    = NULL;
5149 #ifdef DEBUG
5150         desc.ivaSelf    = &desc;
5151 #endif
5152         AllVarSetOps::AssignNoCopy(this, desc.ivaMaskVal, AllVarSetOps::MakeEmpty(this));
5153         desc.ivaMaskInd        = VR_NONE;
5154         desc.ivaMaskCall       = CALLINT_NONE;
5155         desc.ivaMaskIncomplete = false;
5156
5157         /* Now walk all the statements of the loop */
5158
5159         beg = loop->lpHead->bbNext;
5160         end = loop->lpBottom;
5161
5162         for (/**/; /**/; beg = beg->bbNext)
5163         {
5164             noway_assert(beg);
5165
5166             for (GenTreeStmt* stmt = beg->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt)
5167             {
5168                 noway_assert(stmt->gtOper == GT_STMT);
5169                 fgWalkTreePre(&stmt->gtStmtExpr, optIsVarAssgCB, &desc);
5170
5171                 if  (desc.ivaMaskIncomplete)
5172                 {
5173                     loop->lpFlags |= LPFLG_ASGVARS_INC;
5174                 }
5175             }
5176
5177             if  (beg == end)
5178                 break;
5179         }
5180
5181         AllVarSetOps::Assign(this, loop->lpAsgVars, desc.ivaMaskVal);
5182         loop->lpAsgInds = desc.ivaMaskInd;
5183         loop->lpAsgCall = desc.ivaMaskCall;
5184
5185         /* Now we know what variables are assigned in the loop */
5186
5187         loop->lpFlags |= LPFLG_ASGVARS_YES;
5188     }
5189
5190     /* Now we can finally test the caller's mask against the loop's */
5191     if  (!AllVarSetOps::IsEmptyIntersection(this, loop->lpAsgVars, vars) ||
5192          (loop->lpAsgInds & inds))
5193     {
5194         return  1;
5195     }
5196
5197     switch (loop->lpAsgCall)
5198     {
5199     case CALLINT_ALL:
5200
5201         /* Can't hoist if the call might have side effect on an indirection. */
5202
5203         if (loop->lpAsgInds != VR_NONE)
5204             return  1;
5205
5206         break;
5207
5208     case CALLINT_REF_INDIRS:
5209
5210         /* Can't hoist if the call might have side effect on an ref indirection. */
5211
5212         if (loop->lpAsgInds & VR_IND_REF)
5213             return  1;
5214
5215         break;
5216
5217     case CALLINT_SCL_INDIRS:
5218
5219         /* Can't hoist if the call might have side effect on an non-ref indirection. */
5220
5221         if (loop->lpAsgInds & VR_IND_SCL)
5222             return  1;
5223
5224         break;
5225
5226     case CALLINT_ALL_INDIRS:
5227
5228         /* Can't hoist if the call might have side effect on any indirection. */
5229
5230         if (loop->lpAsgInds & (VR_IND_REF|VR_IND_SCL))
5231             return  1;
5232
5233         break;
5234
5235     case CALLINT_NONE:
5236
5237         /* Other helpers kill nothing */
5238
5239         break;
5240
5241     default:
5242         noway_assert(!"Unexpected lpAsgCall value");
5243     }
5244
5245     return  0;
5246 }
5247
5248 void                    Compiler::optPerformHoistExpr(GenTreePtr origExpr, unsigned lnum)
5249 {
5250 #ifdef DEBUG
5251     if (verbose)
5252     {
5253         printf("\nHoisting a copy of ");
5254         printTreeID(origExpr);
5255         printf(" into PreHeader for loop L%02u <BB%02u..BB%02u>:\n",
5256                lnum, optLoopTable[lnum].lpFirst->bbNum, optLoopTable[lnum].lpBottom->bbNum);
5257         gtDispTree(origExpr);
5258         printf("\n");
5259     }
5260 #endif
5261
5262     // This loop has to be in a form that is approved for hoisting.
5263     assert (optLoopTable[lnum].lpFlags & LPFLG_HOISTABLE);
5264
5265     // Create a copy of the expression and mark it for CSE's.   
5266     GenTreePtr hoistExpr = gtCloneExpr(origExpr, GTF_MAKE_CSE);
5267
5268     // At this point we should have a cloned expression, marked with the GTF_MAKE_CSE flag
5269     assert(hoistExpr != origExpr);
5270     assert(hoistExpr->gtFlags & GTF_MAKE_CSE);
5271
5272     GenTreePtr hoist = hoistExpr;
5273     // The value of the expression isn't used (unless it's an assignment).
5274     if (hoistExpr->OperGet() != GT_ASG)
5275     {
5276         hoist = gtUnusedValNode(hoistExpr);
5277     }
5278
5279     /* Put the statement in the preheader */
5280
5281     fgCreateLoopPreHeader(lnum);
5282
5283     BasicBlock *  preHead = optLoopTable[lnum].lpHead;
5284     assert (preHead->bbJumpKind == BBJ_NONE);
5285
5286     // fgMorphTree and lvaRecursiveIncRefCounts requires that compCurBB be the block that contains
5287     // (or in this case, will contain) the expression.
5288     compCurBB = preHead; 
5289     
5290     // Increment the ref counts of any local vars appearing in "hoist".
5291     // Note that we need to do this before fgMorphTree() as fgMorph() could constant
5292     // fold away some of the lcl vars referenced by "hoist".
5293     lvaRecursiveIncRefCounts(hoist);
5294
5295     hoist = fgMorphTree(hoist);
5296
5297     GenTreePtr hoistStmt = gtNewStmt(hoist);
5298     hoistStmt->gtFlags |= GTF_STMT_CMPADD;
5299
5300     /* simply append the statement at the end of the preHead's list */
5301
5302     GenTreePtr treeList = preHead->bbTreeList;
5303
5304     if (treeList)
5305     {
5306         /* append after last statement */
5307
5308         GenTreePtr  last = treeList->gtPrev;
5309         assert (last->gtNext == 0);
5310
5311         last->gtNext        = hoistStmt;
5312         hoistStmt->gtPrev   = last;
5313         treeList->gtPrev    = hoistStmt;
5314     }
5315     else
5316     {
5317         /* Empty pre-header - store the single statement in the block */
5318
5319         preHead->bbTreeList = hoistStmt;
5320         hoistStmt->gtPrev   = hoistStmt;
5321     }
5322
5323     hoistStmt->gtNext = nullptr;
5324
5325 #ifdef DEBUG
5326     if (verbose)
5327     {
5328         printf("This hoisted copy placed in PreHeader (BB%02u):\n", preHead->bbNum);
5329         gtDispTree(hoist);
5330     }
5331 #endif
5332
5333     if (fgStmtListThreaded)
5334     {
5335         gtSetStmtInfo(hoistStmt);
5336         fgSetStmtSeq(hoistStmt);
5337     }
5338
5339 #ifdef DEBUG
5340     if (m_nodeTestData != NULL)
5341     {
5342
5343         // What is the depth of the loop "lnum"?
5344         ssize_t depth = 0;
5345         unsigned lnumIter = lnum;
5346         while (optLoopTable[lnumIter].lpParent != BasicBlock::NOT_IN_LOOP)
5347         {
5348             depth++;
5349             lnumIter = optLoopTable[lnumIter].lpParent;
5350         }
5351
5352         NodeToTestDataMap* testData = GetNodeTestData();
5353
5354         TestLabelAndNum tlAndN;
5355         if (testData->Lookup(origExpr, &tlAndN) && tlAndN.m_tl == TL_LoopHoist)
5356         {
5357             if (tlAndN.m_num == -1)
5358             {
5359                 printf("Node ");
5360                 printTreeID(origExpr);
5361                 printf(" was declared 'do not hoist', but is being hoisted.\n");
5362                 assert(false);
5363             }
5364             else if (tlAndN.m_num != depth)
5365             {
5366                 printf("Node ");
5367                 printTreeID(origExpr);
5368                 printf(" was declared as hoistable from loop at nesting depth %d; actually hoisted from loop at depth %d.\n",
5369                        tlAndN.m_num, depth);
5370                 assert(false);
5371             }
5372             else
5373             {
5374                 // We've correctly hoisted this, so remove the annotation.  Later, we'll check for any remaining "must hoist" annotations.
5375                 testData->Remove(origExpr);
5376                 // Now we insert an annotation to make sure that "hoistExpr" is actually CSE'd.
5377                 tlAndN.m_tl = TL_CSE_Def;
5378                 tlAndN.m_num = m_loopHoistCSEClass++;
5379                 testData->Set(hoistExpr, tlAndN);
5380             }
5381         }
5382     }
5383 #endif
5384
5385 #if LOOP_HOIST_STATS
5386     if (!m_curLoopHasHoistedExpression)
5387     {
5388         m_loopsWithHoistedExpressions++;
5389         m_curLoopHasHoistedExpression = true;
5390     }
5391     m_totalHoistedExpressions++;
5392 #endif // LOOP_HOIST_STATS
5393
5394
5395 void                    Compiler::optHoistLoopCode()
5396 {
5397     // If we don't have any loops in the method then take an early out now.
5398     if (optLoopCount == 0)
5399         return;
5400
5401 #ifdef DEBUG
5402     unsigned jitNoHoist = JitConfig.JitNoHoist();
5403     if (jitNoHoist > 0)
5404     {
5405         return;
5406     }
5407 #endif
5408
5409 #if 0
5410     // The code in this #if has been useful in debugging loop cloning issues, by
5411     // enabling selective enablement of the loop cloning optimization according to
5412     // method hash.
5413 #ifdef DEBUG
5414     unsigned methHash = info.compMethodHash();
5415     char* lostr = getenv("loophoisthashlo");
5416     unsigned methHashLo = 0;
5417     if (lostr != NULL) 
5418     {
5419         sscanf_s(lostr, "%x", &methHashLo);
5420         // methHashLo = (unsigned(atoi(lostr)) << 2);  // So we don't have to use negative numbers.
5421     }
5422     char* histr = getenv("loophoisthashhi");
5423     unsigned methHashHi = UINT32_MAX;
5424     if (histr != NULL) 
5425     {
5426         sscanf_s(histr, "%x", &methHashHi);
5427         // methHashHi = (unsigned(atoi(histr)) << 2);  // So we don't have to use negative numbers.
5428     }
5429     if (methHash < methHashLo || methHash > methHashHi)
5430         return;
5431     printf("Doing loop hoisting in %s (0x%x).\n", info.compFullName, methHash);
5432 #endif  // DEBUG
5433 #endif  // 0     -- debugging loop cloning issues
5434
5435 #ifdef DEBUG
5436     if  (verbose)
5437     {
5438         printf("\n*************** In optHoistLoopCode()\n");
5439         printf("Blocks/Trees before phase\n");
5440         fgDispBasicBlocks(true);
5441         printf("");
5442     }
5443 #endif
5444
5445     // Consider all the loop nests, in outer-to-inner order (thus hoisting expressions outside the largest loop in which
5446     // they are invariant.)
5447     LoopHoistContext hoistCtxt(this);
5448     for (unsigned lnum = 0; lnum < optLoopCount; lnum++)
5449     {
5450         if (optLoopTable[lnum].lpFlags & LPFLG_REMOVED)
5451             continue;
5452
5453         if (optLoopTable[lnum].lpParent == BasicBlock::NOT_IN_LOOP)
5454         {
5455             optHoistLoopNest(lnum, &hoistCtxt);
5456         }
5457     }
5458
5459 #if DEBUG
5460     if  (fgModified)
5461     {    
5462         if (verbose)
5463         {
5464             printf("Blocks/Trees after optHoistLoopCode() modified flowgraph\n");
5465             fgDispBasicBlocks(true);
5466             printf("");
5467         }
5468
5469         // Make sure that the predecessor lists are accurate
5470         fgDebugCheckBBlist();
5471     }
5472 #endif
5473
5474 #ifdef DEBUG
5475     // Test Data stuff..
5476     // If we have no test data, early out.
5477     if (m_nodeTestData == NULL) return;
5478     NodeToTestDataMap* testData = GetNodeTestData();
5479     for (NodeToTestDataMap::KeyIterator ki = testData->Begin(); !ki.Equal(testData->End()); ++ki)
5480     {
5481         TestLabelAndNum tlAndN;
5482         GenTreePtr node = ki.Get();
5483         bool b = testData->Lookup(node, &tlAndN);
5484         assert(b);
5485         if (tlAndN.m_tl != TL_LoopHoist) continue;
5486         // Otherwise, it is a loop hoist annotation.
5487         assert(tlAndN.m_num < 100);  // >= 100 indicates nested static field address, should already have been moved.
5488         if (tlAndN.m_num >= 0)
5489         {
5490             printf("Node ");
5491             printTreeID(node);
5492             printf(" was declared 'must hoist', but has not been hoisted.\n");
5493             assert(false);
5494         }
5495     }
5496 #endif  // DEBUG
5497 }
5498
5499 void                    Compiler::optHoistLoopNest(unsigned lnum, LoopHoistContext* hoistCtxt)
5500 {
5501     // Do this loop, then recursively do all nested loops.
5502     CLANG_FORMAT_COMMENT_ANCHOR;
5503
5504 #if LOOP_HOIST_STATS
5505     // Record stats
5506     m_curLoopHasHoistedExpression = false;
5507     m_loopsConsidered++;
5508 #endif // LOOP_HOIST_STATS
5509
5510     optHoistThisLoop(lnum, hoistCtxt);
5511     
5512     VNSet* hoistedInCurLoop = hoistCtxt->ExtractHoistedInCurLoop();
5513
5514     if (optLoopTable[lnum].lpChild != BasicBlock::NOT_IN_LOOP)
5515     {
5516         // Add the ones hoisted in "lnum" to "hoistedInParents" for any nested loops.
5517         // TODO-Cleanup: we should have a set abstraction for loops.
5518         if (hoistedInCurLoop != nullptr)
5519         {
5520             for (VNSet::KeyIterator keys = hoistedInCurLoop->Begin(); !keys.Equal(hoistedInCurLoop->End()); ++keys)
5521             {
5522 #ifdef DEBUG
5523                 bool b;
5524                 assert(!hoistCtxt->m_hoistedInParentLoops.Lookup(keys.Get(), &b));
5525 #endif
5526                 hoistCtxt->m_hoistedInParentLoops.Set(keys.Get(), true);
5527             }
5528         }
5529
5530         for (unsigned child = optLoopTable[lnum].lpChild; child != BasicBlock::NOT_IN_LOOP; child = optLoopTable[child].lpSibling)
5531         {
5532             optHoistLoopNest(child, hoistCtxt);
5533         }
5534
5535         // Now remove them.
5536         // TODO-Cleanup: we should have a set abstraction for loops.
5537         if (hoistedInCurLoop != nullptr)
5538         {
5539             for (VNSet::KeyIterator keys = hoistedInCurLoop->Begin(); !keys.Equal(hoistedInCurLoop->End()); ++keys)
5540             {
5541                 // Note that we asserted when we added these that they hadn't been members, so removing is appropriate.
5542                 hoistCtxt->m_hoistedInParentLoops.Remove(keys.Get());
5543             }
5544         }
5545     }
5546 }
5547
5548 void                    Compiler::optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt)
5549 {
5550     LoopDsc* pLoopDsc = &optLoopTable[lnum];
5551
5552     /* If loop was removed continue */
5553
5554     if  (pLoopDsc->lpFlags & LPFLG_REMOVED)
5555         return;
5556
5557     /* Get the head and tail of the loop */
5558
5559     BasicBlock* head = pLoopDsc->lpHead;
5560     BasicBlock* tail = pLoopDsc->lpBottom;
5561     BasicBlock* lbeg = pLoopDsc->lpEntry;
5562     BasicBlock* block;
5563
5564     // We must have a do-while loop
5565     if ((pLoopDsc->lpFlags & LPFLG_DO_WHILE) == 0)
5566         return;
5567
5568     // The loop-head must dominate the loop-entry.
5569     // TODO-CQ: Couldn't we make this true if it's not?
5570     if (!fgDominate(head, lbeg))
5571         return;
5572
5573     // if lbeg is the start of a new try block then we won't be able to hoist
5574     if (!BasicBlock::sameTryRegion(head, lbeg))
5575         return;
5576
5577     // We don't bother hoisting when inside of a catch block
5578     if ((lbeg->bbCatchTyp != BBCT_NONE) && (lbeg->bbCatchTyp != BBCT_FINALLY))
5579         return;
5580
5581     pLoopDsc->lpFlags |= LPFLG_HOISTABLE;
5582
5583     unsigned        begn = lbeg->bbNum;
5584     unsigned        endn = tail->bbNum;
5585
5586     // Ensure the per-loop sets/tables are empty.
5587     hoistCtxt->m_curLoopVnInvariantCache.RemoveAll();
5588
5589 #ifdef  DEBUG
5590     if  (verbose)
5591     {
5592         printf("optHoistLoopCode for loop L%02u <BB%02u..BB%02u>:\n", lnum, begn, endn);
5593         printf("  Loop body %s a call\n", pLoopDsc->lpContainsCall ?  "contains" : "does not contain");
5594     }
5595 #endif
5596
5597     VARSET_TP VARSET_INIT_NOCOPY(loopVars, VarSetOps::Intersection(this, pLoopDsc->lpVarInOut,
5598                                                                          pLoopDsc->lpVarUseDef));
5599
5600     pLoopDsc->lpVarInOutCount    = VarSetOps::Count(this, pLoopDsc->lpVarInOut);
5601     pLoopDsc->lpLoopVarCount     = VarSetOps::Count(this, loopVars);
5602     pLoopDsc->lpHoistedExprCount = 0;
5603
5604 #ifndef _TARGET_64BIT_
5605     unsigned longVarsCount = VarSetOps::Count(this, lvaLongVars);
5606
5607     if (longVarsCount > 0)
5608     {
5609         // Since 64-bit variables take up two registers on 32-bit targets, we increase
5610         //  the Counts such that each TYP_LONG variable counts twice.
5611         //
5612         VARSET_TP VARSET_INIT_NOCOPY(loopLongVars,  VarSetOps::Intersection(this, loopVars, lvaLongVars));
5613         VARSET_TP VARSET_INIT_NOCOPY(inOutLongVars, VarSetOps::Intersection(this,  pLoopDsc->lpVarInOut, lvaLongVars));
5614
5615 #ifdef  DEBUG
5616         if  (verbose)
5617         {
5618             printf("\n  LONGVARS(%d)=",  VarSetOps::Count(this, lvaLongVars));
5619                                          lvaDispVarSet(lvaLongVars);
5620         }
5621 #endif
5622         pLoopDsc->lpLoopVarCount  += VarSetOps::Count(this, loopLongVars);
5623         pLoopDsc->lpVarInOutCount += VarSetOps::Count(this, inOutLongVars);
5624     }
5625 #endif // !_TARGET_64BIT_
5626
5627 #ifdef  DEBUG
5628     if  (verbose)
5629     {
5630         printf("\n  USEDEF  (%d)=",  VarSetOps::Count(this, pLoopDsc->lpVarUseDef));
5631                                      lvaDispVarSet(pLoopDsc->lpVarUseDef);
5632
5633         printf("\n  INOUT   (%d)=",  pLoopDsc->lpVarInOutCount);
5634                                      lvaDispVarSet(pLoopDsc->lpVarInOut);
5635                                      
5636         printf("\n  LOOPVARS(%d)=",  pLoopDsc->lpLoopVarCount);
5637                                      lvaDispVarSet(loopVars);
5638         printf("\n");
5639     }
5640 #endif
5641
5642     unsigned floatVarsCount = VarSetOps::Count(this, lvaFloatVars);
5643
5644     if (floatVarsCount > 0)
5645     {
5646         VARSET_TP VARSET_INIT_NOCOPY(loopFPVars,  VarSetOps::Intersection(this, loopVars, lvaFloatVars));
5647         VARSET_TP VARSET_INIT_NOCOPY(inOutFPVars, VarSetOps::Intersection(this,  pLoopDsc->lpVarInOut, lvaFloatVars));                                                        
5648
5649         pLoopDsc->lpLoopVarFPCount     = VarSetOps::Count(this, loopFPVars);
5650         pLoopDsc->lpVarInOutFPCount    = VarSetOps::Count(this, inOutFPVars);
5651         pLoopDsc->lpHoistedFPExprCount = 0;
5652
5653         pLoopDsc->lpLoopVarCount  -= pLoopDsc->lpLoopVarFPCount;
5654         pLoopDsc->lpVarInOutCount -= pLoopDsc->lpVarInOutFPCount;
5655
5656 #ifdef  DEBUG
5657         if  (verbose)
5658         {
5659             printf(  "  INOUT-FP(%d)=",  pLoopDsc->lpVarInOutFPCount);
5660                                          lvaDispVarSet(inOutFPVars);
5661
5662             printf("\n  LOOPV-FP(%d)=",  pLoopDsc->lpLoopVarFPCount);
5663                                          lvaDispVarSet(loopFPVars);
5664         }
5665 #endif
5666     }
5667     else // (floatVarsCount == 0)
5668     {
5669         pLoopDsc->lpLoopVarFPCount     = 0;
5670         pLoopDsc->lpVarInOutFPCount    = 0;
5671         pLoopDsc->lpHoistedFPExprCount = 0;
5672     }
5673
5674     // Find the set of definitely-executed blocks.
5675     // Ideally, the definitely-executed blocks are the ones that post-dominate the entry block.
5676     // Until we have post-dominators, we'll special-case for single-exit blocks.
5677     ExpandArrayStack<BasicBlock*> defExec(getAllocatorLoopHoist());
5678     if (pLoopDsc->lpFlags & LPFLG_ONE_EXIT)
5679     {
5680         assert(pLoopDsc->lpExit != nullptr);
5681         BasicBlock* cur = pLoopDsc->lpExit;
5682         // Push dominators, until we reach "entry" or exit the loop.
5683         while (   cur != nullptr 
5684                && pLoopDsc->lpContains(cur)
5685                && cur != pLoopDsc->lpEntry)
5686         {
5687             defExec.Push(cur);
5688             cur = cur->bbIDom;
5689         }
5690         // If we didn't reach the entry block, give up and *just* push the entry block.
5691         if (cur != pLoopDsc->lpEntry)
5692         {
5693             defExec.Reset();
5694         }
5695         defExec.Push(pLoopDsc->lpEntry);
5696     }
5697     else  // More than one exit 
5698     {
5699         // We'll assume that only the entry block is definitely executed.  
5700         // We could in the future do better.
5701         defExec.Push(pLoopDsc->lpEntry);
5702     }
5703
5704     while (defExec.Size() > 0)
5705     {
5706         // Consider in reverse order: dominator before dominatee.
5707         BasicBlock* blk = defExec.Pop();
5708         optHoistLoopExprsForBlock(blk, lnum, hoistCtxt);
5709     }
5710 }
5711
5712 // Hoist any expressions in "blk" that are invariant in loop "lnum" outside of "blk" and into a PreHead for loop "lnum".
5713 void Compiler::optHoistLoopExprsForBlock(BasicBlock* blk, 
5714                                          unsigned lnum, 
5715                                          LoopHoistContext* hoistCtxt) 
5716 {
5717     LoopDsc* pLoopDsc = &optLoopTable[lnum];
5718     bool firstBlockAndBeforeSideEffect = (blk == pLoopDsc->lpEntry);
5719     unsigned blkWeight = blk->getBBWeight(this);
5720
5721 #ifdef  DEBUG
5722     if  (verbose)
5723     {
5724         printf("    optHoistLoopExprsForBlock BB%02u (weight=%6s) of loop L%02u <BB%02u..BB%02u>, firstBlock is %s\n",
5725                blk->bbNum,
5726                refCntWtd2str(blkWeight),
5727                lnum, 
5728                pLoopDsc->lpFirst->bbNum, 
5729                pLoopDsc->lpBottom->bbNum, 
5730                firstBlockAndBeforeSideEffect ? "true" : "false");
5731         if (blkWeight <  (BB_UNITY_WEIGHT / 10))
5732         {
5733             printf("      block weight is too small to perform hoisting.\n");
5734         }
5735     }
5736 #endif
5737
5738      if (blkWeight <  (BB_UNITY_WEIGHT / 10))
5739      {
5740          // Block weight is too small to perform hoisting.
5741          return;
5742      }
5743
5744     for (GenTreeStmt* stmt = blk->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt)
5745     {
5746         GenTreePtr stmtTree = stmt->gtStmtExpr;
5747         bool hoistable;
5748         (void)optHoistLoopExprsForTree(stmtTree, lnum, hoistCtxt, &firstBlockAndBeforeSideEffect, &hoistable);
5749         if (hoistable)
5750         {
5751             // we will try to hoist the top-level stmtTree
5752             optHoistCandidate(stmtTree, lnum, hoistCtxt);
5753         }
5754     }
5755 }
5756
5757 bool Compiler::optIsProfitableToHoistableTree(GenTreePtr tree, unsigned lnum)
5758 {
5759     LoopDsc* pLoopDsc = &optLoopTable[lnum];
5760
5761     bool loopContainsCall = pLoopDsc->lpContainsCall;
5762
5763     int availRegCount;
5764     int hoistedExprCount;
5765     int loopVarCount;
5766     int varInOutCount;
5767
5768     if (varTypeIsFloating(tree->TypeGet()))
5769     {
5770         hoistedExprCount = pLoopDsc->lpHoistedFPExprCount;
5771         loopVarCount     = pLoopDsc->lpLoopVarFPCount;
5772         varInOutCount    = pLoopDsc->lpVarInOutFPCount;
5773
5774        availRegCount = CNT_CALLEE_SAVED_FLOAT;
5775         if (!loopContainsCall)
5776         {
5777             availRegCount += CNT_CALLEE_TRASH_FLOAT-1;
5778         }
5779 #ifdef _TARGET_ARM_
5780         // For ARM each double takes two FP registers 
5781         // For now on ARM we won't track singles/doubles 
5782         // and instead just assume that we always have doubles.
5783         //
5784         availRegCount /= 2;
5785 #endif
5786     }
5787     else
5788     {
5789         hoistedExprCount = pLoopDsc->lpHoistedExprCount;
5790         loopVarCount     = pLoopDsc->lpLoopVarCount;
5791         varInOutCount    = pLoopDsc->lpVarInOutCount;
5792
5793         availRegCount = CNT_CALLEE_SAVED-1;
5794         if (!loopContainsCall)
5795         {
5796             availRegCount += CNT_CALLEE_TRASH-1;
5797         }
5798 #ifndef _TARGET_64BIT_
5799         // For our 32-bit targets Long types take two registers.
5800         if (varTypeIsLong(tree->TypeGet()))
5801         {
5802             availRegCount = (availRegCount+1) / 2;
5803         }
5804 #endif
5805     }
5806
5807     // decrement the availRegCount by the count of expression that we have already hoisted.
5808     availRegCount -= hoistedExprCount;
5809
5810     // the variables that are read/written inside the loop should 
5811     // always be a subset of the InOut variables for the loop
5812     assert(loopVarCount <= varInOutCount);
5813
5814     // When loopVarCount >= availRegCount we believe that all of the
5815     // available registers will get used to hold LclVars inside the loop.
5816     // This pessimistically assumes that each loopVar has a conflicting 
5817     // lifetime with every other loopVar.
5818     // For this case we will hoist the expression only if is profitable
5819     // to place it in a stack home location (gtCostEx >= 2*IND_COST_EX)
5820     // as we believe it will be placed in the stack or one of the other
5821     // loopVars will be spilled into the stack
5822     //
5823     if (loopVarCount >= availRegCount)
5824     {
5825         // Don't hoist expressions that are not heavy: tree->gtCostEx < (2*IND_COST_EX)
5826         if (tree->gtCostEx < (2*IND_COST_EX))
5827             return false;
5828     }
5829
5830     // When varInOutCount < availRegCount we are know that there are 
5831     // some available register(s) when we enter the loop body.
5832     // When varInOutCount == availRegCount there often will be a register
5833     // available when we enter the loop body, since a loop often defines a 
5834     // LclVar on exit or there is often at least one LclVar that is worth 
5835     // spilling to the stack to make way for this hoisted expression.
5836     // So we are willing hoist an expression with gtCostEx == MIN_CSE_COST
5837     //
5838     if (varInOutCount > availRegCount)
5839     {
5840         // Don't hoist expressions that barely meet CSE cost requirements: tree->gtCostEx == MIN_CSE_COST
5841         if (tree->gtCostEx <= MIN_CSE_COST+1)
5842             return false;
5843     }
5844
5845     return true;
5846 }
5847
5848 //
5849 //  This function returns true if 'tree' is a loop invariant expression.
5850 //  It also sets '*pHoistable' to true if 'tree' can be hoisted into a loop PreHeader block
5851 //
5852 bool Compiler::optHoistLoopExprsForTree(GenTreePtr tree,
5853                                         unsigned lnum,
5854                                         LoopHoistContext* hoistCtxt,
5855                                         bool* pFirstBlockAndBeforeSideEffect,
5856                                         bool* pHoistable)
5857 {
5858     // First do the children.
5859     // We must keep track of whether each child node was hoistable or not
5860     //
5861     unsigned nChildren = tree->NumChildren();
5862     bool childrenHoistable[GenTree::MAX_CHILDREN];
5863
5864     // Initialize the array elements for childrenHoistable[] to false
5865     for (unsigned i = 0; i < nChildren; i++)
5866     {
5867         childrenHoistable[i] = false;
5868     }
5869
5870     bool treeIsInvariant = true;
5871     for (unsigned childNum = 0; childNum < nChildren; childNum++)
5872     {
5873         if (!optHoistLoopExprsForTree(tree->GetChild(childNum), lnum, hoistCtxt, pFirstBlockAndBeforeSideEffect, &childrenHoistable[childNum]))
5874         {
5875             treeIsInvariant = false;
5876         }
5877     }
5878
5879     // If all the children of "tree" are hoistable, then "tree" itself can be hoisted
5880     //
5881     bool treeIsHoistable = treeIsInvariant;
5882
5883     // But we must see if anything else prevents "tree" from being hoisted.
5884     //
5885     if (treeIsInvariant)
5886     {
5887         // Tree must be a suitable CSE candidate for us to be able to hoist it.
5888         treeIsHoistable = optIsCSEcandidate(tree);
5889
5890         // If it's a call, it must be a helper call, and be pure.
5891         // Further, if it may run a cctor, it must be labeled as "Hoistable" 
5892         // (meaning it won't run a cctor because the class is not precise-init).
5893         if (treeIsHoistable && tree->OperGet() == GT_CALL)
5894         {
5895             GenTreeCall* call = tree->AsCall();
5896             if (call->gtCallType != CT_HELPER)
5897             {
5898                 treeIsHoistable = false;
5899             }
5900             else
5901             {
5902                 CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd);
5903                 if (!s_helperCallProperties.IsPure(helpFunc))
5904                 {
5905                     treeIsHoistable = false;
5906                 }
5907                 else if (   s_helperCallProperties.MayRunCctor(helpFunc)
5908                          && (call->gtFlags & GTF_CALL_HOISTABLE) == 0)
5909                 {
5910                     treeIsHoistable = false;
5911                 }
5912             }
5913         }
5914
5915         if (treeIsHoistable)
5916         {
5917             if (!(*pFirstBlockAndBeforeSideEffect))
5918             {
5919                 // For now, we give up on an expression that might raise an exception if it is after the
5920                 // first possible global side effect (and we assume we're after that if we're not in the first block).
5921                 //TODO-CQ: this is when we might do loop cloning.
5922                 //
5923                 if ((tree->gtFlags & GTF_EXCEPT) != 0)
5924                 {
5925                     treeIsHoistable = false;
5926                 }
5927             }
5928             // Currently we must give up on reads from static variables (even if we are in the first block).
5929             //
5930             if (tree->OperGet() == GT_CLS_VAR)
5931             {
5932                 // TODO-CQ: test that fails if we hoist GT_CLS_VAR: JIT\Directed\Languages\ComponentPascal\pi_r.exe method Main
5933                 treeIsHoistable = false;
5934             }
5935         }
5936
5937         // Is the value of the whole tree loop invariant?
5938         treeIsInvariant = optVNIsLoopInvariant(tree->gtVNPair.GetLiberal(), lnum, &hoistCtxt->m_curLoopVnInvariantCache);
5939
5940         // Is the value of the whole tree loop invariant?
5941         if (!treeIsInvariant)
5942         {
5943             treeIsHoistable = false;
5944         }
5945     }
5946
5947     // Check if we need to set '*pFirstBlockAndBeforeSideEffect' to false.
5948     // If we encounter a tree with a call in it 
5949     //  or if we see an assignment to global we set it to false.
5950     //
5951     // If we are already set to false then we can skip these checks
5952     //
5953     if (*pFirstBlockAndBeforeSideEffect)
5954     {
5955         // For this purpose, we only care about memory side effects.  We assume that expressions will
5956         // be hoisted so that they are evaluated in the same order as they would have been in the loop,
5957         // and therefore throw exceptions in the same order.  (So we don't use GTF_GLOBALLY_VISIBLE_SIDE_EFFECTS
5958         // here, since that includes exceptions.)
5959         if (tree->gtFlags & GTF_CALL)
5960         {
5961             *pFirstBlockAndBeforeSideEffect = false;
5962         } 
5963         else if (tree->OperIsAssignment())
5964         {
5965             // If the LHS of the assignment has a global reference, then assume it's a global side effect.
5966             GenTreePtr lhs = tree->gtOp.gtOp1;
5967             if (lhs->gtFlags & GTF_GLOB_REF)
5968             {
5969                 *pFirstBlockAndBeforeSideEffect = false;
5970             }
5971         } else if (tree->OperIsCopyBlkOp())
5972         {
5973             GenTreePtr args = tree->gtOp.gtOp1;
5974             assert(args->OperGet() == GT_LIST);
5975             if (args->gtOp.gtOp1->gtFlags & GTF_GLOB_REF)
5976             {
5977                 *pFirstBlockAndBeforeSideEffect = false;
5978             }
5979         }
5980     }
5981     
5982     // If this 'tree' is hoistable then we return and the caller will
5983     // decide to hoist it as part of larger hoistable expression.
5984     //
5985     if (!treeIsHoistable)
5986     {
5987         // We are not hoistable so we will now hoist any hoistable children.
5988         //
5989         for (unsigned childNum = 0; childNum < nChildren; childNum++)
5990         {
5991             if (childrenHoistable[childNum])
5992             {
5993                 // We can't hoist the LHS of an assignment, isn't a real use. 
5994                 if (childNum == 0 && (tree->OperIsAssignment())) 
5995                     continue;
5996
5997                 GenTreePtr child = tree->GetChild(childNum);
5998
5999                 // We try to hoist this 'child' tree
6000                 optHoistCandidate(child, lnum, hoistCtxt);
6001             }
6002         }
6003     }
6004
6005     *pHoistable = treeIsHoistable;
6006     return treeIsInvariant;
6007 }
6008
6009 void Compiler::optHoistCandidate(GenTreePtr tree, unsigned lnum, LoopHoistContext* hoistCtxt)
6010 {
6011     if (lnum == BasicBlock::NOT_IN_LOOP)
6012     {
6013         // The hoisted expression isn't valid at any loop head so don't hoist this expression.
6014         return;
6015     }
6016
6017     // The outer loop also must be suitable for hoisting...
6018     if ((optLoopTable[lnum].lpFlags & LPFLG_HOISTABLE) == 0)
6019         return;
6020
6021     // If the hoisted expression isn't valid at this loop head then break
6022     if (!optTreeIsValidAtLoopHead(tree, lnum))
6023         return;
6024
6025     // It must pass the hoistable profitablity tests for this loop level
6026     if (!optIsProfitableToHoistableTree(tree, lnum))
6027         return;
6028
6029
6030     bool b;
6031     if (hoistCtxt->m_hoistedInParentLoops.Lookup(tree->gtVNPair.GetLiberal(), &b))
6032     {
6033         // already hoisted in a parent loop, so don't hoist this expression.
6034         return;
6035     }
6036     
6037     if (hoistCtxt->GetHoistedInCurLoop(this)->Lookup(tree->gtVNPair.GetLiberal(), &b))
6038     {
6039         // already hoisted this expression in the current loop, so don't hoist this expression.
6040         return;
6041     }
6042
6043     // Expression can be hoisted 
6044     optPerformHoistExpr(tree, lnum);
6045
6046     // Increment lpHoistedExprCount or lpHoistedFPExprCount 
6047     if (!varTypeIsFloating(tree->TypeGet()))
6048     {
6049         optLoopTable[lnum].lpHoistedExprCount++; 
6050 #ifndef _TARGET_64BIT_
6051         // For our 32-bit targets Long types take two registers.
6052         if (varTypeIsLong(tree->TypeGet()))
6053         {
6054             optLoopTable[lnum].lpHoistedExprCount++; 
6055         }
6056 #endif
6057     }
6058     else // Floating point expr hoisted
6059     {
6060         optLoopTable[lnum].lpHoistedFPExprCount++; 
6061     }
6062
6063     // Record the hoisted expression in hoistCtxt
6064     hoistCtxt->GetHoistedInCurLoop(this)->Set(tree->gtVNPair.GetLiberal(), true);
6065 }
6066
6067
6068 bool Compiler::optVNIsLoopInvariant(ValueNum vn, unsigned lnum, VNToBoolMap* loopVnInvariantCache)
6069 {
6070     // If it is not a VN, is not loop-invariant.
6071     if (vn == ValueNumStore::NoVN) return false;
6072
6073     // We'll always short-circuit constants.
6074     if (vnStore->IsVNConstant(vn) || vn == vnStore->VNForVoid())
6075         return true;
6076
6077     // If we've done this query previously, don't repeat.
6078     bool previousRes = false;
6079     if (loopVnInvariantCache->Lookup(vn, &previousRes))
6080         return previousRes;
6081
6082     bool res = true;
6083     VNFuncApp funcApp;
6084     if (vnStore->GetVNFunc(vn, &funcApp))
6085     {
6086         if (funcApp.m_func == VNF_PhiDef)
6087         {
6088             // First, make sure it's a "proper" phi -- the definition is a Phi application.
6089             VNFuncApp phiDefValFuncApp;
6090             if (   !vnStore->GetVNFunc(funcApp.m_args[2], &phiDefValFuncApp)
6091                 || phiDefValFuncApp.m_func != VNF_Phi)
6092             {
6093                 // It's not *really* a definition, rather a pass-through of some other VN.
6094                 // (This could occur, say if both sides of an if-then-else diamond made the
6095                 // same assignment to a variable.)
6096                 res = optVNIsLoopInvariant(funcApp.m_args[2], lnum, loopVnInvariantCache);
6097             }
6098             else
6099             {
6100                 // Is the definition within the loop?  If so, is not loop-invariant.
6101                 unsigned lclNum = funcApp.m_args[0];
6102                 unsigned ssaNum = funcApp.m_args[1];
6103                 LclSsaVarDsc* ssaDef = lvaTable[lclNum].GetPerSsaData(ssaNum);
6104                 res = !optLoopContains(lnum, ssaDef->m_defLoc.m_blk->bbNatLoopNum);
6105             }
6106         }
6107         else if (funcApp.m_func == VNF_PhiHeapDef)
6108         {
6109             BasicBlock* defnBlk = reinterpret_cast<BasicBlock*>(vnStore->ConstantValue<ssize_t>(funcApp.m_args[0]));
6110             res = !optLoopContains(lnum, defnBlk->bbNatLoopNum);
6111         }
6112         else
6113         {
6114             for (unsigned i = 0; i < funcApp.m_arity; i++)
6115             {
6116                 // TODO-CQ: We need to either make sure that *all* VN functions
6117                 // always take VN args, or else have a list of arg positions to exempt, as implicitly
6118                 // constant.
6119                 if (!optVNIsLoopInvariant(funcApp.m_args[i], lnum, loopVnInvariantCache))
6120                 {
6121                     res = false;
6122                     break;
6123                 }
6124             }
6125         }
6126     }
6127     else
6128     {
6129         // Otherwise, assume non-function "new, unique" VN's are not loop invariant.
6130         res = false;
6131     }
6132     
6133     loopVnInvariantCache->Set(vn, res);
6134     return res;
6135 }
6136
6137 bool                Compiler::optTreeIsValidAtLoopHead(GenTreePtr tree, unsigned lnum)
6138 {
6139     if (tree->OperIsLocal())
6140     {
6141         GenTreeLclVarCommon* lclVar = tree->AsLclVarCommon();
6142         unsigned lclNum = lclVar->gtLclNum;
6143
6144         // The lvlVar must be have an Ssa tracked lifetime
6145         if (fgExcludeFromSsa(lclNum))
6146             return false;
6147
6148         // If the loop does not contains the SSA def we can hoist it.
6149         if (!optLoopTable[lnum].lpContains(lvaTable[lclNum].GetPerSsaData(lclVar->GetSsaNum())->m_defLoc.m_blk))
6150             return true;
6151     }
6152     else if (tree->OperIsConst())
6153     {
6154         return true;
6155     }
6156     else  // If every one of the children nodes are valid at this Loop's Head.
6157     {
6158         unsigned nChildren = tree->NumChildren();
6159         for (unsigned childNum = 0; childNum < nChildren; childNum++)
6160         {
6161             if (!optTreeIsValidAtLoopHead(tree->GetChild(childNum), lnum))
6162                 return false;
6163         }
6164         return true;
6165     }
6166     return false;
6167 }
6168
6169
6170 /*****************************************************************************
6171  *
6172  *  Creates a pre-header block for the given loop - a preheader is a BBJ_NONE
6173  *  header. The pre-header will replace the current lpHead in the loop table.
6174  *  The loop has to be a do-while loop. Thus, all blocks dominated by lpHead
6175  *  will also be dominated by the loop-top, lpHead->bbNext. 
6176  *
6177  */
6178
6179 void                 Compiler::fgCreateLoopPreHeader(unsigned   lnum)
6180 {
6181     LoopDsc* pLoopDsc = &optLoopTable[lnum];
6182
6183     /* This loop has to be a "do-while" loop */
6184
6185     assert (pLoopDsc->lpFlags & LPFLG_DO_WHILE);
6186     
6187     /* Have we already created a loop-preheader block? */
6188
6189     if (pLoopDsc->lpFlags & LPFLG_HAS_PREHEAD)
6190         return;
6191
6192     BasicBlock* head  = pLoopDsc->lpHead;
6193     BasicBlock* top   = pLoopDsc->lpTop;
6194     BasicBlock* entry = pLoopDsc->lpEntry;
6195
6196     // if 'entry' and 'head' are in different try regions then we won't be able to hoist
6197     if (!BasicBlock::sameTryRegion(head, entry))
6198         return;
6199
6200     // Ensure that lpHead always dominates lpEntry
6201
6202     noway_assert(fgDominate(head, entry));
6203     
6204     /* Get hold of the first block of the loop body */
6205
6206     assert (top == entry);
6207
6208     /* Allocate a new basic block */
6209
6210     BasicBlock * preHead = bbNewBasicBlock(BBJ_NONE);
6211     preHead->bbFlags    |= BBF_INTERNAL | BBF_LOOP_PREHEADER;
6212
6213     // Must set IL code offset
6214     preHead->bbCodeOffs  = top->bbCodeOffs;
6215
6216     // Set the default value of the preHead weight in case we don't have 
6217     // valid profile data and since this blocks weight is just an estimate
6218     // we clear any BBF_PROF_WEIGHT flag that we may have picked up from head.
6219     //
6220     preHead->inheritWeight(head);
6221     preHead->bbFlags &= ~BBF_PROF_WEIGHT;
6222
6223 #ifdef  DEBUG
6224     if  (verbose)
6225         printf("\nCreated PreHeader (BB%02u) for loop L%02u (BB%02u - BB%02u), with weight = %s\n",
6226                preHead->bbNum, lnum, top->bbNum, pLoopDsc->lpBottom->bbNum, 
6227                refCntWtd2str(preHead->getBBWeight(this)));
6228 #endif
6229
6230     // The preheader block is part of the containing loop (if any).
6231     preHead->bbNatLoopNum = pLoopDsc->lpParent;
6232
6233     if (fgIsUsingProfileWeights() && (head->bbJumpKind == BBJ_COND))
6234     {
6235         if ((head->bbWeight == 0)  || (head->bbNext->bbWeight == 0))
6236         {
6237             preHead->bbWeight = 0;
6238             preHead->bbFlags |= BBF_RUN_RARELY;
6239         }
6240         else
6241         {
6242             bool allValidProfileWeights = ((head->bbFlags             & BBF_PROF_WEIGHT) != 0)
6243                                        && ((head->bbJumpDest->bbFlags & BBF_PROF_WEIGHT) != 0)
6244                                        && ((head->bbNext->bbFlags     & BBF_PROF_WEIGHT) != 0);
6245            
6246             if (allValidProfileWeights)
6247             {
6248                 double loopEnteredCount;
6249                 double loopSkippedCount;
6250
6251                 if (fgHaveValidEdgeWeights)
6252                 {
6253                     flowList * edgeToNext = fgGetPredForBlock(head->bbNext, head);
6254                     flowList * edgeToJump = fgGetPredForBlock(head->bbJumpDest, head);
6255                     noway_assert(edgeToNext != NULL);
6256                     noway_assert(edgeToJump != NULL);
6257
6258                     loopEnteredCount = ((double) edgeToNext->flEdgeWeightMin  + (double) edgeToNext->flEdgeWeightMax)  / 2.0;
6259                     loopSkippedCount = ((double) edgeToJump->flEdgeWeightMin  + (double) edgeToJump->flEdgeWeightMax)  / 2.0;
6260                 }
6261                 else
6262                 {
6263                     loopEnteredCount = (double) head->bbNext->bbWeight;
6264                     loopSkippedCount = (double) head->bbJumpDest->bbWeight;
6265                 }
6266
6267                 double loopTakenRatio = loopEnteredCount / (loopEnteredCount + loopSkippedCount);
6268
6269                 // Calculate a good approximation of the preHead's block weight
6270                 unsigned preHeadWeight = (unsigned) (((double) head->bbWeight * loopTakenRatio) + 0.5);
6271                 preHead->setBBWeight(max(preHeadWeight, 1));
6272                 noway_assert(!preHead->isRunRarely());
6273              }
6274         }
6275     }
6276
6277     // Link in the preHead block.
6278     fgInsertBBbefore(top, preHead);
6279
6280     // Ideally we would re-run SSA and VN if we optimized by doing loop hoisting.
6281     // However, that is too expensive at this point. Instead, we update the phi
6282     // node block references, if we created pre-header block due to hoisting.
6283     // This is sufficient because any definition participating in SSA that flowed
6284     // into the phi via the loop header block will now flow through the preheader
6285     // block from the header block.
6286
6287     for (GenTreePtr stmt = top->bbTreeList; stmt; stmt = stmt->gtNext)
6288     {
6289         GenTreePtr tree = stmt->gtStmt.gtStmtExpr;
6290         if (tree->OperGet() != GT_ASG)
6291         {
6292             break;
6293         }
6294         GenTreePtr op2 = tree->gtGetOp2();
6295         if (op2->OperGet() != GT_PHI)
6296         {
6297             break;
6298         }
6299         GenTreeArgList* args = op2->gtGetOp1()->AsArgList();
6300         while (args != nullptr)
6301         {
6302             GenTreePhiArg* phiArg = args->Current()->AsPhiArg();
6303             if (phiArg->gtPredBB == head)
6304             {
6305                 phiArg->gtPredBB = preHead;
6306             }
6307             args = args->Rest();
6308         }
6309     }
6310
6311     // The handler can't begin at the top of the loop.  If it did, it would be incorrect
6312     // to set the handler index on the pre header without updating the exception table.
6313     noway_assert(!top->hasHndIndex() || fgFirstBlockOfHandler(top) != top);
6314
6315     // Update the EH table to make the hoisted block part of the loop's EH block.
6316     fgExtendEHRegionBefore(top);
6317
6318     // TODO-CQ: set dominators for this block, to allow loop optimizations requiring them 
6319     //        (e.g: hoisting expression in a loop with the same 'head' as this one)
6320
6321     /* Update the loop entry */
6322
6323     pLoopDsc->lpHead   = preHead;
6324     pLoopDsc->lpFlags |= LPFLG_HAS_PREHEAD;
6325
6326     /* The new block becomes the 'head' of the loop - update bbRefs and bbPreds
6327        All predecessors of 'beg', (which is the entry in the loop)
6328        now have to jump to 'preHead', unless they are dominated by 'head' */
6329
6330     preHead->bbRefs = 0;
6331     fgAddRefPred(preHead, head);
6332     bool checkNestedLoops = false;
6333
6334     for (flowList * pred = top->bbPreds; pred; pred = pred->flNext)
6335     {
6336         BasicBlock  *   predBlock = pred->flBlock;
6337
6338         if (fgDominate(top, predBlock))
6339         {
6340             // note: if 'top' dominates predBlock, 'head' dominates predBlock too
6341             // (we know that 'head' dominates 'top'), but using 'top' instead of
6342             // 'head' in the test allows us to not enter here if 'predBlock == head'
6343
6344             if (predBlock != pLoopDsc->lpBottom)
6345             {
6346                 noway_assert(predBlock != head);
6347                 checkNestedLoops = true;
6348             }
6349             continue;
6350         }
6351
6352         switch (predBlock->bbJumpKind)
6353         {
6354         case BBJ_NONE:
6355             noway_assert(predBlock == head);
6356             break;
6357
6358         case BBJ_COND:
6359             if  (predBlock == head)
6360             {
6361                 noway_assert(predBlock->bbJumpDest != top);
6362                 break;
6363             }
6364             __fallthrough;
6365
6366         case BBJ_ALWAYS:
6367         case BBJ_EHCATCHRET:
6368             noway_assert(predBlock->bbJumpDest == top);
6369             predBlock->bbJumpDest = preHead;
6370             preHead->bbFlags |= BBF_JMP_TARGET|BBF_HAS_LABEL;
6371             
6372             if (predBlock == head)
6373             {
6374                 // This is essentially the same case of predBlock being a BBJ_NONE. We may not be
6375                 // able to make this a BBJ_NONE if it's an internal block (for example, a leave).
6376                 // Just break, pred will be removed after switch.
6377             }
6378             else
6379             {                
6380                 fgRemoveRefPred(top, predBlock);
6381                 fgAddRefPred(preHead, predBlock);
6382             }   
6383             break;
6384
6385         case BBJ_SWITCH:
6386             unsigned        jumpCnt; jumpCnt = predBlock->bbJumpSwt->bbsCount;
6387             BasicBlock * *  jumpTab; jumpTab = predBlock->bbJumpSwt->bbsDstTab;
6388
6389             do
6390             {
6391                 assert (*jumpTab);
6392                 if ((*jumpTab) == top)
6393                 {
6394                     (*jumpTab) = preHead;
6395
6396                     fgRemoveRefPred(top, predBlock);
6397                     fgAddRefPred(preHead, predBlock);
6398                     preHead->bbFlags |= BBF_JMP_TARGET|BBF_HAS_LABEL;
6399                 }
6400             }
6401             while (++jumpTab, --jumpCnt);
6402
6403         default:
6404             noway_assert(!"Unexpected bbJumpKind");
6405             break;
6406         }
6407     }
6408
6409     noway_assert(!fgGetPredForBlock(top, preHead));
6410     fgRemoveRefPred(top, head);
6411     fgAddRefPred(top, preHead);
6412
6413     /* 
6414         If we found at least one back-edge in the flowgraph pointing to the top/entry of the loop
6415         (other than the back-edge of the loop we are considering) then we likely have nested
6416         do-while loops with the same entry block and inserting the preheader block changes the head
6417         of all the nested loops. Now we will update this piece of information in the loop table, and
6418         mark all nested loops as having a preheader (the preheader block can be shared among all nested
6419         do-while loops with the same entry block).
6420     */
6421     if (checkNestedLoops)
6422     {
6423         for (unsigned l = 0; l < optLoopCount; l++)
6424         {
6425             if (optLoopTable[l].lpHead == head)
6426             {
6427                 noway_assert(l != lnum);  // pLoopDsc->lpHead was already changed from 'head' to 'preHead'
6428                 noway_assert(optLoopTable[l].lpEntry == top);
6429                 optUpdateLoopHead(l, optLoopTable[l].lpHead, preHead);
6430                 optLoopTable[l].lpFlags |= LPFLG_HAS_PREHEAD;
6431 #ifdef  DEBUG
6432                 if  (verbose)
6433                     printf("Same PreHeader (BB%02u) can be used for loop L%02u (BB%02u - BB%02u)\n\n",
6434                            preHead->bbNum, l, top->bbNum, optLoopTable[l].lpBottom->bbNum);
6435 #endif
6436             }
6437         }
6438     }
6439 }
6440
6441 bool                Compiler::optBlockIsLoopEntry(BasicBlock* blk, unsigned* pLnum)
6442 {
6443     unsigned lnum = blk->bbNatLoopNum;
6444     while (lnum != BasicBlock::NOT_IN_LOOP)
6445     {
6446         if (optLoopTable[lnum].lpEntry == blk)
6447         {
6448             *pLnum = lnum;
6449             return true;
6450         }
6451         lnum = optLoopTable[lnum].lpParent;
6452     }
6453     return false;
6454 }
6455
6456 void                Compiler::optComputeLoopSideEffects()
6457 {
6458     unsigned  lnum;
6459     for (lnum = 0; lnum < optLoopCount; lnum++)
6460     {
6461         VarSetOps::AssignNoCopy(this, optLoopTable[lnum].lpVarInOut,  VarSetOps::MakeEmpty(this));
6462         VarSetOps::AssignNoCopy(this, optLoopTable[lnum].lpVarUseDef, VarSetOps::MakeEmpty(this));
6463         optLoopTable[lnum].lpContainsCall = false;
6464     }
6465
6466     for (lnum = 0; lnum < optLoopCount; lnum++)
6467     {
6468         if (optLoopTable[lnum].lpFlags & LPFLG_REMOVED)
6469             continue;
6470
6471         if (optLoopTable[lnum].lpParent == BasicBlock::NOT_IN_LOOP) // Is outermost...
6472             optComputeLoopNestSideEffects(lnum);
6473     }
6474
6475     VarSetOps::AssignNoCopy(this, lvaFloatVars,  VarSetOps::MakeEmpty(this));
6476 #ifndef _TARGET_64BIT_
6477     VarSetOps::AssignNoCopy(this, lvaLongVars,  VarSetOps::MakeEmpty(this));
6478 #endif
6479
6480     for (unsigned i = 0; i < lvaCount; i++)
6481     {
6482         LclVarDsc* varDsc = &lvaTable[i];
6483         if (varDsc->lvTracked)
6484         {
6485             if (varTypeIsFloating(varDsc->lvType))
6486             {
6487                 VarSetOps::AddElemD(this, lvaFloatVars, varDsc->lvVarIndex);
6488             }
6489 #ifndef _TARGET_64BIT_
6490             else if (varTypeIsLong(varDsc->lvType))
6491             {
6492                 VarSetOps::AddElemD(this, lvaLongVars, varDsc->lvVarIndex);
6493             }
6494 #endif
6495         }
6496     }
6497 }
6498
6499 void                Compiler::optComputeLoopNestSideEffects(unsigned lnum)
6500 {
6501     assert(optLoopTable[lnum].lpParent == BasicBlock::NOT_IN_LOOP);  // Requires: lnum is outermost.
6502     BasicBlock* botNext = optLoopTable[lnum].lpBottom->bbNext;
6503     for (BasicBlock* bbInLoop = optLoopTable[lnum].lpFirst; bbInLoop != botNext; bbInLoop = bbInLoop->bbNext)
6504     {
6505         optComputeLoopSideEffectsOfBlock(bbInLoop);
6506     }
6507 }
6508
6509 void                Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk)
6510 {
6511     unsigned mostNestedLoop = blk->bbNatLoopNum;
6512     assert(mostNestedLoop != BasicBlock::NOT_IN_LOOP);
6513    
6514     AddVariableLivenessAllContainingLoops(mostNestedLoop, blk);
6515
6516     bool heapHavoc = false;  // True ==> there's a call or a memory store that has arbitrary heap effects.
6517
6518     // Now iterate over the remaining statements, and their trees.
6519     for (GenTreePtr stmts = blk->FirstNonPhiDef(); (stmts != nullptr); stmts = stmts->gtNext)
6520     {
6521         for (GenTreePtr tree = stmts->gtStmt.gtStmtList; (tree != nullptr); tree = tree->gtNext)
6522         {
6523             genTreeOps oper = tree->OperGet();
6524
6525             // Even after we set heapHavoc we still may want to know if a loop contains calls
6526             if (heapHavoc)
6527             {
6528                 if (oper == GT_CALL)
6529                 {
6530                     // Record that this loop contains a call
6531                     AddContainsCallAllContainingLoops(mostNestedLoop);
6532                 }
6533
6534                 // If we just set lpContainsCall or it was previously set 
6535                 if  (optLoopTable[mostNestedLoop].lpContainsCall)
6536                 {
6537                     // We can early exit after both heapHavoc and lpContainsCall are both set to true.
6538                     break;
6539                 }
6540
6541                 // We are just looking for GT_CALL nodes after heapHavoc was set.
6542                 continue;
6543             }
6544
6545             // otherwise heapHavoc is not set
6546             assert(!heapHavoc);
6547
6548             // This body is a distillation of the heap-side effect code of value numbering.
6549             // We also do a very limited analysis if byref PtrTo values, to cover some cases
6550             // that the compiler creates.
6551
6552             if (GenTree::OperIsAssignment(oper))
6553             {
6554                 GenTreePtr lhs = tree->gtOp.gtOp1->gtEffectiveVal(/*commaOnly*/true);
6555
6556                 if (lhs->OperGet() == GT_IND)
6557                 {
6558                     GenTreePtr arg = lhs->gtOp.gtOp1->gtEffectiveVal(/*commaOnly*/true);
6559                     FieldSeqNode* fldSeqArrElem = nullptr;
6560
6561                     if ((tree->gtFlags & GTF_IND_VOLATILE) != 0)
6562                     {
6563                         heapHavoc = true;
6564                         continue;
6565                     }
6566
6567                     ArrayInfo arrInfo;
6568
6569                     if (arg->TypeGet() == TYP_BYREF && arg->OperGet() == GT_LCL_VAR)
6570                     {
6571                         // If it's a local byref for which we recorded a value number, use that...
6572                         GenTreeLclVar* argLcl = arg->AsLclVar();
6573                         if (!fgExcludeFromSsa(argLcl->GetLclNum()))
6574                         {
6575                             ValueNum argVN = lvaTable[argLcl->GetLclNum()].GetPerSsaData(argLcl->GetSsaNum())->m_vnPair.GetLiberal();
6576                             VNFuncApp funcApp;
6577                             if (argVN != ValueNumStore::NoVN && vnStore->GetVNFunc(argVN, &funcApp) && funcApp.m_func == VNF_PtrToArrElem)
6578                             {
6579                                 assert(vnStore->IsVNHandle(funcApp.m_args[0]));
6580                                 CORINFO_CLASS_HANDLE elemType = CORINFO_CLASS_HANDLE(vnStore->ConstantValue<size_t>(funcApp.m_args[0]));
6581                                 AddModifiedElemTypeAllContainingLoops(mostNestedLoop, elemType);
6582                                 // Don't set heapHavoc below.
6583                                 continue;
6584                             }
6585                         }
6586                         // Otherwise...
6587                         heapHavoc = true;
6588                     }
6589                     // Is the LHS an array index expression?
6590                     else if (lhs->ParseArrayElemForm(this, &arrInfo, &fldSeqArrElem))
6591                     {
6592                         // We actually ignore "fldSeq" -- any modification to an S[], at any
6593                         // field of "S", will lose all information about the array type.
6594                         CORINFO_CLASS_HANDLE elemTypeEq = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType);
6595                         AddModifiedElemTypeAllContainingLoops(mostNestedLoop, elemTypeEq);
6596                     }
6597                     else 
6598                     {                        
6599                         // We are only interested in IsFieldAddr()'s fldSeq out parameter.
6600                         //
6601                         GenTreePtr obj          = nullptr;  // unused
6602                         GenTreePtr staticOffset = nullptr;  // unused
6603                         FieldSeqNode* fldSeq    = nullptr;
6604
6605                         if (arg->IsFieldAddr(this, &obj, &staticOffset, &fldSeq) &&
6606                             (fldSeq != FieldSeqStore::NotAField()))
6607                         {
6608                             // Get the first (object) field from field seq.  Heap[field] will yield the "field map".
6609                             assert(fldSeq != nullptr);
6610                             if (fldSeq->IsFirstElemFieldSeq())
6611                             {
6612                                 fldSeq = fldSeq->m_next;
6613                                 assert(fldSeq != nullptr);
6614                             }
6615
6616                             AddModifiedFieldAllContainingLoops(mostNestedLoop, fldSeq->m_fieldHnd);
6617                         }
6618                         else
6619                         {
6620                             heapHavoc = true;
6621                         }
6622                     }
6623                 } 
6624                 else if (lhs->OperGet() == GT_CLS_VAR)
6625                 {
6626                     AddModifiedFieldAllContainingLoops(mostNestedLoop, lhs->gtClsVar.gtClsVarHnd);
6627                 }
6628                 // Otherwise, must be local lhs form.  I should assert that.
6629                 else if (lhs->OperGet() == GT_LCL_VAR)
6630                 {
6631                     GenTreeLclVar* lhsLcl = lhs->AsLclVar();
6632                     GenTreePtr rhs = tree->gtOp.gtOp2;
6633                     ValueNum rhsVN = rhs->gtVNPair.GetLiberal();
6634                     // If we gave the RHS a value number, propagate it.
6635                     if (rhsVN != ValueNumStore::NoVN)
6636                     {
6637                         rhsVN = vnStore->VNNormVal(rhsVN);
6638                         if (!fgExcludeFromSsa(lhsLcl->GetLclNum()))
6639                         {
6640                             lvaTable[lhsLcl->GetLclNum()].GetPerSsaData(lhsLcl->GetSsaNum())->m_vnPair.SetLiberal(rhsVN);
6641                         }
6642                     }
6643                 }
6644             }
6645             else  // not GenTree::OperIsAssignment(oper)
6646             {
6647                 switch (oper)
6648                 {
6649                 case GT_COMMA:
6650                     tree->gtVNPair = tree->gtOp.gtOp2->gtVNPair;
6651                     break;
6652
6653                 case GT_ADDR:
6654                     // Is it an addr of a array index expression?
6655                     {
6656                         GenTreePtr addrArg = tree->gtOp.gtOp1;
6657                         if (addrArg->OperGet() == GT_IND)
6658                         {
6659                             // Is the LHS an array index expression?
6660                             if (addrArg->gtFlags & GTF_IND_ARR_INDEX)
6661                             {
6662                                 ArrayInfo arrInfo;
6663                                 bool b = GetArrayInfoMap()->Lookup(addrArg, &arrInfo);
6664                                 assert(b);
6665                                 CORINFO_CLASS_HANDLE elemType = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType);
6666                                 tree->gtVNPair.SetBoth(vnStore->VNForFunc(TYP_BYREF, VNF_PtrToArrElem,
6667                                                                           vnStore->VNForHandle(ssize_t(elemType), GTF_ICON_CLASS_HDL),  
6668                                                                           // The rest are dummy arguments.
6669                                                                           vnStore->VNForNull(),
6670                                                                           vnStore->VNForNull(),
6671                                                                           vnStore->VNForNull()));
6672                             }
6673                         }
6674                     }
6675                     break;
6676
6677                 case GT_INITBLK:
6678                 case GT_COPYBLK:
6679                 case GT_COPYOBJ:
6680                     {
6681                         GenTreeLclVarCommon* lclVarTree;
6682                         bool                 isEntire;
6683                         if (!tree->DefinesLocal(this, &lclVarTree, &isEntire))
6684                         {
6685                             // For now, assume arbitrary side effects on the heap...
6686                             // TODO-CQ: Why not be complete, and get this case right?
6687                             heapHavoc = true;
6688                         }
6689                     }
6690                     break;
6691
6692                 case GT_LOCKADD:        // Binop
6693                 case GT_XADD:           // Binop
6694                 case GT_XCHG:           // Binop
6695                 case GT_CMPXCHG:        // Specialop
6696                     {
6697                         heapHavoc = true;
6698                     }
6699                     break;
6700
6701                 case GT_CALL:
6702                     {
6703                         GenTreeCall* call = tree->AsCall();
6704
6705                         // Record that this loop contains a call
6706                         AddContainsCallAllContainingLoops(mostNestedLoop);
6707
6708                         if (call->gtCallType == CT_HELPER)
6709                         {
6710                             CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd);
6711                             if (s_helperCallProperties.MutatesHeap(helpFunc))
6712                             {
6713                                 heapHavoc = true;
6714                             }
6715                             else if (s_helperCallProperties.MayRunCctor(helpFunc))
6716                             {
6717                                 // If the call is labeled as "Hoistable", then we've checked the
6718                                 // class that would be constructed, and it is not precise-init, so
6719                                 // the cctor will not be run by this call.  Otherwise, it might be,
6720                                 // and might have arbitrary side effects.
6721                                 if ((tree->gtFlags & GTF_CALL_HOISTABLE) == 0)
6722                                 {
6723                                     heapHavoc = true;
6724                                 }
6725                             }
6726                         }
6727                         else
6728                         {
6729                             heapHavoc = true;
6730                         }
6731                         break;
6732                     }
6733
6734                 default:
6735                     // All other gtOper node kinds, leave 'heapHavoc' unchanged (i.e. false)
6736                     break;
6737                 }
6738             }
6739         }
6740     }
6741
6742     if (heapHavoc)
6743     {
6744         // Record that all loops containing this block have heap havoc effects.
6745         unsigned lnum = mostNestedLoop;
6746         while (lnum != BasicBlock::NOT_IN_LOOP)
6747         {
6748             optLoopTable[lnum].lpLoopHasHeapHavoc = true;
6749             lnum = optLoopTable[lnum].lpParent;
6750         }
6751     }
6752 }
6753
6754 // Marks the containsCall information to "lnum" and any parent loops.
6755 void                Compiler::AddContainsCallAllContainingLoops(unsigned lnum)
6756 {
6757     assert(0 <= lnum && lnum < optLoopCount);
6758     while (lnum != BasicBlock::NOT_IN_LOOP)
6759     {
6760         optLoopTable[lnum].lpContainsCall = true;
6761         lnum = optLoopTable[lnum].lpParent;
6762     }
6763 }
6764
6765 // Adds the variable liveness information for 'blk' to 'this' LoopDsc
6766 void                Compiler::LoopDsc::AddVariableLiveness(Compiler* comp, BasicBlock * blk)
6767 {
6768     VarSetOps::UnionD(comp, this->lpVarInOut,  blk->bbLiveIn);
6769     VarSetOps::UnionD(comp, this->lpVarInOut,  blk->bbLiveOut);
6770
6771     VarSetOps::UnionD(comp, this->lpVarUseDef, blk->bbVarUse);
6772     VarSetOps::UnionD(comp, this->lpVarUseDef, blk->bbVarDef);
6773 }
6774
6775 // Adds the variable liveness information for 'blk' to "lnum" and any parent loops.
6776 void                Compiler::AddVariableLivenessAllContainingLoops(unsigned lnum, BasicBlock * blk)
6777 {
6778     assert(0 <= lnum && lnum < optLoopCount);
6779     while (lnum != BasicBlock::NOT_IN_LOOP)
6780     {
6781         optLoopTable[lnum].AddVariableLiveness(this, blk);
6782         lnum = optLoopTable[lnum].lpParent;
6783     }
6784 }
6785
6786 // Adds "fldHnd" to the set of modified fields of "lnum" and any parent loops.
6787 void                Compiler::AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd)
6788 {
6789     assert(0 <= lnum && lnum < optLoopCount);
6790     while (lnum != BasicBlock::NOT_IN_LOOP)
6791     {
6792         optLoopTable[lnum].AddModifiedField(this, fldHnd);
6793         lnum = optLoopTable[lnum].lpParent;
6794     }
6795 }
6796
6797 // Adds "elemType" to the set of modified array element types of "lnum" and any parent loops.
6798 void                Compiler::AddModifiedElemTypeAllContainingLoops(unsigned lnum, CORINFO_CLASS_HANDLE elemClsHnd)
6799 {
6800     assert(0 <= lnum && lnum < optLoopCount);
6801     while (lnum != BasicBlock::NOT_IN_LOOP)
6802     {
6803         optLoopTable[lnum].AddModifiedElemType(this, elemClsHnd);
6804         lnum = optLoopTable[lnum].lpParent;
6805     }
6806 }
6807
6808 /*****************************************************************************
6809  *
6810  *  Helper passed to Compiler::fgWalkAllTreesPre() to decrement the LclVar usage counts
6811  *  The 'keepList'is either a single tree or a list of trees that are formed by
6812  *  one or more GT_COMMA nodes.  It is the kept side-effects as returned by the
6813  *  gtExtractSideEffList method.
6814  */
6815
6816 /* static */
6817 Compiler::fgWalkResult      Compiler::optRemoveTreeVisitor(GenTreePtr *pTree, fgWalkData *data)
6818 {
6819     GenTreePtr  tree = *pTree;
6820     Compiler *  comp = data->compiler;
6821     GenTreePtr  keepList = (GenTreePtr)(data->pCallbackData);
6822
6823     // We may have a non-NULL side effect list that is being kept
6824     //
6825     if (keepList)
6826     {
6827         GenTreePtr keptTree = keepList;
6828         while (keptTree->OperGet() == GT_COMMA)
6829         {
6830             assert(keptTree->OperKind() & GTK_SMPOP);
6831             GenTreePtr op1 = keptTree->gtOp.gtOp1; 
6832             GenTreePtr op2 = keptTree->gtGetOp2();
6833
6834             // For the GT_COMMA case the op1 is part of the orginal CSE tree 
6835             // that is being kept because it contains some side-effect
6836             //
6837             if (tree == op1)
6838             {
6839                 // This tree and all of its sub trees are being kept.
6840                 return WALK_SKIP_SUBTREES;
6841             }
6842
6843             // For the GT_COMMA case the op2 are the remaining side-effects of the orginal CSE tree
6844             // which can again be another GT_COMMA or the final side-effect part
6845             //
6846             keptTree = op2;
6847         }
6848         if (tree == keptTree)
6849         {
6850             // This tree and all of its sub trees are being kept.
6851             return WALK_SKIP_SUBTREES;
6852         }
6853     }
6854
6855     // This node is being removed from the graph of GenTreePtr
6856
6857     // Look for any local variable references
6858
6859     if  (tree->gtOper == GT_LCL_VAR && comp->lvaLocalVarRefCounted)
6860     {
6861         unsigned        lclNum;
6862         LclVarDsc   *   varDsc;
6863
6864         /* This variable ref is going away, decrease its ref counts */
6865
6866         lclNum = tree->gtLclVarCommon.gtLclNum;
6867         assert(lclNum < comp->lvaCount);
6868         varDsc = comp->lvaTable + lclNum;
6869
6870         // make sure it's been initialized
6871         assert(comp->compCurBB != nullptr);
6872         assert(comp->compCurBB->bbWeight <= BB_MAX_WEIGHT); 
6873
6874         /* Decrement its lvRefCnt and lvRefCntWtd */
6875
6876         // Use getBBWeight to determine the proper block weight.
6877         // This impacts the block weights when we have IBC data.
6878         varDsc->decRefCnts(comp->compCurBB->getBBWeight(comp), comp);
6879     }
6880
6881     return  WALK_CONTINUE;
6882 }
6883
6884 /*****************************************************************************
6885  *
6886  *  Routine called to decrement the LclVar ref counts when removing a tree
6887  *  during the remove RangeCheck phase.
6888  *  This method will decrement the refcounts for any LclVars used below 'deadTree', 
6889  *  unless the node is found in the 'keepList' (which are saved side effects)
6890  *  The keepList is communicated using the walkData.pCallbackData field
6891  *  Also the compCurBB must be set to the current BasicBlock  which contains
6892  *  'deadTree' as we need to fetch the block weight when decrementing the ref counts.
6893  */
6894
6895 void Compiler::optRemoveTree(GenTreePtr deadTree, GenTreePtr keepList)
6896 {
6897     // We communicate this value using the walkData.pCallbackData field
6898     //
6899     fgWalkTreePre(&deadTree, optRemoveTreeVisitor, (void*)keepList);
6900 }
6901
6902 /*****************************************************************************
6903  *
6904  *  Given an array index node, mark it as not needing a range check.
6905  */
6906
6907 void                Compiler::optRemoveRangeCheck(GenTreePtr tree,
6908                                                   GenTreePtr stmt,
6909                                                   bool       updateCSEcounts,
6910                                                   unsigned   sideEffFlags,
6911                                                   bool       forceRemove)
6912 {
6913     GenTreePtr      add1;
6914     GenTreePtr  *   addp;
6915
6916     GenTreePtr      nop1;
6917     GenTreePtr  *   nopp;
6918
6919     GenTreePtr      icon;
6920     GenTreePtr      mult;
6921
6922     GenTreePtr      base;
6923
6924     ssize_t         ival;
6925
6926 #if !REARRANGE_ADDS
6927     noway_assert(!"can't remove range checks without REARRANGE_ADDS right now");
6928 #endif
6929
6930     noway_assert(stmt->gtOper     == GT_STMT);
6931     noway_assert(tree->gtOper     == GT_COMMA);
6932     noway_assert(tree->gtOp.gtOp1->gtOper == GT_ARR_BOUNDS_CHECK);
6933     noway_assert(forceRemove || optIsRangeCheckRemovable(tree->gtOp.gtOp1));
6934
6935     GenTreeBoundsChk* bndsChk = tree->gtOp.gtOp1->AsBoundsChk();
6936     
6937 #ifdef DEBUG
6938     if (verbose)
6939     {
6940         printf("Before optRemoveRangeCheck:\n");
6941         gtDispTree(tree);
6942     }
6943 #endif
6944
6945     GenTreePtr sideEffList = nullptr;
6946     if (sideEffFlags)
6947     {
6948         gtExtractSideEffList(tree->gtOp.gtOp1, &sideEffList, sideEffFlags);
6949     }
6950
6951     // Decrement the ref counts for any LclVars that are being deleted
6952     //                    
6953     optRemoveTree(tree->gtOp.gtOp1, sideEffList);
6954
6955     // Just replace the bndsChk with a NOP as an operand to the GT_COMMA, if there are no side effects.
6956     tree->gtOp.gtOp1 = (sideEffList != NULL) ? sideEffList : gtNewNothingNode();
6957
6958     // TODO-CQ: We should also remove the GT_COMMA, but in any case we can no longer CSE the GT_COMMA.
6959     tree->gtFlags |= GTF_DONT_CSE;
6960
6961     /* Recalculate the gtCostSz, etc... */
6962     gtSetStmtInfo(stmt);
6963
6964     /* Re-thread the nodes if necessary */
6965     if (fgStmtListThreaded)
6966     {
6967         fgSetStmtSeq(stmt);
6968     }
6969
6970 #ifdef DEBUG
6971     if (verbose)
6972     {
6973         printf("After optRemoveRangeCheck:\n");
6974         gtDispTree(tree);
6975     }
6976 #endif
6977
6978 }
6979
6980 /*****************************************************************************
6981  * Return the scale in an array reference, given a pointer to the
6982  * multiplication node.
6983  */
6984
6985 ssize_t                   Compiler::optGetArrayRefScaleAndIndex(GenTreePtr mul, GenTreePtr *pIndex DEBUGARG(bool bRngChk))
6986 {
6987     assert (mul);
6988     assert (mul->gtOper == GT_MUL || mul->gtOper == GT_LSH);
6989     assert (mul->gtOp.gtOp2->IsCnsIntOrI());
6990
6991     ssize_t scale = mul->gtOp.gtOp2->gtIntConCommon.IconValue();
6992
6993     if  (mul->gtOper == GT_LSH)
6994         scale = ((ssize_t)1) << scale;
6995
6996     GenTreePtr index = mul->gtOp.gtOp1;
6997
6998     if (index->gtOper == GT_MUL && index->gtOp.gtOp2->IsCnsIntOrI())
6999     {
7000         // case of two cascading multiplications for constant int (e.g.  * 20 morphed to * 5 * 4):
7001         // When index->gtOper is GT_MUL and index->gtOp.gtOp2->gtOper is GT_CNS_INT (i.e. * 5),
7002         //     we can bump up the scale from 4 to 5*4, and then change index to index->gtOp.gtOp1.
7003         // Otherwise, we cannot optimize it. We will simply keep the original scale and index.
7004         scale *= index->gtOp.gtOp2->gtIntConCommon.IconValue();
7005         index = index->gtOp.gtOp1;
7006     }
7007
7008     assert (!bRngChk || index->gtOper != GT_COMMA);
7009
7010     if (pIndex)
7011         *pIndex = index;
7012
7013     return scale;
7014 }
7015
7016 /*****************************************************************************
7017  * Find the last assignment to of the local variable in the block. Return
7018  * RHS or NULL. If any local variable in the RHS has been killed in
7019  * intervening code, return NULL. If the variable being searched for is killed
7020  * in the intervening code, return NULL.
7021  *
7022  */
7023
7024 GenTreePtr Compiler::optFindLocalInit(BasicBlock *block, GenTreePtr local, VARSET_TP* pKilledInOut, bool* pLhsRhsKilledAfterInit)
7025 {
7026     assert(pKilledInOut);
7027     assert(pLhsRhsKilledAfterInit);
7028
7029     *pLhsRhsKilledAfterInit = false;
7030
7031     unsigned LclNum = local->gtLclVarCommon.gtLclNum;
7032
7033     GenTreePtr list = block->bbTreeList;
7034     if  (list == NULL)
7035     {
7036         return NULL;
7037     }
7038
7039     GenTreePtr rhs = NULL;
7040     GenTreePtr stmt = list;
7041     do
7042     {
7043         stmt = stmt->gtPrev;
7044         if  (stmt == NULL)
7045         {
7046             break;
7047         }
7048
7049         GenTreePtr tree = stmt->gtStmt.gtStmtExpr;
7050         // If we encounter an assignment to a local variable,
7051         if ((tree->OperKind() & GTK_ASGOP) && tree->gtOp.gtOp1->gtOper == GT_LCL_VAR)
7052         {
7053             // And the assigned variable equals the input local,
7054             if (tree->gtOp.gtOp1->gtLclVarCommon.gtLclNum == LclNum)
7055             {
7056                 // If the assignment is '=' and it is not a conditional, then return rhs.
7057                 if (tree->gtOper == GT_ASG && !(tree->gtFlags & GTF_COLON_COND))
7058                 {
7059                     rhs = tree->gtOp.gtOp2;
7060                 }
7061                 // If the assignment is 'op=' or a conditional equal, then the search ends here,
7062                 // as we found a kill to the input local.
7063                 else
7064                 {
7065                     *pLhsRhsKilledAfterInit = true;
7066                     assert(rhs == NULL);
7067                 }
7068                 break;
7069             }
7070             else
7071             {
7072                 LclVarDsc* varDsc = optIsTrackedLocal(tree->gtOp.gtOp1);
7073                 if (varDsc == NULL)
7074                 {
7075                     return NULL;
7076                 }
7077                 VarSetOps::AddElemD(this, *pKilledInOut, varDsc->lvVarIndex);
7078             }
7079         }
7080     }
7081     while (stmt != list);
7082
7083     if (rhs == NULL)
7084     {
7085         return NULL;
7086     }
7087
7088     // If any local in the RHS is killed in intervening code, or RHS has an indirection, return NULL.
7089     varRefKinds rhsRefs = VR_NONE;
7090     VARSET_TP VARSET_INIT_NOCOPY(rhsLocals, VarSetOps::UninitVal());
7091     bool b = lvaLclVarRefs(rhs, NULL, &rhsRefs, &rhsLocals);
7092     if (!b ||
7093         !VarSetOps::IsEmptyIntersection(this, rhsLocals, *pKilledInOut) ||
7094         (rhsRefs != VR_NONE))
7095     {
7096         // If RHS has been indirectly referenced, consider it a write and a kill.
7097         *pLhsRhsKilledAfterInit = true;
7098         return NULL;
7099     }
7100
7101     return rhs;
7102 }
7103
7104 /*****************************************************************************
7105  *
7106  *  Return true if "op1" is guaranteed to be less then or equal to "op2".
7107  */
7108
7109 #if FANCY_ARRAY_OPT
7110
7111 bool                Compiler::optIsNoMore(GenTreePtr op1, GenTreePtr op2,
7112                                           int add1, int add2)
7113 {
7114     if  (op1->gtOper == GT_CNS_INT &&
7115          op2->gtOper == GT_CNS_INT)
7116     {
7117         add1 += op1->gtIntCon.gtIconVal;
7118         add2 += op2->gtIntCon.gtIconVal;
7119     }
7120     else
7121     {
7122         /* Check for +/- constant on either operand */
7123
7124         if  (op1->gtOper == GT_ADD && op1->gtOp.gtOp2->gtOper == GT_CNS_INT)
7125         {
7126             add1 += op1->gtOp.gtOp2->gtIntCon.gtIconVal;
7127             op1   = op1->gtOp.gtOp1;
7128         }
7129
7130         if  (op2->gtOper == GT_ADD && op2->gtOp.gtOp2->gtOper == GT_CNS_INT)
7131         {
7132             add2 += op2->gtOp.gtOp2->gtIntCon.gtIconVal;
7133             op2   = op2->gtOp.gtOp1;
7134         }
7135
7136         /* We only allow local variable references */
7137
7138         if  (op1->gtOper != GT_LCL_VAR)
7139             return false;
7140         if  (op2->gtOper != GT_LCL_VAR)
7141             return false;
7142         if  (op1->gtLclVarCommon.gtLclNum != op2->gtLclVarCommon.gtLclNum)
7143             return false;
7144
7145         /* NOTE: Caller ensures that this variable has only one def */
7146
7147         // printf("limit [%d]:\n", add1); gtDispTree(op1);
7148         // printf("size  [%d]:\n", add2); gtDispTree(op2);
7149         // printf("\n");
7150
7151     }
7152
7153     return  (bool)(add1 <= add2);
7154 }
7155
7156 #endif
7157
7158 //------------------------------------------------------------------------------
7159 // optObtainLoopCloningOpts: Identify optimization candidates and update
7160 //      the "context" for array optimizations.
7161 //
7162 // Arguments:
7163 //     context     -  data structure where all loop cloning info is kept. The
7164 //                    optInfo fields of the context are updated with the
7165 //                    identified optimization candidates.
7166 //                      
7167 void Compiler::optObtainLoopCloningOpts(LoopCloneContext* context)
7168 {
7169     for (unsigned i = 0; i < optLoopCount; i++)
7170     {
7171         JITDUMP("Considering loop %d to clone for optimizations.\n", i);
7172         if (optIsLoopClonable(i))
7173         {
7174             if (!(optLoopTable[i].lpFlags & LPFLG_REMOVED))
7175             {
7176                 optIdentifyLoopOptInfo(i, context);
7177             }
7178         }
7179         JITDUMP("------------------------------------------------------------\n");
7180     }
7181     JITDUMP("\n");
7182 }
7183
7184 //------------------------------------------------------------------------
7185 // optIdentifyLoopOptInfo: Identify loop optimization candidates an also
7186 //      check if the loop is suitable for the optimizations performed.
7187 //
7188 // Arguments:
7189 //     loopNum     -  the current loop index for which conditions are derived.
7190 //     context     -  data structure where all loop cloning candidates will be
7191 //                    updated.
7192 //
7193 // Return Value:
7194 //     If the loop is not suitable for the optimizations, return false - context
7195 //     should not contain any optimization candidate for the loop if false.
7196 //     Else return true.
7197 //
7198 // Operation:
7199 //      Check if the loop is well formed for this optimization and identify the
7200 //      optimization candidates and update the "context" parameter with all the
7201 //      contextual information necessary to perform the optimization later.
7202 //
7203 bool               Compiler::optIdentifyLoopOptInfo(unsigned loopNum, LoopCloneContext* context)
7204 {
7205     noway_assert(loopNum < optLoopCount);
7206
7207     LoopDsc* pLoop = &optLoopTable[loopNum];
7208
7209     if (!(pLoop->lpFlags & LPFLG_ITER))
7210     {
7211         JITDUMP("> No iter flag on loop %d.\n", loopNum);
7212         return false;
7213     }
7214
7215     unsigned ivLclNum = pLoop->lpIterVar();
7216     if (lvaVarAddrExposed(ivLclNum))
7217     {
7218         JITDUMP("> Rejected V%02u as iter var because is address-exposed.\n", ivLclNum);
7219         return false;
7220     }
7221
7222     BasicBlock* head = pLoop->lpHead;
7223     BasicBlock* end = pLoop->lpBottom;
7224     BasicBlock* beg = head->bbNext;
7225
7226     if (end->bbJumpKind != BBJ_COND)
7227     {
7228         JITDUMP("> Couldn't find termination test.\n");
7229         return false;
7230     }
7231
7232     if  (end->bbJumpDest != beg)
7233     {
7234         JITDUMP("> Branch at loop 'end' not looping to 'begin'.\n");
7235         return false;
7236     }
7237
7238     // TODO-CQ: CLONE: Mark increasing or decreasing loops.
7239     if ((pLoop->lpIterOper() != GT_ASG_ADD && pLoop->lpIterOper() != GT_ADD) || (pLoop->lpIterConst() != 1))
7240     {
7241         JITDUMP("> Loop iteration operator not matching\n");
7242         return false;
7243     }
7244
7245     if ((pLoop->lpFlags & LPFLG_CONST_LIMIT) == 0 &&
7246         (pLoop->lpFlags & LPFLG_VAR_LIMIT) == 0 &&
7247         (pLoop->lpFlags & LPFLG_ARRLEN_LIMIT) == 0)
7248     {
7249         JITDUMP("> Loop limit is neither constant, variable or array length\n");
7250         return false;
7251     }
7252
7253     if (!(((pLoop->lpTestOper() == GT_LT || pLoop->lpTestOper() == GT_LE) && (pLoop->lpIterOper() == GT_ADD || pLoop->lpIterOper() == GT_ASG_ADD)) ||
7254         ((pLoop->lpTestOper() == GT_GT || pLoop->lpTestOper() == GT_GE) && (pLoop->lpIterOper() == GT_SUB || pLoop->lpIterOper() == GT_ASG_SUB))))
7255     {
7256         JITDUMP("> Loop test (%s) doesn't agree with the direction (%s) of the pLoop->\n",
7257                 GenTree::NodeName(pLoop->lpTestOper()), GenTree::NodeName(pLoop->lpIterOper()));
7258         return false;
7259     }
7260
7261     if (!(pLoop->lpTestTree->OperKind() & GTK_RELOP) || !(pLoop->lpTestTree->gtFlags & GTF_RELOP_ZTT))
7262     {
7263         JITDUMP("> Loop inversion NOT present, loop test [%06u] may not protect entry from head.\n", pLoop->lpTestTree->gtTreeID);
7264         return false;
7265     }
7266
7267 #ifdef DEBUG
7268     GenTreePtr op1 = pLoop->lpIterator();
7269     noway_assert((op1->gtOper == GT_LCL_VAR) && (op1->gtLclVarCommon.gtLclNum == ivLclNum));
7270 #endif
7271
7272     JITDUMP("Checking blocks BB%02d..BB%02d for optimization candidates\n", beg->bbNum, end->bbNext ? end->bbNext->bbNum : 0);
7273
7274     LoopCloneVisitorInfo info(context, loopNum, nullptr);
7275     for (BasicBlock* block = beg; block != end->bbNext; block = block->bbNext)
7276     {
7277         compCurBB = block;
7278         for (GenTreePtr stmt = block->bbTreeList; stmt; stmt = stmt->gtNext)
7279         {
7280             info.stmt = stmt;
7281             fgWalkTreePre(&stmt->gtStmt.gtStmtExpr, optCanOptimizeByLoopCloningVisitor, &info, false, false);
7282         }
7283     }
7284
7285     return true;
7286 }
7287
7288 //---------------------------------------------------------------------------------------------------------------
7289 //  optExtractArrIndex: Try to extract the array index from "tree".
7290 //
7291 //  Arguments:
7292 //      tree        the tree to be checked if it is the array [] operation.
7293 //      result      the extracted GT_INDEX information is updated in result.
7294 //      lhsNum      for the root level (function is recursive) callers should be BAD_VAR_NUM.
7295 //
7296 //  Return Value:
7297 //      Returns true if array index can be extracted, else, return false. See assumption about
7298 //      what will be extracted. The "result" variable's rank parameter is advanced for every
7299 //      dimension of [] encountered.
7300 //
7301 //  Operation:
7302 //      Given a "tree" extract the GT_INDEX node in "result" as ArrIndex. In FlowGraph morph
7303 //      we have converted a GT_INDEX tree into a scaled index base offset expression. We need
7304 //      to reconstruct this to be able to know if this is an array access.
7305 //
7306 //  Assumption:
7307 //      The method extracts only if the array base and indices are GT_LCL_VAR.
7308 //
7309 //  TODO-CQ: CLONE: After morph make sure this method extracts values before morph.
7310 //
7311 //    [000000001AF828D8] ---XG-------                     indir     int   
7312 //    [000000001AF872C8] ------------                           const     long   16 Fseq[#FirstElem]
7313 //    [000000001AF87340] ------------                        +         byref 
7314 //    [000000001AF87160] -------N----                                 const     long   2
7315 //    [000000001AF871D8] ------------                              <<        long  
7316 //    [000000001AF870C0] ------------                                 cast      long <- int
7317 //    [000000001AF86F30] i-----------                                    lclVar    int    V04 loc0         
7318 //    [000000001AF87250] ------------                           +         byref 
7319 //    [000000001AF86EB8] ------------                              lclVar    ref    V01 arg1         
7320 //    [000000001AF87468] ---XG-------                  comma     int   
7321 //    [000000001AF87020] ---X--------                     arrBndsChk void  
7322 //    [000000001AF86FA8] ---X--------                        arrLen    int   
7323 //    [000000001AF827E8] ------------                           lclVar    ref    V01 arg1         
7324 //    [000000001AF82860] ------------                        lclVar    int    V04 loc0         
7325 //    [000000001AF829F0] -A-XG-------               =         int   
7326 //    [000000001AF82978] D------N----                  lclVar    int    V06 tmp0         
7327 //
7328 bool Compiler::optExtractArrIndex(GenTreePtr tree, ArrIndex* result, unsigned lhsNum)
7329 {
7330     if (tree->gtOper != GT_COMMA)
7331     {
7332         return false;
7333     }
7334     GenTreePtr before = tree->gtGetOp1();
7335     if (before->gtOper != GT_ARR_BOUNDS_CHECK)
7336     {
7337         return false;
7338     }
7339     GenTreeBoundsChk* arrBndsChk = before->AsBoundsChk();
7340     if (arrBndsChk->gtArrLen->gtGetOp1()->gtOper != GT_LCL_VAR)
7341     {
7342         return false;
7343     }
7344     if (arrBndsChk->gtIndex->gtOper != GT_LCL_VAR)
7345     {
7346         return false;
7347     }
7348     unsigned arrLcl = arrBndsChk->gtArrLen->gtGetOp1()->gtLclVarCommon.gtLclNum;
7349     if (lhsNum != BAD_VAR_NUM && arrLcl != lhsNum)
7350     {
7351         return false;
7352     }
7353
7354     unsigned indLcl = arrBndsChk->gtIndex->gtLclVarCommon.gtLclNum;
7355
7356     GenTreePtr after = tree->gtGetOp2();
7357
7358     if (after->gtOper != GT_IND)
7359     {
7360         return false;
7361     }
7362     GenTreePtr sibo = after->gtGetOp1();
7363     if (sibo->gtOper != GT_ADD)
7364     {
7365         return false;
7366     }
7367     GenTreePtr sib = sibo->gtGetOp1();
7368     GenTreePtr ofs = sibo->gtGetOp2();
7369     if (ofs->gtOper != GT_CNS_INT)
7370     {
7371         return false;
7372     }
7373     if (sib->gtOper != GT_ADD)
7374     {
7375         return false;
7376     }
7377     GenTreePtr si = sib->gtGetOp2();
7378     GenTreePtr base = sib->gtGetOp1();
7379     if (si->gtOper != GT_LSH)
7380     {
7381         return false;
7382     }
7383     if (base->OperGet() != GT_LCL_VAR || base->gtLclVarCommon.gtLclNum != arrLcl)
7384     {
7385         return false;
7386     }
7387     GenTreePtr scale = si->gtGetOp2();
7388     GenTreePtr index = si->gtGetOp1();
7389     if (scale->gtOper != GT_CNS_INT)
7390     {
7391         return false;
7392     }
7393 #ifdef _TARGET_AMD64_
7394     if (index->gtOper != GT_CAST)
7395     {
7396         return false;
7397     }
7398     GenTreePtr indexVar = index->gtGetOp1();
7399 #else
7400     GenTreePtr indexVar = index;
7401 #endif
7402     if (indexVar->gtOper != GT_LCL_VAR || indexVar->gtLclVarCommon.gtLclNum != indLcl)
7403     {
7404         return false;
7405     }
7406     if (lhsNum == BAD_VAR_NUM)
7407     {
7408         result->arrLcl = arrLcl;
7409     }
7410     result->indLcls.Push(indLcl);
7411     result->bndsChks.Push(tree);
7412     result->useBlock = compCurBB;
7413     result->rank++;
7414
7415     return true;
7416 }
7417
7418 //---------------------------------------------------------------------------------------------------------------
7419 //  optReconstructArrIndex: Reconstruct array index.
7420 //
7421 //  Arguments:
7422 //      tree        the tree to be checked if it is an array [][][] operation.
7423 //      result      the extracted GT_INDEX information.
7424 //      lhsNum      for the root level (function is recursive) callers should be BAD_VAR_NUM.
7425 //
7426 //  Return Value:
7427 //      Returns true if array index can be extracted, else, return false. "rank" field in
7428 //      "result" contains the array access depth. The "indLcls" fields contain the indices.
7429 //
7430 //  Operation:
7431 //      Recursively look for a list of array indices. In the example below, we encounter,
7432 //      V03 = ((V05 = V00[V01]), (V05[V02])) which corresponds to access of V00[V01][V02]
7433 //      The return value would then be:
7434 //      ArrIndex result { arrLcl: V00, indLcls: [V01, V02], rank: 2 }
7435 //
7436 //      V00[V01][V02] would be morphed as:
7437 //
7438 //      [000000001B366848] ---XG-------                        indir     int   
7439 //      [000000001B36BC50] ------------                                 V05 + (V02 << 2) + 16
7440 //      [000000001B36C200] ---XG-------                     comma     int   
7441 //      [000000001B36BDB8] ---X--------                        arrBndsChk(V05, V02)
7442 //      [000000001B36C278] -A-XG-------                  comma     int   
7443 //      [000000001B366730] R--XG-------                           indir     ref
7444 //      [000000001B36C2F0] ------------                             V00 + (V01 << 3) + 24
7445 //      [000000001B36C818] ---XG-------                        comma     ref   
7446 //      [000000001B36C458] ---X--------                           arrBndsChk(V00, V01)
7447 //      [000000001B36BB60] -A-XG-------                     =         ref   
7448 //      [000000001B36BAE8] D------N----                        lclVar    ref    V05 tmp2         
7449 //      [000000001B36A668] -A-XG-------               =         int   
7450 //      [000000001B36A5F0] D------N----                  lclVar    int    V03 tmp0
7451 //
7452 //  Assumption:
7453 //      The method extracts only if the array base and indices are GT_LCL_VAR.
7454 //
7455 bool Compiler::optReconstructArrIndex(GenTreePtr tree, ArrIndex* result, unsigned lhsNum)
7456 {
7457     // If we can extract "tree" (which is a top level comma) return.
7458     if (optExtractArrIndex(tree, result, lhsNum))
7459     {
7460         return true;
7461     }
7462     // We have a comma (check if array base expr is computed in "before"), descend further.
7463     else if (tree->OperGet() == GT_COMMA)
7464     {
7465         GenTreePtr before = tree->gtGetOp1();
7466         // "before" should evaluate an array base for the "after" indexing.
7467         if (before->OperGet() != GT_ASG)
7468         {
7469             return false;
7470         }
7471         GenTreePtr lhs = before->gtGetOp1();
7472         GenTreePtr rhs = before->gtGetOp2();
7473
7474         // "rhs" should contain an GT_INDEX
7475         if (!lhs->IsLocal() || !optReconstructArrIndex(rhs, result, lhsNum))
7476         {
7477             return false;
7478         }
7479         unsigned lhsNum = lhs->gtLclVarCommon.gtLclNum;
7480         GenTreePtr after = tree->gtGetOp2();
7481         // Pass the "lhsNum", so we can verify if indeed it is used as the array base.
7482         return optExtractArrIndex(after, result, lhsNum);
7483     }
7484     return false;
7485 }
7486
7487 /* static */
7488 Compiler::fgWalkResult Compiler::optCanOptimizeByLoopCloningVisitor(GenTreePtr* pTree, Compiler::fgWalkData* data)
7489 {
7490     return data->compiler->optCanOptimizeByLoopCloning(*pTree, (LoopCloneVisitorInfo*) data->pCallbackData);
7491 }
7492
7493
7494 //-------------------------------------------------------------------------
7495 //  optIsStackLocalInvariant: Is stack local invariant in loop.
7496 //
7497 //  Arguments:
7498 //      loopNum      The loop in which the variable is tested for invariance.
7499 //      lclNum       The local that is tested for invariance in the loop.
7500 //
7501 //  Return Value:
7502 //      Returns true if the variable is loop invariant in loopNum.
7503 //
7504 bool Compiler::optIsStackLocalInvariant(unsigned loopNum, unsigned lclNum)
7505 {
7506     if (lvaVarAddrExposed(lclNum))
7507     {
7508         return false;
7509     }
7510     if (optIsVarAssgLoop(loopNum, lclNum))
7511     {
7512         return false;
7513     }
7514     return true;
7515 }
7516
7517 //----------------------------------------------------------------------------------------------
7518 //  optCanOptimizeByLoopCloning: Check if the tree can be optimized by loop cloning and if so,
7519 //      identify as potential candidate and update the loop context.
7520 //
7521 //  Arguments:
7522 //      tree         The tree encountered during the tree walk.
7523 //      info         Supplies information about the current block or stmt in which the tree is.
7524 //                   Also supplies the "context" pointer for updating with loop cloning
7525 //                   candidates. Also supplies loopNum.
7526 //
7527 //  Operation:
7528 //      If array index can be reconstructed, check if the iter var of the loop matches the
7529 //      array index var in some dim. Also ensure other index vars before the identified
7530 //      dim are loop invariant.
7531 //  
7532 //  Return Value:
7533 //      Skip sub trees if the optimization candidate is identified or else continue walking
7534 //
7535 Compiler::fgWalkResult Compiler::optCanOptimizeByLoopCloning(GenTreePtr tree, LoopCloneVisitorInfo* info)
7536 {
7537     ArrIndex arrIndex(getAllocator());
7538
7539     // Check if array index can be optimized.
7540     if (optReconstructArrIndex(tree, &arrIndex, BAD_VAR_NUM))
7541     {
7542         assert(tree->gtOper == GT_COMMA);
7543 #ifdef DEBUG
7544         if (verbose)
7545         {
7546             JITDUMP("Found ArrIndex at tree ");
7547             printTreeID(tree);
7548             printf(" which is equivalent to: ");
7549             arrIndex.Print();
7550             JITDUMP("\n");
7551         }
7552 #endif
7553         if (!optIsStackLocalInvariant(info->loopNum, arrIndex.arrLcl))
7554         {
7555             return WALK_SKIP_SUBTREES;
7556         }
7557
7558         // Walk the dimensions and see if iterVar of the loop is used as index.
7559         for (unsigned dim = 0; dim < arrIndex.rank; ++dim)
7560         {
7561             // Is index variable also used as the loop iter var.
7562             if (arrIndex.indLcls[dim] == optLoopTable[info->loopNum].lpIterVar())
7563             {
7564                 // Check the previous indices are all loop invariant.
7565                 for (unsigned dim2 = 0; dim2 < dim; ++dim2)
7566                 {
7567                     if (optIsVarAssgLoop(info->loopNum, arrIndex.indLcls[dim2]))
7568                     {
7569                         JITDUMP("V%02d is assigned in loop\n", arrIndex.indLcls[dim2]);
7570                         return WALK_SKIP_SUBTREES;
7571                     }
7572                 }
7573 #ifdef DEBUG
7574                 if (verbose)
7575                 {
7576                     JITDUMP("Loop %d can be cloned for ArrIndex ", info->loopNum);
7577                     arrIndex.Print();
7578                     JITDUMP(" on dim %d\n", dim);
7579                 }
7580 #endif
7581                 // Update the loop context.
7582                 info->context->EnsureLoopOptInfo(info->loopNum)->Push(new (this, CMK_LoopOpt) LcJaggedArrayOptInfo(arrIndex, dim, info->stmt));
7583             }
7584             else
7585             {
7586                 JITDUMP("Induction V%02d is not used as index on dim %d\n", optLoopTable[info->loopNum].lpIterVar(), dim);
7587             }
7588         }
7589         return WALK_SKIP_SUBTREES;
7590     }
7591     else if (tree->gtOper == GT_ARR_ELEM)
7592     {
7593         // TODO-CQ: CLONE: Implement.
7594         return WALK_SKIP_SUBTREES;
7595     }
7596     return WALK_CONTINUE;
7597 }
7598
7599 struct optRangeCheckDsc
7600 {
7601     Compiler* pCompiler;
7602     bool      bValidIndex;
7603 };
7604 /*
7605     Walk to make sure that only locals and constants are contained in the index
7606     for a range check
7607 */
7608 Compiler::fgWalkResult      Compiler::optValidRangeCheckIndex(GenTreePtr * pTree, fgWalkData *data)
7609 {
7610     GenTreePtr        tree = *pTree;
7611     optRangeCheckDsc* pData= (optRangeCheckDsc*) data->pCallbackData;
7612
7613     if (tree->gtOper == GT_IND || tree->gtOper == GT_CLS_VAR || 
7614         tree->gtOper == GT_FIELD || tree->gtOper == GT_LCL_FLD)
7615     {
7616         pData->bValidIndex = false;
7617         return WALK_ABORT;
7618     }
7619
7620     if (tree->gtOper == GT_LCL_VAR)
7621     {
7622         if (pData->pCompiler->lvaTable[tree->gtLclVarCommon.gtLclNum].lvAddrExposed)
7623         {
7624             pData->bValidIndex = false;
7625             return WALK_ABORT;
7626         }
7627     }
7628
7629     return WALK_CONTINUE;
7630 }
7631
7632 /*
7633     returns true if a range check can legally be removed (for the moment it checks
7634     that the array is a local array (non subject to racing conditions) and that the
7635     index is either a constant or a local
7636 */
7637 bool Compiler::optIsRangeCheckRemovable(GenTreePtr tree)
7638 {
7639     noway_assert(tree->gtOper == GT_ARR_BOUNDS_CHECK);
7640     GenTreeBoundsChk* bndsChk = tree->AsBoundsChk();
7641     GenTreePtr pArray = bndsChk->GetArray();
7642     if (pArray == NULL && !bndsChk->gtArrLen->IsCnsIntOrI())
7643     {
7644         return false;
7645     }
7646     GenTreePtr pIndex = bndsChk->gtIndex;
7647     
7648     // The length must be a constant (the pArray == NULL case) or the array reference must be a local. 
7649     // Otherwise we can be targeted by malicious race-conditions.
7650     if (pArray != NULL)
7651     {
7652         if ( pArray->gtOper != GT_LCL_VAR )
7653         {        
7654
7655 #ifdef DEBUG
7656             if (verbose)
7657             {
7658                 printf("Can't remove range check if the array isn't referenced with a local\n");
7659                 gtDispTree(pArray);
7660             }
7661 #endif
7662             return false;
7663         }
7664         else
7665         {
7666             noway_assert(pArray->gtType == TYP_REF);    
7667             noway_assert(pArray->gtLclVarCommon.gtLclNum < lvaCount);
7668
7669             if (lvaTable[pArray->gtLclVarCommon.gtLclNum].lvAddrExposed)
7670             {
7671                 // If the array address has been taken, don't do the optimization
7672                 // (this restriction can be lowered a bit, but i don't think it's worth it)
7673                 CLANG_FORMAT_COMMENT_ANCHOR;
7674 #ifdef DEBUG
7675                 if (verbose)
7676                 {
7677                     printf("Can't remove range check if the array has its address taken\n");
7678                     gtDispTree(pArray);
7679                 }
7680 #endif
7681                 return false;
7682             }
7683         }
7684     }
7685     
7686     
7687     optRangeCheckDsc Data;
7688     Data.pCompiler  =this;
7689     Data.bValidIndex=true;
7690
7691     fgWalkTreePre(&pIndex, optValidRangeCheckIndex, &Data);
7692         
7693     if (!Data.bValidIndex)
7694     {
7695         #ifdef DEBUG
7696         if (verbose)
7697         {
7698             printf("Can't remove range check with this index");
7699             gtDispTree(pIndex);
7700         }
7701         #endif
7702
7703         return false;
7704     }
7705     
7706
7707     return true;
7708 }
7709
7710 /******************************************************************************
7711  *
7712  * Replace x==null with (x|x)==0 if x is a GC-type.
7713  * This will stress code-gen and the emitter to make sure they support such trees.
7714  */
7715
7716 #ifdef DEBUG
7717
7718 void            Compiler::optOptimizeBoolsGcStress(BasicBlock * condBlock)
7719 {
7720     if (!compStressCompile(STRESS_OPT_BOOLS_GC, 20))
7721         return;
7722     
7723     noway_assert(condBlock->bbJumpKind == BBJ_COND);
7724     GenTreePtr  condStmt = condBlock->bbTreeList->gtPrev->gtStmt.gtStmtExpr;
7725
7726     noway_assert(condStmt->gtOper == GT_JTRUE);
7727
7728     bool        isBool;
7729     GenTreePtr  relop;
7730
7731     GenTreePtr  comparand = optIsBoolCond(condStmt, &relop, &isBool);
7732     
7733     if (comparand == NULL || !varTypeIsGC(comparand->TypeGet()))
7734         return;
7735
7736     if (comparand->gtFlags & (GTF_ASG|GTF_CALL|GTF_ORDER_SIDEEFF))
7737         return;
7738
7739     GenTreePtr  comparandClone = gtCloneExpr(comparand);
7740
7741     // Bump up the ref-counts of any variables in 'comparandClone'
7742     compCurBB = condBlock;
7743     fgWalkTreePre(&comparandClone, Compiler::lvaIncRefCntsCB, (void *)this, true);
7744     
7745     noway_assert(relop->gtOp.gtOp1 == comparand);
7746     genTreeOps oper = compStressCompile(STRESS_OPT_BOOLS_GC, 50) ? GT_OR : GT_AND;
7747     relop->gtOp.gtOp1 = gtNewOperNode(oper, TYP_I_IMPL, comparand, comparandClone);
7748
7749     // Comparand type is already checked, and we have const int, there is no harm
7750     // morphing it into a TYP_I_IMPL.
7751     noway_assert(relop->gtOp.gtOp2->gtOper == GT_CNS_INT);
7752     relop->gtOp.gtOp2->gtType = TYP_I_IMPL;
7753 }
7754
7755 #endif
7756
7757 /******************************************************************************
7758  * Function used by folding of boolean conditionals
7759  * Given a GT_JTRUE node, checks that it is a boolean comparison of the form
7760  *    "if (boolVal ==/!=  0/1)". This is translated into a GT_EQ node with "op1"
7761  *    being a boolean lclVar and "op2" the const 0/1.
7762  * On success, the comparand (ie. boolVal) is returned.   Else NULL.
7763  * compPtr returns the compare node (i.e. GT_EQ or GT_NE node)
7764  * boolPtr returns whether the comparand is a boolean value (must be 0 or 1).
7765  * When return boolPtr equal to true, if the comparison was against a 1 (i.e true)
7766  * value then we morph the tree by reversing the GT_EQ/GT_NE and change the 1 to 0.
7767  */
7768
7769 GenTree *           Compiler::optIsBoolCond(GenTree *   condBranch,
7770                                             GenTree * * compPtr,
7771                                             bool      * boolPtr)
7772 {
7773     bool isBool = false;
7774
7775     noway_assert(condBranch->gtOper == GT_JTRUE);
7776     GenTree *   cond = condBranch->gtOp.gtOp1;
7777
7778     /* The condition must be "!= 0" or "== 0" */
7779
7780     if ((cond->gtOper != GT_EQ) && (cond->gtOper != GT_NE))
7781         return nullptr;
7782
7783     /* Return the compare node to the caller */
7784
7785     *compPtr = cond;
7786
7787     /* Get hold of the comparands */
7788
7789     GenTree *   opr1 = cond->gtOp.gtOp1;
7790     GenTree *   opr2 = cond->gtOp.gtOp2;
7791
7792     if  (opr2->gtOper != GT_CNS_INT)
7793         return  nullptr;
7794
7795     if (!opr2->IsIntegralConst(0) && !opr2->IsIntegralConst(1))
7796         return nullptr;
7797
7798     ssize_t ival2 = opr2->gtIntCon.gtIconVal;
7799
7800     /* Is the value a boolean?
7801      * We can either have a boolean expression (marked GTF_BOOLEAN) or
7802      * a local variable that is marked as being boolean (lvIsBoolean) */
7803
7804     if  (opr1->gtFlags & GTF_BOOLEAN)
7805     {
7806         isBool = true;
7807     }
7808     else if ((opr1->gtOper == GT_CNS_INT) &&
7809              (opr1->IsIntegralConst(0) || opr1->IsIntegralConst(1)))
7810     {
7811         isBool = true;
7812     }
7813     else if (opr1->gtOper == GT_LCL_VAR)
7814     {
7815         /* is it a boolean local variable */
7816
7817         unsigned    lclNum = opr1->gtLclVarCommon.gtLclNum;
7818         noway_assert(lclNum < lvaCount);
7819
7820         if (lvaTable[lclNum].lvIsBoolean)
7821             isBool = true;
7822     }
7823
7824     /* Was our comparison against the constant 1 (i.e. true) */
7825     if  (ival2 == 1)
7826     {
7827         // If this is a boolean expression tree we can reverse the relop 
7828         // and change the true to false.
7829         if (isBool)
7830         {
7831             gtReverseCond(cond);
7832             opr2->gtIntCon.gtIconVal = 0;
7833         }
7834         else
7835             return NULL;
7836     }
7837
7838     *boolPtr = isBool;
7839     return opr1;
7840 }
7841
7842
7843 void                Compiler::optOptimizeBools()
7844 {
7845 #ifdef DEBUG
7846     if  (verbose) 
7847     {
7848         printf("*************** In optOptimizeBools()\n");
7849         if (verboseTrees)
7850         {
7851             printf("Blocks/Trees before phase\n");
7852             fgDispBasicBlocks(true);
7853         }
7854     }
7855 #endif
7856     bool            change;
7857
7858     do
7859     {
7860         change = false;
7861
7862         for (BasicBlock * b1 = fgFirstBB; b1; b1 = b1->bbNext)
7863         {
7864             /* We're only interested in conditional jumps here */
7865
7866             if  (b1->bbJumpKind != BBJ_COND)
7867                 continue;
7868
7869             /* If there is no next block, we're done */
7870
7871             BasicBlock * b2 = b1->bbNext;
7872             if  (!b2)
7873                 break;
7874
7875             /* The next block must not be marked as BBF_DONT_REMOVE */
7876             if  (b2->bbFlags & BBF_DONT_REMOVE)
7877                 continue;
7878
7879             /* The next block also needs to be a condition */
7880
7881             if  (b2->bbJumpKind != BBJ_COND)
7882             {
7883 #ifdef DEBUG
7884                 optOptimizeBoolsGcStress(b1);
7885 #endif
7886                 continue;
7887             }
7888
7889             bool    sameTarget; // Do b1 and b2 have the same bbJumpDest?
7890
7891             if      (b1->bbJumpDest == b2->bbJumpDest)
7892             {
7893                 /* Given the following sequence of blocks :
7894                         B1: brtrue(t1, BX)
7895                         B2: brtrue(t2, BX)
7896                         B3:
7897                    we wil try to fold it to :
7898                         B1: brtrue(t1|t2, BX)
7899                         B3:
7900                 */
7901
7902                 sameTarget = true;
7903             }
7904             else if (b1->bbJumpDest == b2->bbNext)  /*b1->bbJumpDest->bbNum == n1+2*/
7905             {
7906                 /* Given the following sequence of blocks :
7907                         B1: brtrue(t1, B3)
7908                         B2: brtrue(t2, BX)
7909                         B3:
7910                    we will try to fold it to :
7911                         B1: brtrue((!t1)&&t2, B3)
7912                         B3:
7913                 */
7914
7915                 sameTarget = false;
7916             }
7917             else
7918             {
7919                 continue;
7920             }
7921
7922             /* The second block must contain a single statement */
7923
7924             GenTreePtr s2 = b2->bbTreeList;
7925             if  (s2->gtPrev != s2)
7926                 continue;
7927
7928             noway_assert(s2->gtOper == GT_STMT);
7929             GenTreePtr  t2 = s2->gtStmt.gtStmtExpr;
7930             noway_assert(t2->gtOper == GT_JTRUE);
7931
7932             /* Find the condition for the first block */
7933
7934             GenTreePtr  s1 = b1->bbTreeList->gtPrev;
7935
7936             noway_assert(s1->gtOper == GT_STMT);
7937             GenTreePtr  t1 = s1->gtStmt.gtStmtExpr;
7938             noway_assert(t1->gtOper == GT_JTRUE);
7939
7940             if  (b2->countOfInEdges() > 1)
7941                 continue;
7942
7943             /* Find the branch conditions of b1 and b2 */
7944
7945             bool        bool1, bool2;
7946
7947             GenTreePtr  c1 = optIsBoolCond(t1, &t1, &bool1);
7948             if (!c1) continue;
7949
7950             GenTreePtr  c2 = optIsBoolCond(t2, &t2, &bool2);
7951             if (!c2) continue;
7952
7953             noway_assert(t1->gtOper == GT_EQ || t1->gtOper == GT_NE && t1->gtOp.gtOp1 == c1);
7954             noway_assert(t2->gtOper == GT_EQ || t2->gtOper == GT_NE && t2->gtOp.gtOp1 == c2);
7955
7956             // Leave out floats where the bit-representation is more complicated 
7957             // - there are two representations for 0.
7958             //            
7959             if (varTypeIsFloating(c1->TypeGet()) || varTypeIsFloating(c2->TypeGet()))
7960                 continue;
7961
7962             // Make sure the types involved are of the same sizes
7963             if (genTypeSize(c1->TypeGet()) != genTypeSize(c2->TypeGet()))
7964                 continue;
7965             if (genTypeSize(t1->TypeGet()) != genTypeSize(t2->TypeGet()))
7966                 continue;
7967 #ifdef _TARGET_ARMARCH_
7968             // Skip the small operand which we cannot encode.
7969             if (varTypeIsSmall(c1->TypeGet()))
7970                 continue;
7971 #endif
7972             /* The second condition must not contain side effects */
7973
7974             if  (c2->gtFlags & GTF_GLOB_EFFECT)
7975                 continue;
7976
7977             /* The second condition must not be too expensive */
7978
7979             gtPrepareCost(c2);
7980
7981             if (c2->gtCostEx > 12)
7982                 continue;
7983
7984             genTreeOps      foldOp;
7985             genTreeOps      cmpOp;
7986             var_types       foldType = c1->TypeGet();
7987             if (varTypeIsGC(foldType))
7988             {
7989                 foldType = TYP_I_IMPL;
7990             }
7991
7992             if (sameTarget)
7993             {
7994                 /* Both conditions must be the same */
7995
7996                 if (t1->gtOper != t2->gtOper)
7997                     continue;
7998
7999                 if (t1->gtOper == GT_EQ)
8000                 {
8001                     /* t1:c1==0 t2:c2==0 ==> Branch to BX if either value is 0
8002                        So we will branch to BX if (c1&c2)==0 */
8003
8004                     foldOp = GT_AND;
8005                     cmpOp  = GT_EQ;
8006                 }
8007                 else
8008                 {
8009                     /* t1:c1!=0 t2:c2!=0 ==> Branch to BX if either value is non-0
8010                        So we will branch to BX if (c1|c2)!=0 */
8011
8012                     foldOp = GT_OR;
8013                     cmpOp  = GT_NE;
8014                 }
8015             }
8016             else
8017             {
8018                 /* The b1 condition must be the reverse of the b2 condition */
8019
8020                 if (t1->gtOper == t2->gtOper)
8021                     continue;
8022
8023                 if (t1->gtOper == GT_EQ)
8024                 {
8025                     /* t1:c1==0 t2:c2!=0 ==> Branch to BX if both values are non-0
8026                        So we will branch to BX if (c1&c2)!=0 */
8027
8028                     foldOp = GT_AND;
8029                     cmpOp  = GT_NE;
8030                 }
8031                 else
8032                 {
8033                     /* t1:c1!=0 t2:c2==0 ==> Branch to BX if both values are 0
8034                        So we will branch to BX if (c1|c2)==0 */
8035
8036                     foldOp = GT_OR;
8037                     cmpOp  = GT_EQ;
8038                 }
8039             }
8040
8041             // Anding requires both values to be 0 or 1
8042
8043             if ((foldOp == GT_AND) && (!bool1 || !bool2))
8044                 continue;
8045
8046             //
8047             // Now update the trees
8048             //
8049             GenTreePtr cmpOp1 = gtNewOperNode(foldOp, foldType, c1, c2);
8050             if (bool1 && bool2)
8051             {
8052                 /* When we 'OR'/'AND' two booleans, the result is boolean as well */
8053                 cmpOp1->gtFlags |= GTF_BOOLEAN;
8054             }
8055
8056             t1->SetOper(cmpOp);
8057             t1->gtOp.gtOp1 = cmpOp1;
8058             t1->gtOp.gtOp2->gtType = foldType; // Could have been varTypeIsGC()
8059
8060 #if FEATURE_SET_FLAGS
8061             // For comparisons against zero we will have the GTF_SET_FLAGS set
8062             // and this can cause an assert to fire in fgMoveOpsLeft(GenTreePtr tree)
8063             // during the CSE phase.
8064             //
8065             // So make sure to clear any GTF_SET_FLAGS bit on these operations
8066             // as they are no longer feeding directly into a comparisons against zero
8067
8068             // Make sure that the GTF_SET_FLAGS bit is cleared.
8069             // Fix 388436 ARM JitStress WP7
8070             c1->gtFlags &= ~GTF_SET_FLAGS;
8071             c2->gtFlags &= ~GTF_SET_FLAGS;
8072
8073             // The new top level node that we just created does feed directly into
8074             // a comparison against zero, so set the GTF_SET_FLAGS bit so that
8075             // we generate an instuction that sets the flags, which allows us 
8076             // to omit the cmp with zero instruction.
8077
8078             // Request that the codegen for cmpOp1 sets the condition flags
8079             // when it generates the code for cmpOp1.
8080             //
8081             cmpOp1->gtRequestSetFlags();
8082 #endif      
8083
8084              flowList * edge1 = fgGetPredForBlock(b1->bbJumpDest, b1);
8085              flowList * edge2;
8086
8087             /* Modify the target of the conditional jump and update bbRefs and bbPreds */
8088
8089             if (sameTarget)
8090             {
8091                 edge2 = fgGetPredForBlock(b2->bbJumpDest, b2);
8092             }
8093             else
8094             {
8095                 edge2 = fgGetPredForBlock(b2->bbNext, b2);
8096
8097                 fgRemoveRefPred(b1->bbJumpDest, b1);
8098
8099                 b1->bbJumpDest = b2->bbJumpDest;
8100
8101                 fgAddRefPred(b2->bbJumpDest, b1);
8102             }
8103
8104             noway_assert(edge1 != NULL);
8105             noway_assert(edge2 != NULL);
8106
8107             BasicBlock::weight_t edgeSumMin = edge1->flEdgeWeightMin + edge2->flEdgeWeightMin;
8108             BasicBlock::weight_t edgeSumMax = edge1->flEdgeWeightMax + edge2->flEdgeWeightMax;
8109             if ((edgeSumMax >= edge1->flEdgeWeightMax) && (edgeSumMax >= edge2->flEdgeWeightMax))
8110             {
8111                 edge1->flEdgeWeightMin = edgeSumMin;
8112                 edge1->flEdgeWeightMax = edgeSumMax;
8113             }
8114             else
8115             {
8116                 edge1->flEdgeWeightMin = BB_ZERO_WEIGHT;
8117                 edge1->flEdgeWeightMax = BB_MAX_WEIGHT;
8118             }
8119
8120             /* Get rid of the second block (which is a BBJ_COND) */
8121
8122             noway_assert(b1->bbJumpKind == BBJ_COND);
8123             noway_assert(b2->bbJumpKind == BBJ_COND);
8124             noway_assert(b1->bbJumpDest == b2->bbJumpDest);
8125             noway_assert(b1->bbNext == b2); noway_assert(b2->bbNext);           
8126
8127             fgUnlinkBlock(b2);
8128             b2->bbFlags |= BBF_REMOVED;
8129
8130             // If b2 was the last block of a try or handler, update the EH table.
8131
8132             ehUpdateForDeletedBlock(b2);
8133
8134             /* Update bbRefs and bbPreds */
8135
8136             /* Replace pred 'b2' for 'b2->bbNext' with 'b1'
8137              * Remove  pred 'b2' for 'b2->bbJumpDest' */
8138
8139             fgReplacePred(b2->bbNext, b2, b1);
8140
8141             fgRemoveRefPred(b2->bbJumpDest, b2);
8142
8143             /* Update the block numbers and try again */
8144
8145             change = true;
8146 /*
8147             do
8148             {
8149                 b2->bbNum = ++n1;
8150                 b2 = b2->bbNext;
8151             }
8152             while (b2);
8153 */
8154
8155             // Update loop table
8156             fgUpdateLoopsAfterCompacting(b1, b2);
8157             
8158 #ifdef DEBUG
8159             if  (verbose)
8160             {
8161                 printf("Folded %sboolean conditions of BB%02u and BB%02u to :\n",
8162                        c2->OperIsLeaf() ? "" : "non-leaf ",
8163                        b1->bbNum, b2->bbNum);
8164                 gtDispTree(s1); printf("\n");
8165             }
8166 #endif
8167         }
8168     }
8169     while (change);
8170
8171 #ifdef DEBUG
8172     fgDebugCheckBBlist();
8173 #endif
8174 }