Merge pull request #6285 from JosephTremoulet/LenProp
[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     // Flag the block that received the copy as potentially having an array/vtable
3459     // reference if the block copied from did; this is a conservative guess.
3460     if (auto copyFlags = bTest->bbFlags & (BBF_HAS_VTABREF | BBF_HAS_IDX_LEN))
3461     {
3462         block->bbFlags |= copyFlags;
3463     }
3464
3465     // If we have profile data for all blocks and we know that we are cloning the 
3466     //  bTest block into block and thus changing the control flow from block so
3467     //  that it no longer goes directly to bTest anymore, we have to adjust the 
3468     //  weight of bTest by subtracting out the weight of block.
3469     //
3470     if (allProfileWeightsAreValid)
3471     {
3472         //
3473         // Some additional sanity checks before adjusting the weight of bTest
3474         //
3475         if ((weightNext > 0) && (weightTest >= weightBlock) && (weightTest != BB_MAX_WEIGHT))
3476         {
3477             // Get the two edge that flow out of bTest
3478             flowList * edgeToNext = fgGetPredForBlock(bTest->bbNext, bTest);
3479             flowList * edgeToJump = fgGetPredForBlock(bTest->bbJumpDest, bTest);
3480
3481             // Calculate the new weight for block bTest
3482
3483             BasicBlock::weight_t newWeightTest = (weightTest > weightBlock)
3484                                                  ? (weightTest - weightBlock)
3485                                                  : BB_ZERO_WEIGHT;
3486             bTest->bbWeight = newWeightTest;
3487
3488             if (newWeightTest == BB_ZERO_WEIGHT)
3489             {
3490                 bTest->bbFlags |= BBF_RUN_RARELY;
3491                 // All out edge weights are set to zero
3492                 edgeToNext->flEdgeWeightMin = BB_ZERO_WEIGHT;
3493                 edgeToNext->flEdgeWeightMax = BB_ZERO_WEIGHT;
3494                 edgeToJump->flEdgeWeightMin = BB_ZERO_WEIGHT;
3495                 edgeToJump->flEdgeWeightMax = BB_ZERO_WEIGHT;
3496             }
3497             else
3498             {
3499                 // Update the our edge weights
3500                 edgeToNext->flEdgeWeightMin = BB_ZERO_WEIGHT;
3501                 edgeToNext->flEdgeWeightMax = min(edgeToNext->flEdgeWeightMax, newWeightTest); 
3502                 edgeToJump->flEdgeWeightMin = BB_ZERO_WEIGHT;
3503                 edgeToJump->flEdgeWeightMax = min(edgeToJump->flEdgeWeightMax, newWeightTest);    
3504             }
3505          }
3506     }
3507
3508     /* Change the block to end with a conditional jump */
3509
3510     block->bbJumpKind = BBJ_COND;
3511     block->bbJumpDest = bTest->bbNext;
3512
3513     /* Mark the jump dest block as being a jump target */
3514     block->bbJumpDest->bbFlags |= BBF_JMP_TARGET|BBF_HAS_LABEL;
3515
3516     /* Update bbRefs and bbPreds for 'block->bbNext' 'bTest' and 'bTest->bbNext' */
3517
3518     fgAddRefPred(block->bbNext, block);
3519
3520     fgRemoveRefPred(bTest, block);
3521     fgAddRefPred(bTest->bbNext, block);
3522
3523 #ifdef  DEBUG
3524     if  (verbose)
3525     {
3526         printf("\nDuplicating loop condition in BB%02u for loop (BB%02u - BB%02u)",
3527                block->bbNum, block->bbNext->bbNum, bTest->bbNum);
3528         printf("\nEstimated code size expansion is %d\n ", estDupCostSz);
3529
3530         gtDispTree(copyOfCondStmt);
3531     }
3532
3533 #endif
3534 }
3535
3536 /*****************************************************************************
3537  *
3538  *  Optimize the BasicBlock layout of the method
3539  */
3540
3541 void                Compiler::optOptimizeLayout()
3542 {
3543     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
3544
3545 #ifdef DEBUG
3546     if  (verbose) 
3547     {
3548         printf("*************** In optOptimizeLayout()\n");
3549         fgDispHandlerTab();
3550     }
3551
3552     /* Check that the flowgraph data (bbNum, bbRefs, bbPreds) is up-to-date */
3553     fgDebugCheckBBlist();
3554 #endif
3555
3556     noway_assert(fgModified == false);
3557
3558     for (BasicBlock *block = fgFirstBB; block; block = block->bbNext)
3559     {
3560         /* Make sure the appropriate fields are initialized */
3561
3562         if (block->bbWeight == BB_ZERO_WEIGHT)
3563         {
3564             /* Zero weighted block can't have a LOOP_HEAD flag */
3565             noway_assert(block->isLoopHead() == false);
3566             continue;
3567         }
3568         
3569         assert(block->bbLoopNum  == 0);
3570
3571         if (compCodeOpt() != SMALL_CODE)
3572         {
3573             /* Optimize "while(cond){}" loops to "cond; do{}while(cond);" */
3574
3575             fgOptWhileLoop(block);
3576         }
3577     }
3578
3579     if  (fgModified)
3580     {
3581         // Recompute the edge weight if we have modified the flow graph in fgOptWhileLoop
3582         fgComputeEdgeWeights();
3583     }
3584
3585     fgUpdateFlowGraph(true);
3586     fgReorderBlocks();
3587     fgUpdateFlowGraph();
3588 }
3589
3590 /*****************************************************************************
3591  *
3592  *  Perform loop inversion, find and classify natural loops
3593  */
3594
3595 void                Compiler::optOptimizeLoops()
3596 {
3597     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
3598
3599 #ifdef DEBUG
3600     if  (verbose) 
3601         printf("*************** In optOptimizeLoops()\n");
3602 #endif
3603
3604     optSetBlockWeights();
3605
3606     /* Were there any loops in the flow graph? */
3607
3608     if  (fgHasLoops)
3609     {
3610         /* now that we have dominator information we can find loops */
3611
3612         optFindNaturalLoops();
3613
3614         unsigned loopNum = 0;
3615
3616         /* Iterate over the flow graph, marking all loops */
3617
3618         /* We will use the following terminology:
3619          * top        - the first basic block in the loop (i.e. the head of the backward edge)
3620          * bottom     - the last block in the loop (i.e. the block from which we jump to the top)
3621          * lastBottom - used when we have multiple back-edges to the same top
3622          */
3623
3624         flowList *      pred;
3625
3626         BasicBlock *    top;
3627
3628         for (top = fgFirstBB; top; top = top->bbNext)
3629         {
3630             BasicBlock * foundBottom = NULL;
3631
3632             for (pred = top->bbPreds; pred; pred = pred->flNext)
3633             {
3634                 /* Is this a loop candidate? - We look for "back edges" */
3635
3636                 BasicBlock * bottom = pred->flBlock;
3637
3638                 /* is this a backward edge? (from BOTTOM to TOP) */
3639
3640                 if (top->bbNum > bottom->bbNum)
3641                     continue;
3642
3643                 /* 'top' also must have the BBF_LOOP_HEAD flag set */
3644
3645                 if (top->isLoopHead() == false)
3646                     continue;
3647
3648                 /* We only consider back-edges that are BBJ_COND or BBJ_ALWAYS for loops */
3649
3650                 if ((bottom->bbJumpKind != BBJ_COND)   &&
3651                     (bottom->bbJumpKind != BBJ_ALWAYS)    )
3652                     continue;
3653
3654                 /* the top block must be able to reach the bottom block */
3655                 if (!fgReachable(top, bottom))
3656                     continue;
3657
3658                 /* Found a new loop, record the longest backedge in foundBottom */
3659
3660                 if ((foundBottom == NULL) || (bottom->bbNum > foundBottom->bbNum))
3661                 {
3662                     foundBottom = bottom;
3663                 }
3664             }
3665
3666             if (foundBottom)
3667             {
3668                 loopNum++;
3669 #ifdef DEBUG
3670                 /* Mark the loop header as such */
3671                 assert(FitsIn<unsigned char>(loopNum));
3672                 top->bbLoopNum = (unsigned char) loopNum;
3673 #endif
3674
3675                 /* Mark all blocks between 'top' and 'bottom' */
3676                 
3677                 optMarkLoopBlocks(top, foundBottom, false);
3678             }
3679
3680             // We track at most 255 loops
3681             if (loopNum == 255)
3682             {
3683 #if COUNT_LOOPS
3684                 totalUnnatLoopOverflows++;
3685 #endif
3686                 break;
3687             }
3688         }
3689
3690 #if COUNT_LOOPS
3691         totalUnnatLoopCount += loopNum;
3692 #endif
3693
3694 #ifdef  DEBUG
3695         if  (verbose)
3696         {
3697             if  (loopNum > 0)
3698             {
3699                 printf("\nFound a total of %d loops.", loopNum);
3700                 printf("\nAfter loop weight marking:\n");
3701                 fgDispBasicBlocks();
3702                 printf("\n");
3703             }
3704         }
3705 #endif
3706         optLoopsMarked = true;
3707     }
3708 }
3709
3710 //------------------------------------------------------------------------
3711 // optDeriveLoopCloningConditions: Derive loop cloning conditions.
3712 //
3713 // Arguments:
3714 //     loopNum     -  the current loop index for which conditions are derived.
3715 //     context     -  data structure where all loop cloning info is kept.
3716 //
3717 // Return Value:
3718 //     "false" if conditions cannot be obtained. "true" otherwise.
3719 //     The cloning conditions are updated in the "conditions"[loopNum] field
3720 //     of the "context" parameter.
3721 //
3722 // Operation:
3723 //     Inspect the loop cloning optimization candidates and populate the conditions necessary
3724 //     for each optimization candidate. Checks if the loop stride is "> 0" if the loop
3725 //     condition is "less than". If the initializer is "var" init then adds condition
3726 //     "var >= 0", and if the loop is var limit then, "var >= 0" and "var <= a.len"
3727 //     are added to "context". These conditions are checked in the pre-header block
3728 //     and the cloning choice is made.
3729 //
3730 // Assumption:
3731 //      Callers should assume AND operation is used i.e., if all conditions are
3732 //      true, then take the fast path.
3733 //
3734 bool                Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext* context)
3735 {
3736     JITDUMP("------------------------------------------------------------\n");
3737     JITDUMP("Deriving cloning conditions for L%02u\n", loopNum);
3738
3739     LoopDsc* loop = &optLoopTable[loopNum];
3740     ExpandArrayStack<LcOptInfo*>* optInfos = context->GetLoopOptInfo(loopNum);
3741
3742     if (loop->lpTestOper() == GT_LT)
3743     {
3744         // Stride conditions
3745         if (loop->lpIterConst() <= 0)
3746         {
3747             JITDUMP("> Stride %d is invalid\n", loop->lpIterConst());
3748             return false;
3749         }
3750
3751         // Init conditions
3752         if (loop->lpFlags & LPFLG_CONST_INIT)
3753         {
3754             // Only allowing const init at this time.
3755             if (loop->lpConstInit < 0)
3756             {
3757                 JITDUMP("> Init %d is invalid\n", loop->lpConstInit);
3758                 return false;
3759             }
3760         }
3761         else if (loop->lpFlags & LPFLG_VAR_INIT)
3762         {
3763             // limitVar >= 0
3764             LC_Condition geZero(GT_GE,
3765                    LC_Expr(LC_Ident(loop->lpVarInit, LC_Ident::Var)),
3766                    LC_Expr(LC_Ident(0, LC_Ident::Const)));
3767             context->EnsureConditions(loopNum)->Push(geZero);
3768         }
3769         else
3770         {
3771             JITDUMP("> Not variable init\n");
3772             return false;
3773         }
3774
3775         // Limit Conditions
3776         LC_Ident ident;
3777         if (loop->lpFlags & LPFLG_CONST_LIMIT)
3778         {
3779             int limit = loop->lpConstLimit();
3780             if (limit < 0)
3781             {
3782                 JITDUMP("> limit %d is invalid\n", limit);
3783                 return false;
3784             }
3785             ident = LC_Ident(limit, LC_Ident::Const);
3786         }
3787         else if (loop->lpFlags & LPFLG_VAR_LIMIT)
3788         {
3789             unsigned limitLcl = loop->lpVarLimit();
3790             ident = LC_Ident(limitLcl, LC_Ident::Var);
3791
3792             LC_Condition geZero(GT_GE,
3793                    LC_Expr(ident),
3794                    LC_Expr(LC_Ident(0, LC_Ident::Const)));
3795
3796             context->EnsureConditions(loopNum)->Push(geZero);
3797         }
3798         else if (loop->lpFlags & LPFLG_ARRLEN_LIMIT)
3799         {
3800             ArrIndex* index = new (getAllocator()) ArrIndex(getAllocator());
3801             if (!loop->lpArrLenLimit(this, index))
3802             {
3803                 JITDUMP("> ArrLen not matching");
3804                 return false;
3805             }
3806             ident = LC_Ident(LC_Array(LC_Array::Jagged, index, LC_Array::ArrLen));
3807
3808             // Ensure that this array must be dereference-able, before executing the actual condition.
3809             LC_Array array(LC_Array::Jagged, index, LC_Array::None);
3810             context->EnsureDerefs(loopNum)->Push(array);
3811         }
3812         else
3813         {
3814             JITDUMP("> Undetected limit\n");
3815             return false;
3816         }
3817
3818         for (unsigned i = 0; i < optInfos->Size(); ++i)
3819         {
3820             LcOptInfo* optInfo = optInfos->GetRef(i);
3821             switch (optInfo->GetOptType())
3822             {
3823             case LcOptInfo::LcJaggedArray:
3824                 {
3825                     // limit <= arrLen
3826                     LcJaggedArrayOptInfo* arrIndexInfo = optInfo->AsLcJaggedArrayOptInfo();
3827                     LC_Array arrLen(LC_Array::Jagged, &arrIndexInfo->arrIndex, arrIndexInfo->dim, LC_Array::ArrLen);
3828                     LC_Ident arrLenIdent = LC_Ident(arrLen);
3829
3830                     LC_Condition cond(GT_LE, LC_Expr(ident), LC_Expr(arrLenIdent));
3831                     context->EnsureConditions(loopNum)->Push(cond);
3832
3833                     // Ensure that this array must be dereference-able, before executing the actual condition.
3834                     LC_Array array(LC_Array::Jagged, &arrIndexInfo->arrIndex, arrIndexInfo->dim, LC_Array::None);
3835                     context->EnsureDerefs(loopNum)->Push(array);
3836                 }
3837                 break;
3838             case LcOptInfo::LcMdArray:
3839                 {
3840                     // limit <= mdArrLen
3841                     LcMdArrayOptInfo* mdArrInfo = optInfo->AsLcMdArrayOptInfo();
3842                     LC_Condition cond(GT_LE,
3843                             LC_Expr(ident),
3844                             LC_Expr(LC_Ident(
3845                                     LC_Array(
3846                                         LC_Array::MdArray, mdArrInfo->GetArrIndexForDim(getAllocator()), mdArrInfo->dim, LC_Array::None)
3847                                     )));
3848                     context->EnsureConditions(loopNum)->Push(cond);
3849                 }
3850                 break;
3851
3852             default:
3853                 JITDUMP("Unknown opt\n");
3854                 return false;
3855             }
3856         }
3857         JITDUMP("Conditions: (");
3858         DBEXEC(verbose, context->PrintConditions(loopNum));
3859         JITDUMP(")\n");
3860         return true;
3861     }
3862     return false;
3863 }
3864
3865 //------------------------------------------------------------------------------------
3866 // optComputeDerefConditions: Derive loop cloning conditions for dereferencing arrays.
3867 //
3868 // Arguments:
3869 //     loopNum     -  the current loop index for which conditions are derived.
3870 //     context     -  data structure where all loop cloning info is kept.
3871 //
3872 // Return Value:
3873 //     "false" if conditions cannot be obtained. "true" otherwise.
3874 //     The deref conditions are updated in the "derefConditions"[loopNum] field
3875 //     of the "context" parameter.
3876 //
3877 // Definition of Deref Conditions:
3878 //     To be able to check for the loop cloning condition that (limitVar <= a.len)
3879 //     we should first be able to dereference "a". i.e., "a" is non-null.
3880 //
3881 //     Example:
3882 //
3883 //     for (i in 0..n)
3884 //       for (j in 0..n)
3885 //         for (k in 0..n)      // Inner most loop is being cloned. Cloning needs to check if
3886 //                              // (n <= a[i][j].len) and other safer conditions to take the fast path
3887 //           a[i][j][k] = 0;
3888 //
3889 //     Now, we want to deref a[i][j] to invoke length operator on it to perform the cloning fast path check.
3890 //     This involves deref of (a), (a[i]), (a[i][j]), therefore, the following should first
3891 //     be true to do the deref.
3892 //
3893 //     (a != null) && (i < a.len) && (a[i] != null) && (j < a[i].len) && (a[i][j] != null) --> (1)
3894 //
3895 //     Note the short circuiting AND. Implication: these conditions should be performed in separate
3896 //     blocks each of which will branch to slow path if the condition evaluates to false.
3897 //
3898 //     Now, imagine a situation where we have
3899 //      a[x][y][k] = 20 and a[i][j][k] = 0
3900 //     also in the inner most loop where x, y are parameters, then our conditions will have
3901 //     to include
3902 //     (x < a.len) &&
3903 //     (y < a[x].len)
3904 //     in addition to the above conditions (1) to get rid of bounds check on index 'k'
3905 //
3906 //     But these conditions can be checked together with conditions
3907 //     (i < a.len) without a need for a separate block. In summary, the conditions will be:
3908 //     
3909 //     (a != null) &&
3910 //     ((i < a.len) & (x < a.len)) &&      <-- Note the bitwise AND here.
3911 //     (a[i] != null & a[x] != null) &&    <-- Note the bitwise AND here.
3912 //     (j < a[i].len & y < a[x].len) &&    <-- Note the bitwise AND here.
3913 //     (a[i][j] != null & a[x][y] != null) <-- Note the bitwise AND here.
3914 //
3915 //     This naturally yields a tree style pattern, where the nodes of the tree are
3916 //     the array and indices respectively.
3917 //     
3918 //     Example:
3919 //         a => {
3920 //             i => {
3921 //                 j => {
3922 //                     k => {}
3923 //                 }
3924 //             },
3925 //             x => {
3926 //                 y => {
3927 //                     k => {}
3928 //                 }
3929 //             }
3930 //         }
3931 //
3932 //         Notice that the variables in the same levels can have their conditions combined in the
3933 //         same block with a bitwise AND. Whereas, the conditions in consecutive levels will be
3934 //         combined with a short-circuiting AND (i.e., different basic blocks).
3935 //
3936 //  Operation:
3937 //      Construct a tree of array indices and the array which will generate the optimal
3938 //      conditions for loop cloning.
3939 //
3940 //      a[i][j][k], b[i] and a[i][y][k] are the occurrences in the loop. Then, the tree should be:
3941 //
3942 //      a => {
3943 //          i => {
3944 //              j => {
3945 //                  k => {}
3946 //              },
3947 //              y => {
3948 //                  k => {}
3949 //              },
3950 //          }
3951 //      },
3952 //      b => {
3953 //          i => {}
3954 //      }
3955 //      In this method, we will construct such a tree by descending depth first into the array
3956 //      index operation and forming a tree structure as we encounter the array or the index variables.
3957 //
3958 //      This tree structure will then be used to generate conditions like below:
3959 //      (a != null) & (b != null) &&       // from the first level of the tree.
3960 //
3961 //      (i < a.len) & (i < b.len) &&       // from the second level of the tree. Levels can be combined.
3962 //      (a[i] != null) & (b[i] != null) && // from the second level of the tree.
3963 //      
3964 //      (j < a[i].len) & (y < a[i].len) &&       // from the third level.
3965 //      (a[i][j] != null) & (a[i][y] != null) && // from the third level.
3966 //
3967 //      and so on.
3968 //
3969 //
3970 bool Compiler::optComputeDerefConditions(unsigned loopNum, LoopCloneContext* context)
3971 {
3972     ExpandArrayStack<LC_Deref*> nodes(getAllocator());
3973     int maxRank = -1;
3974
3975     // Get the dereference-able arrays.
3976     ExpandArrayStack<LC_Array>* deref = context->EnsureDerefs(loopNum);
3977
3978     // For each array in the dereference list, construct a tree,
3979     // where the nodes are array and index variables and an edge 'u-v'
3980     // exists if a node 'v' indexes node 'u' directly as in u[v] or an edge
3981     // 'u-v-w' transitively if u[v][w] occurs.
3982     for (unsigned i = 0; i < deref->Size(); ++i)
3983     {
3984         LC_Array& array = (*deref)[i];
3985
3986         // First populate the array base variable.
3987         LC_Deref* node = LC_Deref::Find(&nodes, array.arrIndex->arrLcl);
3988         if (node == nullptr)
3989         {
3990             node = new (getAllocator()) LC_Deref(array, 0 /*level*/);
3991             nodes.Push(node);
3992         }
3993
3994         // For each dimension (level) for the array, populate the tree with the variable
3995         // from that dimension.
3996         unsigned rank = (unsigned) array.GetDimRank();
3997         for (unsigned i = 0; i < rank; ++i)
3998         {
3999             node->EnsureChildren(getAllocator());
4000             LC_Deref* tmp = node->Find(array.arrIndex->indLcls[i]);
4001             if (tmp == nullptr)
4002             {
4003                 tmp = new (getAllocator()) LC_Deref(array, node->level + 1);
4004                 node->children->Push(tmp);
4005             }
4006
4007             // Descend one level down.
4008             node = tmp;
4009         }
4010
4011         // Keep the maxRank of all array dereferences.
4012         maxRank = max((int) rank, maxRank);
4013     }
4014
4015 #ifdef DEBUG
4016     if (verbose)
4017     {
4018         for (unsigned i = 0; i < nodes.Size(); ++i)
4019         {
4020             if (i != 0) printf(",");
4021             nodes[i]->Print();
4022             printf("\n");
4023         }
4024     }
4025 #endif
4026
4027     if (maxRank == -1)
4028     {
4029         return false;
4030     }
4031
4032     // First level will always yield the null-check, since it is made of the array base variables.
4033     // All other levels (dimensions) will yield two conditions ex: (i < a.length && a[i] != null)
4034     // So add 1 after rank * 2.
4035     unsigned condBlocks = (unsigned) maxRank * 2 + 1;
4036
4037     // Heuristic to not create too many blocks;
4038     if (condBlocks > 4)
4039     {
4040         return false;
4041     }
4042
4043     // Derive conditions into an 'array of level x array of conditions' i.e., levelCond[levels][conds]
4044     ExpandArrayStack<ExpandArrayStack<LC_Condition>*>* levelCond = context->EnsureBlockConditions(loopNum, condBlocks);
4045     for (unsigned i = 0; i < nodes.Size(); ++i)
4046     {
4047         nodes[i]->DeriveLevelConditions(levelCond);
4048     }
4049
4050     DBEXEC(verbose, context->PrintBlockConditions(loopNum));
4051     return true;
4052 }
4053
4054 #ifdef DEBUG
4055 //----------------------------------------------------------------------------
4056 // optDebugLogLoopCloning:  Insert a call to jithelper that prints a message.
4057 //
4058 // Arguments:
4059 //      block        - the block in which the helper call needs to be inserted.
4060 //      insertBefore - the tree before which the helper call will be inserted.
4061 //
4062 void                Compiler::optDebugLogLoopCloning(BasicBlock* block, GenTreePtr insertBefore)
4063 {
4064     if (JitConfig.JitDebugLogLoopCloning() == 0)
4065     {
4066         return;
4067     }
4068     GenTreePtr logCall = gtNewHelperCallNode(CORINFO_HELP_DEBUG_LOG_LOOP_CLONING, TYP_VOID);
4069     GenTreePtr stmt = fgNewStmtFromTree(logCall);
4070     fgInsertStmtBefore(block, insertBefore, stmt);
4071     fgMorphBlockStmt(block, stmt DEBUGARG("Debug log loop cloning"));
4072 }
4073 #endif
4074
4075 //------------------------------------------------------------------------
4076 // optPerformStaticOptimizations: Perform the optimizations for the optimization
4077 //      candidates gathered during the cloning phase.
4078 //
4079 // Arguments:
4080 //     loopNum     -  the current loop index for which the optimizations are performed.
4081 //     context     -  data structure where all loop cloning info is kept.
4082 //     dynamicPath -  If true, the optimization is performed in the fast path among the
4083 //                    cloned loops. If false, it means this is the only path (i.e.,
4084 //                    there is no slow path.)
4085 //
4086 // Operation:
4087 //      Perform the optimizations on the fast path i.e., the path in which the 
4088 //      optimization candidates were collected at the time of identifying them.
4089 //      The candidates store all the information necessary (the tree/stmt/block
4090 //      they are from) to perform the optimization.
4091 //
4092 // Assumption:
4093 //      The unoptimized path is either already cloned when this method is called or
4094 //      there is no unoptimized path (got eliminated statically.) So this method
4095 //      performs the optimizations assuming that the path in which the candidates
4096 //      were collected is the fast path in which the optimizations will be performed.
4097 //
4098 void                Compiler::optPerformStaticOptimizations(unsigned loopNum, LoopCloneContext* context DEBUGARG(bool dynamicPath))
4099 {
4100     ExpandArrayStack<LcOptInfo*>* optInfos = context->GetLoopOptInfo(loopNum);
4101     for (unsigned i = 0; i < optInfos->Size(); ++i)
4102     {
4103         LcOptInfo* optInfo = optInfos->GetRef(i);
4104         switch (optInfo->GetOptType())
4105         {
4106         case LcOptInfo::LcJaggedArray:
4107             {
4108                 LcJaggedArrayOptInfo* arrIndexInfo = optInfo->AsLcJaggedArrayOptInfo();
4109                 compCurBB = arrIndexInfo->arrIndex.useBlock;
4110                 optRemoveRangeCheck(
4111                     arrIndexInfo->arrIndex.bndsChks[arrIndexInfo->dim],
4112                     arrIndexInfo->stmt, true, GTF_ASG, true);
4113                 DBEXEC(dynamicPath, optDebugLogLoopCloning(arrIndexInfo->arrIndex.useBlock, arrIndexInfo->stmt));
4114             }
4115             break;
4116         case LcOptInfo::LcMdArray:
4117             // TODO-CQ: CLONE: Implement.
4118             break;
4119         default:
4120             break;
4121         }
4122     }
4123 }
4124
4125
4126 //----------------------------------------------------------------------------
4127 //  optCanCloneLoops: Use the environment flag to determine whether loop
4128 //      cloning is allowed to be performed.
4129 //
4130 //  Return Value:
4131 //      Returns true in debug builds if COMPlus_JitCloneLoops flag is set.
4132 //      Disabled for retail for now.
4133 //
4134 bool                Compiler::optCanCloneLoops()
4135 {
4136     // Enabled for retail builds now.
4137     unsigned cloneLoopsFlag = 1;
4138 #ifdef DEBUG
4139     cloneLoopsFlag = JitConfig.JitCloneLoops();
4140 #endif
4141     return (cloneLoopsFlag != 0);
4142 }
4143
4144
4145 //----------------------------------------------------------------------------
4146 //  optIsLoopClonable: Determine whether this loop can be cloned.
4147 //
4148 //  Arguments:
4149 //      loopInd     loop index which needs to be checked if it can be cloned.
4150 //
4151 //  Return Value:
4152 //      Returns true if the loop can be cloned. If it returns false
4153 //      prints a message in debug as why the loop can't be cloned.
4154 //
4155 bool                Compiler::optIsLoopClonable(unsigned loopInd)
4156 {
4157     // First, for now, make sure the loop doesn't have any embedded exception handling -- I don't want to tackle
4158     // inserting new EH regions in the exception table yet.
4159     BasicBlock* stopAt = optLoopTable[loopInd].lpBottom->bbNext;
4160     unsigned loopRetCount = 0;
4161     for (BasicBlock* blk = optLoopTable[loopInd].lpFirst; blk != stopAt; blk = blk->bbNext)
4162     {
4163         if (blk->bbJumpKind == BBJ_RETURN) loopRetCount++;
4164         if (bbIsTryBeg(blk)) 
4165         {
4166             JITDUMP("Loop cloning: rejecting loop %d in %s, because it has a try begin.\n", 
4167                     loopInd, info.compFullName);
4168             return false;
4169         }
4170     }
4171
4172     // Is the entry block a handler or filter start?  If so, then if we cloned, we could create a jump
4173     // into the middle of a handler (to go to the cloned copy.)  Reject.
4174     if (bbIsHandlerBeg(optLoopTable[loopInd].lpEntry))
4175     {
4176         JITDUMP("Loop cloning: rejecting loop because entry block is a handler start.\n");
4177         return false;
4178     }
4179
4180     // If the head and entry are in different EH regions, reject.
4181     if (!BasicBlock::sameEHRegion(optLoopTable[loopInd].lpHead, optLoopTable[loopInd].lpEntry))
4182     {
4183         JITDUMP("Loop cloning: rejecting loop because head and entry blocks are in different EH regions.\n");
4184         return false;
4185     }
4186
4187     // Is the first block after the last block of the loop a handler or filter start?
4188     // Usually, we create a dummy block after the orginal loop, to skip over the loop clone
4189     // and go to where the original loop did.  That raises problems when we don't actually go to
4190     // that block; this is one of those cases.  This could be fixed fairly easily; for example,
4191     // we could add a dummy nop block after the (cloned) loop bottom, in the same handler scope as the
4192     // loop.  This is just a corner to cut to get this working faster.
4193     BasicBlock* bbAfterLoop = optLoopTable[loopInd].lpBottom->bbNext;
4194     if (bbAfterLoop != nullptr && bbIsHandlerBeg(bbAfterLoop))
4195     {
4196         JITDUMP("Loop cloning: rejecting loop because next block after bottom is a handler start.\n");
4197         return false;
4198     }
4199
4200     // We've previously made a decision whether to have separate return epilogs, or branch to one.
4201     // There's a GCInfo limitation in the x86 case, so that there can be no more than 4 separate epilogs.
4202     // (I thought this was x86-specific, but it's not if-d.  On other architectures, the decision should be made as a
4203     // heuristic tradeoff; perhaps we're just choosing to live with 4 as the limit.)
4204     if (fgReturnCount + loopRetCount > 4)
4205     {
4206         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);
4207         return false;
4208     }
4209
4210     // Otherwise, we're going to add those return blocks.
4211     fgReturnCount += loopRetCount;
4212
4213     return true;
4214 }
4215
4216 /*****************************************************************************
4217  *
4218  *  Identify loop cloning opportunities, derive loop cloning conditions,
4219  *  perform loop cloning, use the derived conditions to choose which
4220  *  path to take.
4221  */
4222 void                Compiler::optCloneLoops()
4223 {
4224     JITDUMP("\n*************** In optCloneLoops()\n");
4225     if (optLoopCount == 0 || !optCanCloneLoops())
4226     {
4227         return;
4228     }
4229
4230 #ifdef DEBUG
4231     if (verbose)
4232     {
4233         printf("Blocks/Trees at start of phase\n");
4234         fgDispBasicBlocks(true);
4235     }
4236 #endif
4237
4238     LoopCloneContext context(optLoopCount, getAllocator());
4239
4240     // Obtain array optimization candidates in the context.
4241     optObtainLoopCloningOpts(&context);
4242
4243     // For each loop, derive cloning conditions for the optimization candidates.
4244     for (unsigned i = 0; i < optLoopCount; ++i)
4245     {
4246         ExpandArrayStack<LcOptInfo*>* optInfos = context.GetLoopOptInfo(i);
4247         if (optInfos == nullptr)
4248         {
4249             continue;
4250         }
4251
4252         if (!optDeriveLoopCloningConditions(i, &context) || !optComputeDerefConditions(i, &context))
4253         {
4254             JITDUMP("> Conditions could not be obtained\n");
4255             context.CancelLoopOptInfo(i);
4256         }
4257         else
4258         {
4259             bool allTrue = false;
4260             bool anyFalse = false;
4261             context.EvaluateConditions(i, &allTrue, &anyFalse DEBUGARG(verbose));
4262             if (anyFalse)
4263             {
4264                 context.CancelLoopOptInfo(i);
4265             }
4266             if (allTrue)
4267             {
4268                 // Perform static optimizations on the fast path since we always
4269                 // have to take the cloned path.
4270                 optPerformStaticOptimizations(i, &context DEBUGARG(false));
4271
4272                 // No need to clone.
4273                 context.CancelLoopOptInfo(i);
4274             }
4275         }
4276     }
4277
4278
4279 #if 0
4280     // The code in this #if has been useful in debugging loop cloning issues, by
4281     // enabling selective enablement of the loop cloning optimization according to
4282     // method hash.
4283 #ifdef DEBUG
4284     unsigned methHash = info.compMethodHash();
4285     char* lostr = getenv("loopclonehashlo");
4286     unsigned methHashLo = 0;
4287     if (lostr != NULL) 
4288     {
4289         sscanf_s(lostr, "%x", &methHashLo);
4290         // methHashLo = (unsigned(atoi(lostr)) << 2);  // So we don't have to use negative numbers.
4291     }
4292     char* histr = getenv("loopclonehashhi");
4293     unsigned methHashHi = UINT32_MAX;
4294     if (histr != NULL) 
4295     {
4296         sscanf_s(histr, "%x", &methHashHi);
4297         // methHashHi = (unsigned(atoi(histr)) << 2);  // So we don't have to use negative numbers.
4298     }
4299     if (methHash < methHashLo || methHash > methHashHi)
4300         return;
4301 #endif
4302 #endif
4303
4304     for (unsigned i = 0; i < optLoopCount; ++i)
4305     {
4306         if (context.GetLoopOptInfo(i) != nullptr)
4307         {
4308             optLoopsCloned++;
4309             context.OptimizeConditions(i DEBUGARG(verbose));
4310             context.OptimizeBlockConditions(i DEBUGARG(verbose));
4311             optCloneLoop(i, &context);
4312         }
4313     }
4314
4315 #ifdef DEBUG
4316     if (verbose)
4317     {
4318         printf("\nAfter loop cloning:\n");
4319         fgDispBasicBlocks(/*dumpTrees*/true);
4320     }
4321 #endif
4322 }
4323
4324 void                Compiler::optCloneLoop(unsigned loopInd, LoopCloneContext* context)
4325 {
4326     assert(loopInd < optLoopCount);
4327
4328     JITDUMP("\nCloning loop %d: [h: %d, f: %d, t: %d, e: %d, b: %d].\n",
4329             loopInd,
4330             optLoopTable[loopInd].lpHead->bbNum,
4331             optLoopTable[loopInd].lpFirst->bbNum,
4332             optLoopTable[loopInd].lpTop->bbNum,
4333             optLoopTable[loopInd].lpEntry->bbNum,
4334             optLoopTable[loopInd].lpBottom->bbNum);
4335
4336     // Determine the depth of the loop, so we can properly weight blocks added (outside the cloned loop blocks).
4337     unsigned depth = optLoopDepth(loopInd);
4338     unsigned ambientWeight = 1;
4339     for (unsigned j = 0; j < depth; j++)
4340     {
4341         unsigned lastWeight = ambientWeight;
4342         ambientWeight *= BB_LOOP_WEIGHT;
4343         // If the multiplication overflowed, stick at max.
4344         // (Strictly speaking, a multiplication could overflow and still have a result
4345         // that is >= lastWeight...but if so, the original weight must be pretty large,
4346         // and it got bigger, so that's OK.)
4347         if (ambientWeight < lastWeight)
4348         {
4349             ambientWeight = BB_MAX_WEIGHT;
4350             break;
4351         }
4352     }
4353
4354     // If we're in a non-natural loop, the ambient weight might be higher than we computed above.
4355     // Be safe by taking the max with the head block's weight.
4356     ambientWeight = max(ambientWeight, optLoopTable[loopInd].lpHead->bbWeight);
4357
4358     // This is the containing loop, if any -- to label any blocks we create that are outside
4359     // the loop being cloned.
4360     unsigned char ambientLoop = optLoopTable[loopInd].lpParent;
4361
4362     // First, make sure that the loop has a unique header block, creating an empty one if necessary.
4363     optEnsureUniqueHead(loopInd, ambientWeight);
4364
4365     // We're going to make
4366
4367     // H --> E
4368     // F  
4369     // T  
4370     // E
4371     // B  ?-> T  
4372     // X
4373     //
4374     //   become
4375     //
4376     // H ?-> E2
4377     // H2--> E    (Optional; if E == T == F, let H fall through to F/T/E)
4378     // F  
4379     // T  
4380     // E
4381     // B  ?-> T  
4382     // X2--> X
4383     // F2
4384     // T2
4385     // E2
4386     // B2 ?-> T2
4387     // X
4388
4389     BasicBlock* h = optLoopTable[loopInd].lpHead;
4390     if (h->bbJumpKind != BBJ_NONE && h->bbJumpKind != BBJ_ALWAYS)
4391     {
4392         // Make a new block to be the unique entry to the loop.
4393         assert(h->bbJumpKind == BBJ_COND && h->bbNext == optLoopTable[loopInd].lpEntry);
4394         BasicBlock* newH = fgNewBBafter(BBJ_NONE,
4395                                         h,
4396                                         /*extendRegion*/true);
4397         newH->bbWeight = (newH->isRunRarely() ? 0 : ambientWeight);
4398         BlockSetOps::Assign(this, newH->bbReach, h->bbReach);
4399         // This is in the scope of a surrounding loop, if one exists -- the parent of the loop we're cloning.
4400         newH->bbNatLoopNum = ambientLoop;
4401         h = newH;
4402         optUpdateLoopHead(loopInd, optLoopTable[loopInd].lpHead, h);
4403     }
4404
4405     // First, make X2 after B, if necessary.  (Not necessary if b is a BBJ_ALWAYS.)
4406     // "newPred" will be the predecessor of the blocks of the cloned loop.
4407     BasicBlock* b = optLoopTable[loopInd].lpBottom;
4408     BasicBlock* newPred = b;
4409     if (b->bbJumpKind != BBJ_ALWAYS)
4410     {
4411         BasicBlock* x = b->bbNext;
4412         if (x != nullptr)
4413         {
4414             BasicBlock* x2 = fgNewBBafter(BBJ_ALWAYS, b, /*extendRegion*/true);
4415             x2->bbWeight = (x2->isRunRarely() ? 0 : ambientWeight);
4416
4417             // This is in the scope of a surrounding loop, if one exists -- the parent of the loop we're cloning.
4418             x2->bbNatLoopNum = ambientLoop;
4419
4420             x2->bbJumpDest = x;
4421             BlockSetOps::Assign(this, x2->bbReach, h->bbReach);
4422             newPred = x2;
4423         }
4424     }
4425
4426     // Now we'll make "h2", after "h" to go to "e" -- unless the loop is a do-while,
4427     // so that "h" already falls through to "e" (e == t == f).
4428     BasicBlock* h2 = nullptr;
4429     if (optLoopTable[loopInd].lpHead->bbNext != optLoopTable[loopInd].lpEntry)
4430     {
4431         BasicBlock* h2 = fgNewBBafter(BBJ_ALWAYS,
4432                                       optLoopTable[loopInd].lpHead,
4433                                       /*extendRegion*/true);
4434         h2->bbWeight = (h2->isRunRarely() ? 0 : ambientWeight);
4435
4436         // This is in the scope of a surrounding loop, if one exists -- the parent of the loop we're cloning.
4437         h2->bbNatLoopNum = ambientLoop;
4438
4439         h2->bbJumpDest = optLoopTable[loopInd].lpEntry;
4440         optUpdateLoopHead(loopInd,optLoopTable[loopInd].lpHead, h2);
4441     }
4442
4443     // Now we'll clone the blocks of the loop body.
4444     BasicBlock* newFirst = nullptr;
4445     BasicBlock* newBot = nullptr;
4446
4447     BlockToBlockMap* blockMap = new (getAllocator()) BlockToBlockMap(getAllocator());
4448     for (BasicBlock* blk = optLoopTable[loopInd].lpFirst; 
4449          blk != optLoopTable[loopInd].lpBottom->bbNext; 
4450          blk = blk->bbNext)
4451     {
4452         BasicBlock* newBlk = fgNewBBafter(blk->bbJumpKind,
4453                                           newPred,
4454                                           /*extendRegion*/true);
4455
4456         BasicBlock::CloneBlockState(this, newBlk, blk);
4457         // TODO-Cleanup: The above clones the bbNatLoopNum, which is incorrect.  Eventually, we should probably insert
4458         // the cloned loop in the loop table.  For now, however, we'll just make these blocks be part of the surrounding
4459         // loop, if one exists -- the parent of the loop we're cloning.
4460         newBlk->bbNatLoopNum = optLoopTable[loopInd].lpParent;
4461
4462         if (newFirst == nullptr) newFirst = newBlk;
4463         newBot = newBlk; // Continually overwrite to make sure we get the last one.
4464         newPred = newBlk;
4465         blockMap->Set(blk, newBlk);
4466     }
4467
4468     // Perform the static optimizations on the fast path.
4469     optPerformStaticOptimizations(loopInd, context DEBUGARG(true));
4470
4471     // Now go through the new blocks, remapping their jump targets within the loop.
4472     for (BasicBlock* blk = optLoopTable[loopInd].lpFirst; 
4473          blk != optLoopTable[loopInd].lpBottom->bbNext; 
4474          blk = blk->bbNext)
4475     {
4476
4477         BasicBlock* newblk = nullptr;
4478         bool b = blockMap->Lookup(blk, &newblk);
4479         assert(b && newblk != nullptr);
4480
4481         assert(blk->bbJumpKind == newblk->bbJumpKind);
4482
4483         // First copy the jump destination(s) from "blk".
4484         optCopyBlkDest(blk, newblk);
4485         
4486         // Now redirect the new block according to "blockMap".
4487         optRedirectBlock(newblk, blockMap);
4488     }
4489
4490     assert((h->bbJumpKind == BBJ_NONE && (h->bbNext == h2 || h->bbNext == optLoopTable[loopInd].lpEntry))
4491            || (h->bbJumpKind == BBJ_ALWAYS));
4492
4493     // If all the conditions are true, go to E2.
4494     BasicBlock* e2 = nullptr;
4495     bool foundIt = blockMap->Lookup(optLoopTable[loopInd].lpEntry, &e2);
4496
4497     h->bbJumpKind = BBJ_COND;
4498
4499     // We will create the following structure
4500     //
4501     // cond0 (in h)  -?> cond1
4502     // slow          --> e2 (slow) always
4503     // !cond1        -?> slow
4504     // !cond2        -?> slow
4505     // ...
4506     // !condn        -?> slow
4507     // h2/entry (fast)
4508     //
4509     // We should always have block conditions, at the minimum, the array should be deref-able
4510     assert(context->HasBlockConditions(loopInd));
4511
4512     // Create a unique header for the slow path.
4513     BasicBlock* slowHead = fgNewBBafter(BBJ_ALWAYS, h, true);
4514     slowHead->bbWeight = (h->isRunRarely() ? 0 : ambientWeight);
4515     slowHead->bbNatLoopNum = ambientLoop;
4516     slowHead->bbJumpDest = e2;
4517
4518     BasicBlock* condLast = optInsertLoopChoiceConditions(context, loopInd, h, slowHead);
4519     condLast->bbJumpDest = slowHead;
4520
4521     // If h2 is present it is already the head or replace 'h' by 'condLast'.
4522     if (h2 == nullptr)
4523     {
4524         optUpdateLoopHead(loopInd, optLoopTable[loopInd].lpHead, condLast);
4525     }
4526     assert(foundIt && e2 != NULL);
4527
4528     fgUpdateChangedFlowGraph();
4529 }
4530
4531 //--------------------------------------------------------------------------------------------------
4532 // optInsertLoopChoiceConditions - Insert the loop conditions for a loop between loop head and entry
4533 //
4534 // Arguments:
4535 //      context     loop cloning context variable
4536 //      loopNum     the loop index
4537 //      head        loop head for "loopNum"
4538 //      slowHead    the slow path loop head
4539 //
4540 // Return Values:
4541 //      None.
4542 //
4543 // Operation:
4544 //      Create the following structure.
4545 //
4546 //      Note below that the cond0 is inverted in head i.e., if true jump to cond1. This is because
4547 //      condn cannot jtrue to loop head h2. It has to be from a direct pred block.
4548 //
4549 //      cond0 (in h)  -?> cond1
4550 //      slowHead      --> e2 (slowHead) always
4551 //      !cond1        -?> slowHead
4552 //      !cond2        -?> slowHead
4553 //      ...
4554 //      !condn        -?> slowHead
4555 //      h2/entry (fast)
4556 //
4557 //      Insert condition 0 in 'h' and create other condition blocks and insert conditions in them.
4558 //
4559 BasicBlock* Compiler::optInsertLoopChoiceConditions(LoopCloneContext* context, unsigned loopNum, BasicBlock* head, BasicBlock* slowHead)
4560 {
4561     JITDUMP("Inserting loop cloning conditions\n");
4562     assert(context->HasBlockConditions(loopNum));
4563
4564     BasicBlock* curCond = head;
4565     ExpandArrayStack<ExpandArrayStack<LC_Condition>*>* levelCond = context->GetBlockConditions(loopNum);
4566     for (unsigned i = 0; i < levelCond->Size(); ++i)
4567     {
4568         bool isHeaderBlock = (curCond == head);
4569
4570         // Flip the condition if header block.
4571         context->CondToStmtInBlock(this, *((*levelCond)[i]), curCond, isHeaderBlock);
4572
4573         // Create each condition block ensuring wiring between them.
4574         BasicBlock* tmp = fgNewBBafter(BBJ_COND, isHeaderBlock ? slowHead : curCond, true);
4575         curCond->bbJumpDest = isHeaderBlock ? tmp : slowHead;
4576         curCond = tmp;
4577
4578         curCond->inheritWeight(head);
4579         curCond->bbNatLoopNum = head->bbNatLoopNum;
4580         JITDUMP("Created new block %02d for new level\n", curCond->bbNum);
4581     }
4582
4583     // Finally insert cloning conditions after all deref conditions have been inserted.
4584     context->CondToStmtInBlock(this, *(context->GetConditions(loopNum)), curCond, false);
4585     return curCond;
4586 }
4587
4588 void Compiler::optEnsureUniqueHead(unsigned loopInd, unsigned ambientWeight)
4589 {
4590     BasicBlock* h = optLoopTable[loopInd].lpHead;
4591     BasicBlock* t = optLoopTable[loopInd].lpTop;
4592     BasicBlock* e = optLoopTable[loopInd].lpEntry;
4593     BasicBlock* b = optLoopTable[loopInd].lpBottom;
4594
4595     // If "h" dominates the entry block, then it is the unique header.
4596     if (fgDominate(h, e)) return;
4597
4598     // Otherwise, create a new empty header block, make it the pred of the entry block,
4599     // and redirect the preds of the entry block to go to this.
4600
4601     BasicBlock* beforeTop = t->bbPrev;
4602     // Make sure that the new block is in the same region as the loop.
4603     // (We will only create loops that are entirely within a region.)
4604     BasicBlock * h2 = fgNewBBafter(BBJ_ALWAYS, beforeTop, true);
4605     // This is in the containing loop.
4606     h2->bbNatLoopNum = optLoopTable[loopInd].lpParent;
4607     h2->bbWeight = (h2->isRunRarely() ? 0 : ambientWeight);
4608
4609     // We don't care where it was put; splice it between beforeTop and top.
4610     if (beforeTop->bbNext != h2)
4611     {
4612         h2->bbPrev->setNext(h2->bbNext);  // Splice h2 out.
4613         beforeTop->setNext(h2);           // Splice h2 in, between beforeTop and t.
4614         h2->setNext(t);
4615     }
4616
4617     if (h2->bbNext != e)
4618     {
4619         h2->bbJumpKind = BBJ_ALWAYS;
4620         h2->bbJumpDest = e;
4621     }
4622     BlockSetOps::Assign(this, h2->bbReach, e->bbReach);
4623
4624     // Redirect paths from preds of "e" to go to "h2" instead of "e".
4625     BlockToBlockMap* blockMap = new (getAllocator()) BlockToBlockMap(getAllocator());
4626     blockMap->Set(e, h2);
4627
4628     for (flowList* predEntry = e->bbPreds; predEntry; predEntry = predEntry->flNext)
4629     {
4630         BasicBlock* predBlock = predEntry->flBlock;
4631
4632         // Skip if predBlock is in the loop.
4633         if (t->bbNum <= predBlock->bbNum && predBlock->bbNum <= b->bbNum) continue;
4634         optRedirectBlock(predBlock, blockMap);
4635     }
4636
4637     optUpdateLoopHead(loopInd, optLoopTable[loopInd].lpHead, h2); 
4638 }
4639
4640 /*****************************************************************************
4641  *
4642  *  Determine the kind of interference for the call.
4643  */
4644
4645 /* static */ inline
4646 Compiler::callInterf    Compiler::optCallInterf(GenTreePtr call)
4647 {
4648     assert(call->gtOper == GT_CALL);
4649
4650     // if not a helper, kills everything
4651     if  (call->gtCall.gtCallType != CT_HELPER)
4652         return CALLINT_ALL;
4653
4654     // setfield and array address store kill all indirections
4655     switch (eeGetHelperNum(call->gtCall.gtCallMethHnd))
4656     {
4657     case CORINFO_HELP_ASSIGN_REF:            // Not strictly needed as we don't make a GT_CALL with this
4658     case CORINFO_HELP_CHECKED_ASSIGN_REF:    // Not strictly needed as we don't make a GT_CALL with this
4659     case CORINFO_HELP_ASSIGN_BYREF:          // Not strictly needed as we don't make a GT_CALL with this
4660     case CORINFO_HELP_SETFIELDOBJ:
4661     case CORINFO_HELP_ARRADDR_ST:
4662
4663         return CALLINT_REF_INDIRS;
4664
4665     case CORINFO_HELP_SETFIELDFLOAT:
4666     case CORINFO_HELP_SETFIELDDOUBLE:
4667     case CORINFO_HELP_SETFIELD8:
4668     case CORINFO_HELP_SETFIELD16:
4669     case CORINFO_HELP_SETFIELD32:
4670     case CORINFO_HELP_SETFIELD64:
4671
4672         return CALLINT_SCL_INDIRS;
4673
4674     case CORINFO_HELP_ASSIGN_STRUCT:         // Not strictly needed as we don't use this in Jit32
4675     case CORINFO_HELP_MEMSET:                // Not strictly needed as we don't make a GT_CALL with this
4676     case CORINFO_HELP_MEMCPY:                // Not strictly needed as we don't make a GT_CALL with this
4677     case CORINFO_HELP_SETFIELDSTRUCT:
4678
4679         return CALLINT_ALL_INDIRS;
4680
4681     default:
4682       break;
4683     }
4684
4685     // other helpers kill nothing
4686     return CALLINT_NONE;
4687 }
4688
4689 /*****************************************************************************
4690  *
4691  *  See if the given tree can be computed in the given precision (which must
4692  *  be smaller than the type of the tree for this to make sense). If 'doit'
4693  *  is false, we merely check to see whether narrowing is possible; if we
4694  *  get called with 'doit' being true, we actually perform the narrowing.
4695  */
4696
4697 bool                Compiler::optNarrowTree(GenTreePtr     tree,
4698                                             var_types      srct,
4699                                             var_types      dstt,
4700                                             ValueNumPair   vnpNarrow,
4701                                             bool           doit)
4702 {
4703     genTreeOps      oper;
4704     unsigned        kind;
4705
4706     noway_assert(tree);
4707     noway_assert(genActualType(tree->gtType) == genActualType(srct));
4708
4709     /* Assume we're only handling integer types */
4710     noway_assert(varTypeIsIntegral(srct));
4711     noway_assert(varTypeIsIntegral(dstt));
4712
4713     unsigned srcSize      = genTypeSize(srct);
4714     unsigned dstSize      = genTypeSize(dstt);
4715
4716     /* dstt must be smaller than srct to narrow */
4717     if (dstSize >= srcSize)
4718         return false;
4719
4720     /* Figure out what kind of a node we have */
4721     oper = tree->OperGet();
4722     kind = tree->OperKind();
4723
4724     if  (kind & GTK_ASGOP)
4725     {
4726         noway_assert(doit == false);
4727         return  false;
4728     }
4729
4730     ValueNumPair NoVNPair = ValueNumPair();
4731
4732     if  (kind & GTK_LEAF)
4733     {
4734         switch (oper)
4735         {
4736         /* Constants can usually be narrowed by changing their value */
4737         CLANG_FORMAT_COMMENT_ANCHOR;
4738
4739 #ifndef _TARGET_64BIT_
4740             __int64  lval;  
4741             __int64  lmask;
4742
4743         case GT_CNS_LNG:
4744             lval  = tree->gtIntConCommon.LngValue();
4745             lmask = 0;
4746
4747             switch (dstt)
4748             {
4749                 case TYP_BYTE : lmask = 0x0000007F; break;
4750                 case TYP_BOOL :
4751                 case TYP_UBYTE: lmask = 0x000000FF; break;
4752                 case TYP_SHORT: lmask = 0x00007FFF; break;
4753                 case TYP_CHAR : lmask = 0x0000FFFF; break;
4754                 case TYP_INT  : lmask = 0x7FFFFFFF; break;
4755                 case TYP_UINT : lmask = 0xFFFFFFFF; break;
4756
4757                 default:        return false; 
4758             }
4759
4760             if  ((lval & lmask) != lval)
4761                 return false;
4762
4763             if  (doit)
4764             {
4765                 tree->ChangeOperConst     (GT_CNS_INT);
4766                 tree->gtType             = TYP_INT;
4767                 tree->gtIntCon.gtIconVal = (int) lval;
4768                 if (vnStore != nullptr)
4769                 {
4770                     fgValueNumberTreeConst(tree);
4771                 }
4772             }
4773
4774             return  true;
4775 #endif
4776
4777         case GT_CNS_INT:
4778
4779             ssize_t  ival;  ival  = tree->gtIntCon.gtIconVal;
4780             ssize_t  imask; imask = 0;
4781
4782             switch (dstt)
4783             {
4784                 case TYP_BYTE : imask = 0x0000007F; break;
4785                 case TYP_BOOL :
4786                 case TYP_UBYTE: imask = 0x000000FF; break;
4787                 case TYP_SHORT: imask = 0x00007FFF; break;
4788                 case TYP_CHAR : imask = 0x0000FFFF; break;
4789 #ifdef _TARGET_64BIT_
4790                 case TYP_INT  : imask = 0x7FFFFFFF; break;
4791                 case TYP_UINT : imask = 0xFFFFFFFF; break;
4792 #endif // _TARGET_64BIT_
4793                 default:        return false; 
4794             }
4795
4796             if  ((ival & imask) != ival)
4797                 return false;
4798
4799 #ifdef _TARGET_64BIT_
4800             if  (doit)
4801             {
4802                 tree->gtType = TYP_INT;
4803                 tree->gtIntCon.gtIconVal = (int) ival;
4804                 if (vnStore != nullptr)
4805                 {
4806                     fgValueNumberTreeConst(tree);
4807                 }
4808             }
4809 #endif // _TARGET_64BIT_
4810
4811             return  true;
4812
4813         /* Operands that are in memory can usually be narrowed 
4814            simply by changing their gtType */
4815
4816         case GT_LCL_VAR:
4817             /* We only allow narrowing long -> int for a GT_LCL_VAR */
4818             if (dstSize == sizeof(int))
4819                 goto NARROW_IND;
4820             break;
4821
4822         case GT_CLS_VAR:
4823         case GT_LCL_FLD:
4824             goto NARROW_IND;
4825         default:
4826         break;
4827         }
4828
4829         noway_assert(doit == false);
4830         return  false;
4831
4832     }
4833
4834     if (kind & (GTK_BINOP|GTK_UNOP))
4835     {
4836         GenTreePtr      op1; op1 = tree->gtOp.gtOp1;
4837         GenTreePtr      op2; op2 = tree->gtOp.gtOp2;
4838
4839         switch (tree->gtOper)
4840         {
4841         case GT_AND:
4842             noway_assert(genActualType(tree->gtType) == genActualType(op2->gtType));
4843
4844             // Is op2 a small constant than can be narrowed into dstt?
4845             // if so the result of the GT_AND will also fit into 'dstt' and can be narrowed
4846             if ((op2->gtOper == GT_CNS_INT)  &&  optNarrowTree(op2, srct, dstt, NoVNPair, false))
4847             {               
4848                 // We will change the type of the tree and narrow op2
4849                 //
4850                 if  (doit)
4851                 {
4852                     tree->gtType = genActualType(dstt);
4853                     tree->SetVNs(vnpNarrow);
4854
4855                     optNarrowTree(op2, srct, dstt, NoVNPair, true);
4856                     // We may also need to cast away the upper bits of op1
4857                     if (srcSize == 8) 
4858                     {
4859                         assert(tree->gtType == TYP_INT);
4860                         op1 = gtNewCastNode(TYP_INT, op1, TYP_INT);
4861 #ifdef DEBUG
4862                         op1->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED;
4863 #endif
4864                         tree->gtOp.gtOp1 = op1;
4865                     }
4866                 }
4867                 return true;
4868             }
4869             
4870             goto COMMON_BINOP;
4871
4872         case GT_ADD:
4873         case GT_MUL:
4874
4875             if (tree->gtOverflow() || varTypeIsSmall(dstt))
4876             {
4877                 noway_assert(doit == false);
4878                 return false;
4879             }
4880             __fallthrough;
4881
4882         case GT_OR:
4883         case GT_XOR:
4884 COMMON_BINOP:
4885             noway_assert(genActualType(tree->gtType) == genActualType(op1->gtType));
4886             noway_assert(genActualType(tree->gtType) == genActualType(op2->gtType));
4887
4888             if (gtIsActiveCSE_Candidate(op1)          ||
4889                 gtIsActiveCSE_Candidate(op2)          ||
4890                 !optNarrowTree(op1, srct, dstt, NoVNPair, doit) ||
4891                 !optNarrowTree(op2, srct, dstt, NoVNPair, doit)   )
4892             {
4893                 noway_assert(doit == false);
4894                 return  false;
4895             }
4896
4897             /* Simply change the type of the tree */
4898
4899             if  (doit)
4900             {
4901                 if  (tree->gtOper == GT_MUL && (tree->gtFlags & GTF_MUL_64RSLT))
4902                     tree->gtFlags &= ~GTF_MUL_64RSLT;
4903
4904                 tree->gtType = genActualType(dstt);
4905                 tree->SetVNs(vnpNarrow);
4906             }
4907
4908             return true;
4909
4910         case GT_IND:
4911
4912 NARROW_IND:
4913             /* Simply change the type of the tree */
4914
4915             if  (doit && (dstSize <= genTypeSize(tree->gtType)))
4916             {
4917                 tree->gtType = genSignedType(dstt);
4918                 tree->SetVNs(vnpNarrow);
4919
4920                 /* Make sure we don't mess up the variable type */
4921                 if  ((oper == GT_LCL_VAR) || (oper == GT_LCL_FLD))
4922                     tree->gtFlags |= GTF_VAR_CAST;
4923             }
4924
4925             return  true;
4926
4927         case GT_EQ:
4928         case GT_NE:
4929         case GT_LT:
4930         case GT_LE:
4931         case GT_GT:
4932         case GT_GE:
4933
4934             /* These can always be narrowed since they only represent 0 or 1 */
4935             return  true;
4936
4937         case GT_CAST:
4938             {
4939                 var_types       cast    = tree->CastToType();
4940                 var_types       oprt    = op1->TypeGet();
4941                 unsigned        oprSize = genTypeSize(oprt);
4942
4943                 if (cast != srct)
4944                     return false;
4945
4946                 if (varTypeIsIntegralOrI(dstt) != varTypeIsIntegralOrI(oprt))
4947                     return false;
4948
4949                 if (tree->gtOverflow())
4950                     return false;
4951
4952                 /* Is this a cast from the type we're narrowing to or a smaller one? */
4953
4954                 if  (oprSize <= dstSize)
4955                 {
4956                     /* Bash the target type of the cast */
4957
4958                     if  (doit)
4959                     {
4960                         dstt = genSignedType(dstt);
4961
4962                         if  (oprSize == dstSize)
4963                         {
4964                             // Same size: change the CAST into a NOP
4965                             tree->ChangeOper         (GT_NOP);
4966                             tree->gtType            = dstt;
4967                             tree->gtOp.gtOp2        = nullptr;
4968                             tree->gtVNPair          = op1->gtVNPair;   // Set to op1's ValueNumber
4969                         }
4970                         else
4971                         {
4972                             // oprSize is smaller
4973                             assert(oprSize < dstSize);
4974
4975                             // Change the CastToType in the GT_CAST node
4976                             tree->CastToType() = dstt;
4977
4978                             // The result type of a GT_CAST is never a small type.
4979                             // Use genActualType to widen dstt when it is a small types.
4980                             tree->gtType = genActualType(dstt);
4981                             tree->SetVNs(vnpNarrow);
4982                         }
4983                     }
4984
4985                     return  true;
4986                 }
4987             }
4988             return  false;
4989
4990         case GT_COMMA:
4991             if (!gtIsActiveCSE_Candidate(op2)  &&
4992                 optNarrowTree(op2, srct, dstt, vnpNarrow, doit))
4993             {               
4994                 /* Simply change the type of the tree */
4995
4996                 if  (doit)
4997                 {
4998                     tree->gtType = genActualType(dstt);
4999                     tree->SetVNs(vnpNarrow);
5000                 }
5001                 return true;
5002             }
5003             return false;
5004
5005         default:
5006             noway_assert(doit == false);
5007             return  false;
5008         }
5009
5010     }
5011
5012     return  false;
5013 }
5014
5015
5016 /*****************************************************************************
5017  *
5018  *  The following logic figures out whether the given variable is assigned
5019  *  somewhere in a list of basic blocks (or in an entire loop).
5020  */
5021
5022
5023 Compiler::fgWalkResult      Compiler::optIsVarAssgCB(GenTreePtr *pTree, fgWalkData *data)
5024 {
5025     GenTreePtr tree = *pTree;
5026
5027     if  (tree->OperKind() & GTK_ASGOP)
5028     {
5029         GenTreePtr      dest     = tree->gtOp.gtOp1;
5030         genTreeOps      destOper = dest->OperGet();
5031
5032         isVarAssgDsc *  desc = (isVarAssgDsc*)data->pCallbackData;
5033         assert(desc && desc->ivaSelf == desc);
5034
5035         if  (destOper == GT_LCL_VAR)
5036         {
5037             unsigned        tvar = dest->gtLclVarCommon.gtLclNum;
5038             if  (tvar < lclMAX_ALLSET_TRACKED)
5039                 AllVarSetOps::AddElemD(data->compiler, desc->ivaMaskVal, tvar);
5040             else
5041                 desc->ivaMaskIncomplete  = true;
5042
5043             if  (tvar == desc->ivaVar)
5044             {
5045                 if  (tree != desc->ivaSkip)
5046                     return  WALK_ABORT;
5047             }
5048         }
5049         else if (destOper == GT_LCL_FLD)
5050         {
5051             /* We can't track every field of every var. Moreover, indirections
5052                may access different parts of the var as different (but
5053                overlapping) fields. So just treat them as indirect accesses */
5054
5055             // unsigned    lclNum = dest->gtLclFld.gtLclNum;
5056             // noway_assert(lvaTable[lclNum].lvAddrTaken);
5057
5058             varRefKinds     refs = varTypeIsGC(tree->TypeGet()) ? VR_IND_REF
5059                                                                 : VR_IND_SCL;
5060             desc->ivaMaskInd = varRefKinds(desc->ivaMaskInd | refs);
5061         }
5062         else if (destOper == GT_CLS_VAR)
5063         {
5064             desc->ivaMaskInd = varRefKinds(desc->ivaMaskInd | VR_GLB_VAR);
5065         }
5066         else if (destOper == GT_IND)
5067         {
5068             /* Set the proper indirection bits */
5069
5070             varRefKinds refs = varTypeIsGC(tree->TypeGet()) ? VR_IND_REF
5071                                                             : VR_IND_SCL;
5072             desc->ivaMaskInd = varRefKinds(desc->ivaMaskInd | refs);
5073         }
5074     }
5075     else if (tree->gtOper == GT_CALL)
5076     {
5077         isVarAssgDsc *  desc = (isVarAssgDsc*)data->pCallbackData;
5078         assert(desc && desc->ivaSelf == desc);
5079
5080         desc->ivaMaskCall = optCallInterf(tree);
5081     }
5082
5083     return  WALK_CONTINUE;
5084 }
5085
5086 /*****************************************************************************/
5087
5088 bool                Compiler::optIsVarAssigned(BasicBlock *   beg,
5089                                                BasicBlock *   end,
5090                                                GenTreePtr     skip,
5091                                                unsigned       var)
5092 {
5093     bool            result;
5094     isVarAssgDsc    desc;
5095
5096     desc.ivaSkip     = skip;
5097 #ifdef DEBUG
5098     desc.ivaSelf     = &desc;
5099 #endif
5100     desc.ivaVar      = var;
5101     desc.ivaMaskCall = CALLINT_NONE;
5102     AllVarSetOps::AssignNoCopy(this, desc.ivaMaskVal, AllVarSetOps::MakeEmpty(this));
5103
5104     for (;;)
5105     {
5106         noway_assert(beg);
5107
5108         for (GenTreeStmt* stmt = beg->firstStmt(); stmt; stmt = stmt->gtNextStmt)
5109         {
5110             noway_assert(stmt->gtOper == GT_STMT);
5111             if  (fgWalkTreePre(&stmt->gtStmtExpr, optIsVarAssgCB, &desc))
5112             {
5113                 result = true;
5114                 goto DONE;
5115             }
5116         }
5117
5118         if  (beg == end)
5119             break;
5120
5121         beg = beg->bbNext;
5122     }
5123
5124     result = false;
5125
5126 DONE:
5127
5128     return  result;
5129 }
5130
5131 /*****************************************************************************/
5132 int                 Compiler::optIsSetAssgLoop(unsigned            lnum,
5133                                                ALLVARSET_VALARG_TP vars,
5134                                                varRefKinds         inds)
5135 {
5136     LoopDsc *       loop;
5137
5138     /* Get hold of the loop descriptor */
5139
5140     noway_assert(lnum < optLoopCount);
5141     loop = optLoopTable + lnum;
5142
5143     /* Do we already know what variables are assigned within this loop? */
5144
5145     if  (!(loop->lpFlags & LPFLG_ASGVARS_YES))
5146     {
5147         isVarAssgDsc    desc;
5148
5149         BasicBlock  *   beg;
5150         BasicBlock  *   end;
5151
5152         /* Prepare the descriptor used by the tree walker call-back */
5153
5154         desc.ivaVar     = (unsigned)-1;
5155         desc.ivaSkip    = NULL;
5156 #ifdef DEBUG
5157         desc.ivaSelf    = &desc;
5158 #endif
5159         AllVarSetOps::AssignNoCopy(this, desc.ivaMaskVal, AllVarSetOps::MakeEmpty(this));
5160         desc.ivaMaskInd        = VR_NONE;
5161         desc.ivaMaskCall       = CALLINT_NONE;
5162         desc.ivaMaskIncomplete = false;
5163
5164         /* Now walk all the statements of the loop */
5165
5166         beg = loop->lpHead->bbNext;
5167         end = loop->lpBottom;
5168
5169         for (/**/; /**/; beg = beg->bbNext)
5170         {
5171             noway_assert(beg);
5172
5173             for (GenTreeStmt* stmt = beg->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt)
5174             {
5175                 noway_assert(stmt->gtOper == GT_STMT);
5176                 fgWalkTreePre(&stmt->gtStmtExpr, optIsVarAssgCB, &desc);
5177
5178                 if  (desc.ivaMaskIncomplete)
5179                 {
5180                     loop->lpFlags |= LPFLG_ASGVARS_INC;
5181                 }
5182             }
5183
5184             if  (beg == end)
5185                 break;
5186         }
5187
5188         AllVarSetOps::Assign(this, loop->lpAsgVars, desc.ivaMaskVal);
5189         loop->lpAsgInds = desc.ivaMaskInd;
5190         loop->lpAsgCall = desc.ivaMaskCall;
5191
5192         /* Now we know what variables are assigned in the loop */
5193
5194         loop->lpFlags |= LPFLG_ASGVARS_YES;
5195     }
5196
5197     /* Now we can finally test the caller's mask against the loop's */
5198     if  (!AllVarSetOps::IsEmptyIntersection(this, loop->lpAsgVars, vars) ||
5199          (loop->lpAsgInds & inds))
5200     {
5201         return  1;
5202     }
5203
5204     switch (loop->lpAsgCall)
5205     {
5206     case CALLINT_ALL:
5207
5208         /* Can't hoist if the call might have side effect on an indirection. */
5209
5210         if (loop->lpAsgInds != VR_NONE)
5211             return  1;
5212
5213         break;
5214
5215     case CALLINT_REF_INDIRS:
5216
5217         /* Can't hoist if the call might have side effect on an ref indirection. */
5218
5219         if (loop->lpAsgInds & VR_IND_REF)
5220             return  1;
5221
5222         break;
5223
5224     case CALLINT_SCL_INDIRS:
5225
5226         /* Can't hoist if the call might have side effect on an non-ref indirection. */
5227
5228         if (loop->lpAsgInds & VR_IND_SCL)
5229             return  1;
5230
5231         break;
5232
5233     case CALLINT_ALL_INDIRS:
5234
5235         /* Can't hoist if the call might have side effect on any indirection. */
5236
5237         if (loop->lpAsgInds & (VR_IND_REF|VR_IND_SCL))
5238             return  1;
5239
5240         break;
5241
5242     case CALLINT_NONE:
5243
5244         /* Other helpers kill nothing */
5245
5246         break;
5247
5248     default:
5249         noway_assert(!"Unexpected lpAsgCall value");
5250     }
5251
5252     return  0;
5253 }
5254
5255 void                    Compiler::optPerformHoistExpr(GenTreePtr origExpr, unsigned lnum)
5256 {
5257 #ifdef DEBUG
5258     if (verbose)
5259     {
5260         printf("\nHoisting a copy of ");
5261         printTreeID(origExpr);
5262         printf(" into PreHeader for loop L%02u <BB%02u..BB%02u>:\n",
5263                lnum, optLoopTable[lnum].lpFirst->bbNum, optLoopTable[lnum].lpBottom->bbNum);
5264         gtDispTree(origExpr);
5265         printf("\n");
5266     }
5267 #endif
5268
5269     // This loop has to be in a form that is approved for hoisting.
5270     assert (optLoopTable[lnum].lpFlags & LPFLG_HOISTABLE);
5271
5272     // Create a copy of the expression and mark it for CSE's.   
5273     GenTreePtr hoistExpr = gtCloneExpr(origExpr, GTF_MAKE_CSE);
5274
5275     // At this point we should have a cloned expression, marked with the GTF_MAKE_CSE flag
5276     assert(hoistExpr != origExpr);
5277     assert(hoistExpr->gtFlags & GTF_MAKE_CSE);
5278
5279     GenTreePtr hoist = hoistExpr;
5280     // The value of the expression isn't used (unless it's an assignment).
5281     if (hoistExpr->OperGet() != GT_ASG)
5282     {
5283         hoist = gtUnusedValNode(hoistExpr);
5284     }
5285
5286     /* Put the statement in the preheader */
5287
5288     fgCreateLoopPreHeader(lnum);
5289
5290     BasicBlock *  preHead = optLoopTable[lnum].lpHead;
5291     assert (preHead->bbJumpKind == BBJ_NONE);
5292
5293     // fgMorphTree and lvaRecursiveIncRefCounts requires that compCurBB be the block that contains
5294     // (or in this case, will contain) the expression.
5295     compCurBB = preHead; 
5296     
5297     // Increment the ref counts of any local vars appearing in "hoist".
5298     // Note that we need to do this before fgMorphTree() as fgMorph() could constant
5299     // fold away some of the lcl vars referenced by "hoist".
5300     lvaRecursiveIncRefCounts(hoist);
5301
5302     hoist = fgMorphTree(hoist);
5303
5304     GenTreePtr hoistStmt = gtNewStmt(hoist);
5305     hoistStmt->gtFlags |= GTF_STMT_CMPADD;
5306
5307     /* simply append the statement at the end of the preHead's list */
5308
5309     GenTreePtr treeList = preHead->bbTreeList;
5310
5311     if (treeList)
5312     {
5313         /* append after last statement */
5314
5315         GenTreePtr  last = treeList->gtPrev;
5316         assert (last->gtNext == 0);
5317
5318         last->gtNext        = hoistStmt;
5319         hoistStmt->gtPrev   = last;
5320         treeList->gtPrev    = hoistStmt;
5321     }
5322     else
5323     {
5324         /* Empty pre-header - store the single statement in the block */
5325
5326         preHead->bbTreeList = hoistStmt;
5327         hoistStmt->gtPrev   = hoistStmt;
5328     }
5329
5330     hoistStmt->gtNext = nullptr;
5331
5332 #ifdef DEBUG
5333     if (verbose)
5334     {
5335         printf("This hoisted copy placed in PreHeader (BB%02u):\n", preHead->bbNum);
5336         gtDispTree(hoist);
5337     }
5338 #endif
5339
5340     if (fgStmtListThreaded)
5341     {
5342         gtSetStmtInfo(hoistStmt);
5343         fgSetStmtSeq(hoistStmt);
5344     }
5345
5346 #ifdef DEBUG
5347     if (m_nodeTestData != NULL)
5348     {
5349
5350         // What is the depth of the loop "lnum"?
5351         ssize_t depth = 0;
5352         unsigned lnumIter = lnum;
5353         while (optLoopTable[lnumIter].lpParent != BasicBlock::NOT_IN_LOOP)
5354         {
5355             depth++;
5356             lnumIter = optLoopTable[lnumIter].lpParent;
5357         }
5358
5359         NodeToTestDataMap* testData = GetNodeTestData();
5360
5361         TestLabelAndNum tlAndN;
5362         if (testData->Lookup(origExpr, &tlAndN) && tlAndN.m_tl == TL_LoopHoist)
5363         {
5364             if (tlAndN.m_num == -1)
5365             {
5366                 printf("Node ");
5367                 printTreeID(origExpr);
5368                 printf(" was declared 'do not hoist', but is being hoisted.\n");
5369                 assert(false);
5370             }
5371             else if (tlAndN.m_num != depth)
5372             {
5373                 printf("Node ");
5374                 printTreeID(origExpr);
5375                 printf(" was declared as hoistable from loop at nesting depth %d; actually hoisted from loop at depth %d.\n",
5376                        tlAndN.m_num, depth);
5377                 assert(false);
5378             }
5379             else
5380             {
5381                 // We've correctly hoisted this, so remove the annotation.  Later, we'll check for any remaining "must hoist" annotations.
5382                 testData->Remove(origExpr);
5383                 // Now we insert an annotation to make sure that "hoistExpr" is actually CSE'd.
5384                 tlAndN.m_tl = TL_CSE_Def;
5385                 tlAndN.m_num = m_loopHoistCSEClass++;
5386                 testData->Set(hoistExpr, tlAndN);
5387             }
5388         }
5389     }
5390 #endif
5391
5392 #if LOOP_HOIST_STATS
5393     if (!m_curLoopHasHoistedExpression)
5394     {
5395         m_loopsWithHoistedExpressions++;
5396         m_curLoopHasHoistedExpression = true;
5397     }
5398     m_totalHoistedExpressions++;
5399 #endif // LOOP_HOIST_STATS
5400
5401
5402 void                    Compiler::optHoistLoopCode()
5403 {
5404     // If we don't have any loops in the method then take an early out now.
5405     if (optLoopCount == 0)
5406         return;
5407
5408 #ifdef DEBUG
5409     unsigned jitNoHoist = JitConfig.JitNoHoist();
5410     if (jitNoHoist > 0)
5411     {
5412         return;
5413     }
5414 #endif
5415
5416 #if 0
5417     // The code in this #if has been useful in debugging loop cloning issues, by
5418     // enabling selective enablement of the loop cloning optimization according to
5419     // method hash.
5420 #ifdef DEBUG
5421     unsigned methHash = info.compMethodHash();
5422     char* lostr = getenv("loophoisthashlo");
5423     unsigned methHashLo = 0;
5424     if (lostr != NULL) 
5425     {
5426         sscanf_s(lostr, "%x", &methHashLo);
5427         // methHashLo = (unsigned(atoi(lostr)) << 2);  // So we don't have to use negative numbers.
5428     }
5429     char* histr = getenv("loophoisthashhi");
5430     unsigned methHashHi = UINT32_MAX;
5431     if (histr != NULL) 
5432     {
5433         sscanf_s(histr, "%x", &methHashHi);
5434         // methHashHi = (unsigned(atoi(histr)) << 2);  // So we don't have to use negative numbers.
5435     }
5436     if (methHash < methHashLo || methHash > methHashHi)
5437         return;
5438     printf("Doing loop hoisting in %s (0x%x).\n", info.compFullName, methHash);
5439 #endif  // DEBUG
5440 #endif  // 0     -- debugging loop cloning issues
5441
5442 #ifdef DEBUG
5443     if  (verbose)
5444     {
5445         printf("\n*************** In optHoistLoopCode()\n");
5446         printf("Blocks/Trees before phase\n");
5447         fgDispBasicBlocks(true);
5448         printf("");
5449     }
5450 #endif
5451
5452     // Consider all the loop nests, in outer-to-inner order (thus hoisting expressions outside the largest loop in which
5453     // they are invariant.)
5454     LoopHoistContext hoistCtxt(this);
5455     for (unsigned lnum = 0; lnum < optLoopCount; lnum++)
5456     {
5457         if (optLoopTable[lnum].lpFlags & LPFLG_REMOVED)
5458             continue;
5459
5460         if (optLoopTable[lnum].lpParent == BasicBlock::NOT_IN_LOOP)
5461         {
5462             optHoistLoopNest(lnum, &hoistCtxt);
5463         }
5464     }
5465
5466 #if DEBUG
5467     if  (fgModified)
5468     {    
5469         if (verbose)
5470         {
5471             printf("Blocks/Trees after optHoistLoopCode() modified flowgraph\n");
5472             fgDispBasicBlocks(true);
5473             printf("");
5474         }
5475
5476         // Make sure that the predecessor lists are accurate
5477         fgDebugCheckBBlist();
5478     }
5479 #endif
5480
5481 #ifdef DEBUG
5482     // Test Data stuff..
5483     // If we have no test data, early out.
5484     if (m_nodeTestData == NULL) return;
5485     NodeToTestDataMap* testData = GetNodeTestData();
5486     for (NodeToTestDataMap::KeyIterator ki = testData->Begin(); !ki.Equal(testData->End()); ++ki)
5487     {
5488         TestLabelAndNum tlAndN;
5489         GenTreePtr node = ki.Get();
5490         bool b = testData->Lookup(node, &tlAndN);
5491         assert(b);
5492         if (tlAndN.m_tl != TL_LoopHoist) continue;
5493         // Otherwise, it is a loop hoist annotation.
5494         assert(tlAndN.m_num < 100);  // >= 100 indicates nested static field address, should already have been moved.
5495         if (tlAndN.m_num >= 0)
5496         {
5497             printf("Node ");
5498             printTreeID(node);
5499             printf(" was declared 'must hoist', but has not been hoisted.\n");
5500             assert(false);
5501         }
5502     }
5503 #endif  // DEBUG
5504 }
5505
5506 void                    Compiler::optHoistLoopNest(unsigned lnum, LoopHoistContext* hoistCtxt)
5507 {
5508     // Do this loop, then recursively do all nested loops.
5509     CLANG_FORMAT_COMMENT_ANCHOR;
5510
5511 #if LOOP_HOIST_STATS
5512     // Record stats
5513     m_curLoopHasHoistedExpression = false;
5514     m_loopsConsidered++;
5515 #endif // LOOP_HOIST_STATS
5516
5517     optHoistThisLoop(lnum, hoistCtxt);
5518     
5519     VNSet* hoistedInCurLoop = hoistCtxt->ExtractHoistedInCurLoop();
5520
5521     if (optLoopTable[lnum].lpChild != BasicBlock::NOT_IN_LOOP)
5522     {
5523         // Add the ones hoisted in "lnum" to "hoistedInParents" for any nested loops.
5524         // TODO-Cleanup: we should have a set abstraction for loops.
5525         if (hoistedInCurLoop != nullptr)
5526         {
5527             for (VNSet::KeyIterator keys = hoistedInCurLoop->Begin(); !keys.Equal(hoistedInCurLoop->End()); ++keys)
5528             {
5529 #ifdef DEBUG
5530                 bool b;
5531                 assert(!hoistCtxt->m_hoistedInParentLoops.Lookup(keys.Get(), &b));
5532 #endif
5533                 hoistCtxt->m_hoistedInParentLoops.Set(keys.Get(), true);
5534             }
5535         }
5536
5537         for (unsigned child = optLoopTable[lnum].lpChild; child != BasicBlock::NOT_IN_LOOP; child = optLoopTable[child].lpSibling)
5538         {
5539             optHoistLoopNest(child, hoistCtxt);
5540         }
5541
5542         // Now remove them.
5543         // TODO-Cleanup: we should have a set abstraction for loops.
5544         if (hoistedInCurLoop != nullptr)
5545         {
5546             for (VNSet::KeyIterator keys = hoistedInCurLoop->Begin(); !keys.Equal(hoistedInCurLoop->End()); ++keys)
5547             {
5548                 // Note that we asserted when we added these that they hadn't been members, so removing is appropriate.
5549                 hoistCtxt->m_hoistedInParentLoops.Remove(keys.Get());
5550             }
5551         }
5552     }
5553 }
5554
5555 void                    Compiler::optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt)
5556 {
5557     LoopDsc* pLoopDsc = &optLoopTable[lnum];
5558
5559     /* If loop was removed continue */
5560
5561     if  (pLoopDsc->lpFlags & LPFLG_REMOVED)
5562         return;
5563
5564     /* Get the head and tail of the loop */
5565
5566     BasicBlock* head = pLoopDsc->lpHead;
5567     BasicBlock* tail = pLoopDsc->lpBottom;
5568     BasicBlock* lbeg = pLoopDsc->lpEntry;
5569     BasicBlock* block;
5570
5571     // We must have a do-while loop
5572     if ((pLoopDsc->lpFlags & LPFLG_DO_WHILE) == 0)
5573         return;
5574
5575     // The loop-head must dominate the loop-entry.
5576     // TODO-CQ: Couldn't we make this true if it's not?
5577     if (!fgDominate(head, lbeg))
5578         return;
5579
5580     // if lbeg is the start of a new try block then we won't be able to hoist
5581     if (!BasicBlock::sameTryRegion(head, lbeg))
5582         return;
5583
5584     // We don't bother hoisting when inside of a catch block
5585     if ((lbeg->bbCatchTyp != BBCT_NONE) && (lbeg->bbCatchTyp != BBCT_FINALLY))
5586         return;
5587
5588     pLoopDsc->lpFlags |= LPFLG_HOISTABLE;
5589
5590     unsigned        begn = lbeg->bbNum;
5591     unsigned        endn = tail->bbNum;
5592
5593     // Ensure the per-loop sets/tables are empty.
5594     hoistCtxt->m_curLoopVnInvariantCache.RemoveAll();
5595
5596 #ifdef  DEBUG
5597     if  (verbose)
5598     {
5599         printf("optHoistLoopCode for loop L%02u <BB%02u..BB%02u>:\n", lnum, begn, endn);
5600         printf("  Loop body %s a call\n", pLoopDsc->lpContainsCall ?  "contains" : "does not contain");
5601     }
5602 #endif
5603
5604     VARSET_TP VARSET_INIT_NOCOPY(loopVars, VarSetOps::Intersection(this, pLoopDsc->lpVarInOut,
5605                                                                          pLoopDsc->lpVarUseDef));
5606
5607     pLoopDsc->lpVarInOutCount    = VarSetOps::Count(this, pLoopDsc->lpVarInOut);
5608     pLoopDsc->lpLoopVarCount     = VarSetOps::Count(this, loopVars);
5609     pLoopDsc->lpHoistedExprCount = 0;
5610
5611 #ifndef _TARGET_64BIT_
5612     unsigned longVarsCount = VarSetOps::Count(this, lvaLongVars);
5613
5614     if (longVarsCount > 0)
5615     {
5616         // Since 64-bit variables take up two registers on 32-bit targets, we increase
5617         //  the Counts such that each TYP_LONG variable counts twice.
5618         //
5619         VARSET_TP VARSET_INIT_NOCOPY(loopLongVars,  VarSetOps::Intersection(this, loopVars, lvaLongVars));
5620         VARSET_TP VARSET_INIT_NOCOPY(inOutLongVars, VarSetOps::Intersection(this,  pLoopDsc->lpVarInOut, lvaLongVars));
5621
5622 #ifdef  DEBUG
5623         if  (verbose)
5624         {
5625             printf("\n  LONGVARS(%d)=",  VarSetOps::Count(this, lvaLongVars));
5626                                          lvaDispVarSet(lvaLongVars);
5627         }
5628 #endif
5629         pLoopDsc->lpLoopVarCount  += VarSetOps::Count(this, loopLongVars);
5630         pLoopDsc->lpVarInOutCount += VarSetOps::Count(this, inOutLongVars);
5631     }
5632 #endif // !_TARGET_64BIT_
5633
5634 #ifdef  DEBUG
5635     if  (verbose)
5636     {
5637         printf("\n  USEDEF  (%d)=",  VarSetOps::Count(this, pLoopDsc->lpVarUseDef));
5638                                      lvaDispVarSet(pLoopDsc->lpVarUseDef);
5639
5640         printf("\n  INOUT   (%d)=",  pLoopDsc->lpVarInOutCount);
5641                                      lvaDispVarSet(pLoopDsc->lpVarInOut);
5642                                      
5643         printf("\n  LOOPVARS(%d)=",  pLoopDsc->lpLoopVarCount);
5644                                      lvaDispVarSet(loopVars);
5645         printf("\n");
5646     }
5647 #endif
5648
5649     unsigned floatVarsCount = VarSetOps::Count(this, lvaFloatVars);
5650
5651     if (floatVarsCount > 0)
5652     {
5653         VARSET_TP VARSET_INIT_NOCOPY(loopFPVars,  VarSetOps::Intersection(this, loopVars, lvaFloatVars));
5654         VARSET_TP VARSET_INIT_NOCOPY(inOutFPVars, VarSetOps::Intersection(this,  pLoopDsc->lpVarInOut, lvaFloatVars));                                                        
5655
5656         pLoopDsc->lpLoopVarFPCount     = VarSetOps::Count(this, loopFPVars);
5657         pLoopDsc->lpVarInOutFPCount    = VarSetOps::Count(this, inOutFPVars);
5658         pLoopDsc->lpHoistedFPExprCount = 0;
5659
5660         pLoopDsc->lpLoopVarCount  -= pLoopDsc->lpLoopVarFPCount;
5661         pLoopDsc->lpVarInOutCount -= pLoopDsc->lpVarInOutFPCount;
5662
5663 #ifdef  DEBUG
5664         if  (verbose)
5665         {
5666             printf(  "  INOUT-FP(%d)=",  pLoopDsc->lpVarInOutFPCount);
5667                                          lvaDispVarSet(inOutFPVars);
5668
5669             printf("\n  LOOPV-FP(%d)=",  pLoopDsc->lpLoopVarFPCount);
5670                                          lvaDispVarSet(loopFPVars);
5671         }
5672 #endif
5673     }
5674     else // (floatVarsCount == 0)
5675     {
5676         pLoopDsc->lpLoopVarFPCount     = 0;
5677         pLoopDsc->lpVarInOutFPCount    = 0;
5678         pLoopDsc->lpHoistedFPExprCount = 0;
5679     }
5680
5681     // Find the set of definitely-executed blocks.
5682     // Ideally, the definitely-executed blocks are the ones that post-dominate the entry block.
5683     // Until we have post-dominators, we'll special-case for single-exit blocks.
5684     ExpandArrayStack<BasicBlock*> defExec(getAllocatorLoopHoist());
5685     if (pLoopDsc->lpFlags & LPFLG_ONE_EXIT)
5686     {
5687         assert(pLoopDsc->lpExit != nullptr);
5688         BasicBlock* cur = pLoopDsc->lpExit;
5689         // Push dominators, until we reach "entry" or exit the loop.
5690         while (   cur != nullptr 
5691                && pLoopDsc->lpContains(cur)
5692                && cur != pLoopDsc->lpEntry)
5693         {
5694             defExec.Push(cur);
5695             cur = cur->bbIDom;
5696         }
5697         // If we didn't reach the entry block, give up and *just* push the entry block.
5698         if (cur != pLoopDsc->lpEntry)
5699         {
5700             defExec.Reset();
5701         }
5702         defExec.Push(pLoopDsc->lpEntry);
5703     }
5704     else  // More than one exit 
5705     {
5706         // We'll assume that only the entry block is definitely executed.  
5707         // We could in the future do better.
5708         defExec.Push(pLoopDsc->lpEntry);
5709     }
5710
5711     while (defExec.Size() > 0)
5712     {
5713         // Consider in reverse order: dominator before dominatee.
5714         BasicBlock* blk = defExec.Pop();
5715         optHoistLoopExprsForBlock(blk, lnum, hoistCtxt);
5716     }
5717 }
5718
5719 // Hoist any expressions in "blk" that are invariant in loop "lnum" outside of "blk" and into a PreHead for loop "lnum".
5720 void Compiler::optHoistLoopExprsForBlock(BasicBlock* blk, 
5721                                          unsigned lnum, 
5722                                          LoopHoistContext* hoistCtxt) 
5723 {
5724     LoopDsc* pLoopDsc = &optLoopTable[lnum];
5725     bool firstBlockAndBeforeSideEffect = (blk == pLoopDsc->lpEntry);
5726     unsigned blkWeight = blk->getBBWeight(this);
5727
5728 #ifdef  DEBUG
5729     if  (verbose)
5730     {
5731         printf("    optHoistLoopExprsForBlock BB%02u (weight=%6s) of loop L%02u <BB%02u..BB%02u>, firstBlock is %s\n",
5732                blk->bbNum,
5733                refCntWtd2str(blkWeight),
5734                lnum, 
5735                pLoopDsc->lpFirst->bbNum, 
5736                pLoopDsc->lpBottom->bbNum, 
5737                firstBlockAndBeforeSideEffect ? "true" : "false");
5738         if (blkWeight <  (BB_UNITY_WEIGHT / 10))
5739         {
5740             printf("      block weight is too small to perform hoisting.\n");
5741         }
5742     }
5743 #endif
5744
5745      if (blkWeight <  (BB_UNITY_WEIGHT / 10))
5746      {
5747          // Block weight is too small to perform hoisting.
5748          return;
5749      }
5750
5751     for (GenTreeStmt* stmt = blk->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt)
5752     {
5753         GenTreePtr stmtTree = stmt->gtStmtExpr;
5754         bool hoistable;
5755         (void)optHoistLoopExprsForTree(stmtTree, lnum, hoistCtxt, &firstBlockAndBeforeSideEffect, &hoistable);
5756         if (hoistable)
5757         {
5758             // we will try to hoist the top-level stmtTree
5759             optHoistCandidate(stmtTree, lnum, hoistCtxt);
5760         }
5761     }
5762 }
5763
5764 bool Compiler::optIsProfitableToHoistableTree(GenTreePtr tree, unsigned lnum)
5765 {
5766     LoopDsc* pLoopDsc = &optLoopTable[lnum];
5767
5768     bool loopContainsCall = pLoopDsc->lpContainsCall;
5769
5770     int availRegCount;
5771     int hoistedExprCount;
5772     int loopVarCount;
5773     int varInOutCount;
5774
5775     if (varTypeIsFloating(tree->TypeGet()))
5776     {
5777         hoistedExprCount = pLoopDsc->lpHoistedFPExprCount;
5778         loopVarCount     = pLoopDsc->lpLoopVarFPCount;
5779         varInOutCount    = pLoopDsc->lpVarInOutFPCount;
5780
5781        availRegCount = CNT_CALLEE_SAVED_FLOAT;
5782         if (!loopContainsCall)
5783         {
5784             availRegCount += CNT_CALLEE_TRASH_FLOAT-1;
5785         }
5786 #ifdef _TARGET_ARM_
5787         // For ARM each double takes two FP registers 
5788         // For now on ARM we won't track singles/doubles 
5789         // and instead just assume that we always have doubles.
5790         //
5791         availRegCount /= 2;
5792 #endif
5793     }
5794     else
5795     {
5796         hoistedExprCount = pLoopDsc->lpHoistedExprCount;
5797         loopVarCount     = pLoopDsc->lpLoopVarCount;
5798         varInOutCount    = pLoopDsc->lpVarInOutCount;
5799
5800         availRegCount = CNT_CALLEE_SAVED-1;
5801         if (!loopContainsCall)
5802         {
5803             availRegCount += CNT_CALLEE_TRASH-1;
5804         }
5805 #ifndef _TARGET_64BIT_
5806         // For our 32-bit targets Long types take two registers.
5807         if (varTypeIsLong(tree->TypeGet()))
5808         {
5809             availRegCount = (availRegCount+1) / 2;
5810         }
5811 #endif
5812     }
5813
5814     // decrement the availRegCount by the count of expression that we have already hoisted.
5815     availRegCount -= hoistedExprCount;
5816
5817     // the variables that are read/written inside the loop should 
5818     // always be a subset of the InOut variables for the loop
5819     assert(loopVarCount <= varInOutCount);
5820
5821     // When loopVarCount >= availRegCount we believe that all of the
5822     // available registers will get used to hold LclVars inside the loop.
5823     // This pessimistically assumes that each loopVar has a conflicting 
5824     // lifetime with every other loopVar.
5825     // For this case we will hoist the expression only if is profitable
5826     // to place it in a stack home location (gtCostEx >= 2*IND_COST_EX)
5827     // as we believe it will be placed in the stack or one of the other
5828     // loopVars will be spilled into the stack
5829     //
5830     if (loopVarCount >= availRegCount)
5831     {
5832         // Don't hoist expressions that are not heavy: tree->gtCostEx < (2*IND_COST_EX)
5833         if (tree->gtCostEx < (2*IND_COST_EX))
5834             return false;
5835     }
5836
5837     // When varInOutCount < availRegCount we are know that there are 
5838     // some available register(s) when we enter the loop body.
5839     // When varInOutCount == availRegCount there often will be a register
5840     // available when we enter the loop body, since a loop often defines a 
5841     // LclVar on exit or there is often at least one LclVar that is worth 
5842     // spilling to the stack to make way for this hoisted expression.
5843     // So we are willing hoist an expression with gtCostEx == MIN_CSE_COST
5844     //
5845     if (varInOutCount > availRegCount)
5846     {
5847         // Don't hoist expressions that barely meet CSE cost requirements: tree->gtCostEx == MIN_CSE_COST
5848         if (tree->gtCostEx <= MIN_CSE_COST+1)
5849             return false;
5850     }
5851
5852     return true;
5853 }
5854
5855 //
5856 //  This function returns true if 'tree' is a loop invariant expression.
5857 //  It also sets '*pHoistable' to true if 'tree' can be hoisted into a loop PreHeader block
5858 //
5859 bool Compiler::optHoistLoopExprsForTree(GenTreePtr tree,
5860                                         unsigned lnum,
5861                                         LoopHoistContext* hoistCtxt,
5862                                         bool* pFirstBlockAndBeforeSideEffect,
5863                                         bool* pHoistable)
5864 {
5865     // First do the children.
5866     // We must keep track of whether each child node was hoistable or not
5867     //
5868     unsigned nChildren = tree->NumChildren();
5869     bool childrenHoistable[GenTree::MAX_CHILDREN];
5870
5871     // Initialize the array elements for childrenHoistable[] to false
5872     for (unsigned i = 0; i < nChildren; i++)
5873     {
5874         childrenHoistable[i] = false;
5875     }
5876
5877     bool treeIsInvariant = true;
5878     for (unsigned childNum = 0; childNum < nChildren; childNum++)
5879     {
5880         if (!optHoistLoopExprsForTree(tree->GetChild(childNum), lnum, hoistCtxt, pFirstBlockAndBeforeSideEffect, &childrenHoistable[childNum]))
5881         {
5882             treeIsInvariant = false;
5883         }
5884     }
5885
5886     // If all the children of "tree" are hoistable, then "tree" itself can be hoisted
5887     //
5888     bool treeIsHoistable = treeIsInvariant;
5889
5890     // But we must see if anything else prevents "tree" from being hoisted.
5891     //
5892     if (treeIsInvariant)
5893     {
5894         // Tree must be a suitable CSE candidate for us to be able to hoist it.
5895         treeIsHoistable = optIsCSEcandidate(tree);
5896
5897         // If it's a call, it must be a helper call, and be pure.
5898         // Further, if it may run a cctor, it must be labeled as "Hoistable" 
5899         // (meaning it won't run a cctor because the class is not precise-init).
5900         if (treeIsHoistable && tree->OperGet() == GT_CALL)
5901         {
5902             GenTreeCall* call = tree->AsCall();
5903             if (call->gtCallType != CT_HELPER)
5904             {
5905                 treeIsHoistable = false;
5906             }
5907             else
5908             {
5909                 CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd);
5910                 if (!s_helperCallProperties.IsPure(helpFunc))
5911                 {
5912                     treeIsHoistable = false;
5913                 }
5914                 else if (   s_helperCallProperties.MayRunCctor(helpFunc)
5915                          && (call->gtFlags & GTF_CALL_HOISTABLE) == 0)
5916                 {
5917                     treeIsHoistable = false;
5918                 }
5919             }
5920         }
5921
5922         if (treeIsHoistable)
5923         {
5924             if (!(*pFirstBlockAndBeforeSideEffect))
5925             {
5926                 // For now, we give up on an expression that might raise an exception if it is after the
5927                 // first possible global side effect (and we assume we're after that if we're not in the first block).
5928                 //TODO-CQ: this is when we might do loop cloning.
5929                 //
5930                 if ((tree->gtFlags & GTF_EXCEPT) != 0)
5931                 {
5932                     treeIsHoistable = false;
5933                 }
5934             }
5935             // Currently we must give up on reads from static variables (even if we are in the first block).
5936             //
5937             if (tree->OperGet() == GT_CLS_VAR)
5938             {
5939                 // TODO-CQ: test that fails if we hoist GT_CLS_VAR: JIT\Directed\Languages\ComponentPascal\pi_r.exe method Main
5940                 treeIsHoistable = false;
5941             }
5942         }
5943
5944         // Is the value of the whole tree loop invariant?
5945         treeIsInvariant = optVNIsLoopInvariant(tree->gtVNPair.GetLiberal(), lnum, &hoistCtxt->m_curLoopVnInvariantCache);
5946
5947         // Is the value of the whole tree loop invariant?
5948         if (!treeIsInvariant)
5949         {
5950             treeIsHoistable = false;
5951         }
5952     }
5953
5954     // Check if we need to set '*pFirstBlockAndBeforeSideEffect' to false.
5955     // If we encounter a tree with a call in it 
5956     //  or if we see an assignment to global we set it to false.
5957     //
5958     // If we are already set to false then we can skip these checks
5959     //
5960     if (*pFirstBlockAndBeforeSideEffect)
5961     {
5962         // For this purpose, we only care about memory side effects.  We assume that expressions will
5963         // be hoisted so that they are evaluated in the same order as they would have been in the loop,
5964         // and therefore throw exceptions in the same order.  (So we don't use GTF_GLOBALLY_VISIBLE_SIDE_EFFECTS
5965         // here, since that includes exceptions.)
5966         if (tree->gtFlags & GTF_CALL)
5967         {
5968             *pFirstBlockAndBeforeSideEffect = false;
5969         } 
5970         else if (tree->OperIsAssignment())
5971         {
5972             // If the LHS of the assignment has a global reference, then assume it's a global side effect.
5973             GenTreePtr lhs = tree->gtOp.gtOp1;
5974             if (lhs->gtFlags & GTF_GLOB_REF)
5975             {
5976                 *pFirstBlockAndBeforeSideEffect = false;
5977             }
5978         } else if (tree->OperIsCopyBlkOp())
5979         {
5980             GenTreePtr args = tree->gtOp.gtOp1;
5981             assert(args->OperGet() == GT_LIST);
5982             if (args->gtOp.gtOp1->gtFlags & GTF_GLOB_REF)
5983             {
5984                 *pFirstBlockAndBeforeSideEffect = false;
5985             }
5986         }
5987     }
5988     
5989     // If this 'tree' is hoistable then we return and the caller will
5990     // decide to hoist it as part of larger hoistable expression.
5991     //
5992     if (!treeIsHoistable)
5993     {
5994         // We are not hoistable so we will now hoist any hoistable children.
5995         //
5996         for (unsigned childNum = 0; childNum < nChildren; childNum++)
5997         {
5998             if (childrenHoistable[childNum])
5999             {
6000                 // We can't hoist the LHS of an assignment, isn't a real use. 
6001                 if (childNum == 0 && (tree->OperIsAssignment())) 
6002                     continue;
6003
6004                 GenTreePtr child = tree->GetChild(childNum);
6005
6006                 // We try to hoist this 'child' tree
6007                 optHoistCandidate(child, lnum, hoistCtxt);
6008             }
6009         }
6010     }
6011
6012     *pHoistable = treeIsHoistable;
6013     return treeIsInvariant;
6014 }
6015
6016 void Compiler::optHoistCandidate(GenTreePtr tree, unsigned lnum, LoopHoistContext* hoistCtxt)
6017 {
6018     if (lnum == BasicBlock::NOT_IN_LOOP)
6019     {
6020         // The hoisted expression isn't valid at any loop head so don't hoist this expression.
6021         return;
6022     }
6023
6024     // The outer loop also must be suitable for hoisting...
6025     if ((optLoopTable[lnum].lpFlags & LPFLG_HOISTABLE) == 0)
6026         return;
6027
6028     // If the hoisted expression isn't valid at this loop head then break
6029     if (!optTreeIsValidAtLoopHead(tree, lnum))
6030         return;
6031
6032     // It must pass the hoistable profitablity tests for this loop level
6033     if (!optIsProfitableToHoistableTree(tree, lnum))
6034         return;
6035
6036
6037     bool b;
6038     if (hoistCtxt->m_hoistedInParentLoops.Lookup(tree->gtVNPair.GetLiberal(), &b))
6039     {
6040         // already hoisted in a parent loop, so don't hoist this expression.
6041         return;
6042     }
6043     
6044     if (hoistCtxt->GetHoistedInCurLoop(this)->Lookup(tree->gtVNPair.GetLiberal(), &b))
6045     {
6046         // already hoisted this expression in the current loop, so don't hoist this expression.
6047         return;
6048     }
6049
6050     // Expression can be hoisted 
6051     optPerformHoistExpr(tree, lnum);
6052
6053     // Increment lpHoistedExprCount or lpHoistedFPExprCount 
6054     if (!varTypeIsFloating(tree->TypeGet()))
6055     {
6056         optLoopTable[lnum].lpHoistedExprCount++; 
6057 #ifndef _TARGET_64BIT_
6058         // For our 32-bit targets Long types take two registers.
6059         if (varTypeIsLong(tree->TypeGet()))
6060         {
6061             optLoopTable[lnum].lpHoistedExprCount++; 
6062         }
6063 #endif
6064     }
6065     else // Floating point expr hoisted
6066     {
6067         optLoopTable[lnum].lpHoistedFPExprCount++; 
6068     }
6069
6070     // Record the hoisted expression in hoistCtxt
6071     hoistCtxt->GetHoistedInCurLoop(this)->Set(tree->gtVNPair.GetLiberal(), true);
6072 }
6073
6074
6075 bool Compiler::optVNIsLoopInvariant(ValueNum vn, unsigned lnum, VNToBoolMap* loopVnInvariantCache)
6076 {
6077     // If it is not a VN, is not loop-invariant.
6078     if (vn == ValueNumStore::NoVN) return false;
6079
6080     // We'll always short-circuit constants.
6081     if (vnStore->IsVNConstant(vn) || vn == vnStore->VNForVoid())
6082         return true;
6083
6084     // If we've done this query previously, don't repeat.
6085     bool previousRes = false;
6086     if (loopVnInvariantCache->Lookup(vn, &previousRes))
6087         return previousRes;
6088
6089     bool res = true;
6090     VNFuncApp funcApp;
6091     if (vnStore->GetVNFunc(vn, &funcApp))
6092     {
6093         if (funcApp.m_func == VNF_PhiDef)
6094         {
6095             // First, make sure it's a "proper" phi -- the definition is a Phi application.
6096             VNFuncApp phiDefValFuncApp;
6097             if (   !vnStore->GetVNFunc(funcApp.m_args[2], &phiDefValFuncApp)
6098                 || phiDefValFuncApp.m_func != VNF_Phi)
6099             {
6100                 // It's not *really* a definition, rather a pass-through of some other VN.
6101                 // (This could occur, say if both sides of an if-then-else diamond made the
6102                 // same assignment to a variable.)
6103                 res = optVNIsLoopInvariant(funcApp.m_args[2], lnum, loopVnInvariantCache);
6104             }
6105             else
6106             {
6107                 // Is the definition within the loop?  If so, is not loop-invariant.
6108                 unsigned lclNum = funcApp.m_args[0];
6109                 unsigned ssaNum = funcApp.m_args[1];
6110                 LclSsaVarDsc* ssaDef = lvaTable[lclNum].GetPerSsaData(ssaNum);
6111                 res = !optLoopContains(lnum, ssaDef->m_defLoc.m_blk->bbNatLoopNum);
6112             }
6113         }
6114         else if (funcApp.m_func == VNF_PhiHeapDef)
6115         {
6116             BasicBlock* defnBlk = reinterpret_cast<BasicBlock*>(vnStore->ConstantValue<ssize_t>(funcApp.m_args[0]));
6117             res = !optLoopContains(lnum, defnBlk->bbNatLoopNum);
6118         }
6119         else
6120         {
6121             for (unsigned i = 0; i < funcApp.m_arity; i++)
6122             {
6123                 // TODO-CQ: We need to either make sure that *all* VN functions
6124                 // always take VN args, or else have a list of arg positions to exempt, as implicitly
6125                 // constant.
6126                 if (!optVNIsLoopInvariant(funcApp.m_args[i], lnum, loopVnInvariantCache))
6127                 {
6128                     res = false;
6129                     break;
6130                 }
6131             }
6132         }
6133     }
6134     else
6135     {
6136         // Otherwise, assume non-function "new, unique" VN's are not loop invariant.
6137         res = false;
6138     }
6139     
6140     loopVnInvariantCache->Set(vn, res);
6141     return res;
6142 }
6143
6144 bool                Compiler::optTreeIsValidAtLoopHead(GenTreePtr tree, unsigned lnum)
6145 {
6146     if (tree->OperIsLocal())
6147     {
6148         GenTreeLclVarCommon* lclVar = tree->AsLclVarCommon();
6149         unsigned lclNum = lclVar->gtLclNum;
6150
6151         // The lvlVar must be have an Ssa tracked lifetime
6152         if (fgExcludeFromSsa(lclNum))
6153             return false;
6154
6155         // If the loop does not contains the SSA def we can hoist it.
6156         if (!optLoopTable[lnum].lpContains(lvaTable[lclNum].GetPerSsaData(lclVar->GetSsaNum())->m_defLoc.m_blk))
6157             return true;
6158     }
6159     else if (tree->OperIsConst())
6160     {
6161         return true;
6162     }
6163     else  // If every one of the children nodes are valid at this Loop's Head.
6164     {
6165         unsigned nChildren = tree->NumChildren();
6166         for (unsigned childNum = 0; childNum < nChildren; childNum++)
6167         {
6168             if (!optTreeIsValidAtLoopHead(tree->GetChild(childNum), lnum))
6169                 return false;
6170         }
6171         return true;
6172     }
6173     return false;
6174 }
6175
6176
6177 /*****************************************************************************
6178  *
6179  *  Creates a pre-header block for the given loop - a preheader is a BBJ_NONE
6180  *  header. The pre-header will replace the current lpHead in the loop table.
6181  *  The loop has to be a do-while loop. Thus, all blocks dominated by lpHead
6182  *  will also be dominated by the loop-top, lpHead->bbNext. 
6183  *
6184  */
6185
6186 void                 Compiler::fgCreateLoopPreHeader(unsigned   lnum)
6187 {
6188     LoopDsc* pLoopDsc = &optLoopTable[lnum];
6189
6190     /* This loop has to be a "do-while" loop */
6191
6192     assert (pLoopDsc->lpFlags & LPFLG_DO_WHILE);
6193     
6194     /* Have we already created a loop-preheader block? */
6195
6196     if (pLoopDsc->lpFlags & LPFLG_HAS_PREHEAD)
6197         return;
6198
6199     BasicBlock* head  = pLoopDsc->lpHead;
6200     BasicBlock* top   = pLoopDsc->lpTop;
6201     BasicBlock* entry = pLoopDsc->lpEntry;
6202
6203     // if 'entry' and 'head' are in different try regions then we won't be able to hoist
6204     if (!BasicBlock::sameTryRegion(head, entry))
6205         return;
6206
6207     // Ensure that lpHead always dominates lpEntry
6208
6209     noway_assert(fgDominate(head, entry));
6210     
6211     /* Get hold of the first block of the loop body */
6212
6213     assert (top == entry);
6214
6215     /* Allocate a new basic block */
6216
6217     BasicBlock * preHead = bbNewBasicBlock(BBJ_NONE);
6218     preHead->bbFlags    |= BBF_INTERNAL | BBF_LOOP_PREHEADER;
6219
6220     // Must set IL code offset
6221     preHead->bbCodeOffs  = top->bbCodeOffs;
6222
6223     // Set the default value of the preHead weight in case we don't have 
6224     // valid profile data and since this blocks weight is just an estimate
6225     // we clear any BBF_PROF_WEIGHT flag that we may have picked up from head.
6226     //
6227     preHead->inheritWeight(head);
6228     preHead->bbFlags &= ~BBF_PROF_WEIGHT;
6229
6230 #ifdef  DEBUG
6231     if  (verbose)
6232         printf("\nCreated PreHeader (BB%02u) for loop L%02u (BB%02u - BB%02u), with weight = %s\n",
6233                preHead->bbNum, lnum, top->bbNum, pLoopDsc->lpBottom->bbNum, 
6234                refCntWtd2str(preHead->getBBWeight(this)));
6235 #endif
6236
6237     // The preheader block is part of the containing loop (if any).
6238     preHead->bbNatLoopNum = pLoopDsc->lpParent;
6239
6240     if (fgIsUsingProfileWeights() && (head->bbJumpKind == BBJ_COND))
6241     {
6242         if ((head->bbWeight == 0)  || (head->bbNext->bbWeight == 0))
6243         {
6244             preHead->bbWeight = 0;
6245             preHead->bbFlags |= BBF_RUN_RARELY;
6246         }
6247         else
6248         {
6249             bool allValidProfileWeights = ((head->bbFlags             & BBF_PROF_WEIGHT) != 0)
6250                                        && ((head->bbJumpDest->bbFlags & BBF_PROF_WEIGHT) != 0)
6251                                        && ((head->bbNext->bbFlags     & BBF_PROF_WEIGHT) != 0);
6252            
6253             if (allValidProfileWeights)
6254             {
6255                 double loopEnteredCount;
6256                 double loopSkippedCount;
6257
6258                 if (fgHaveValidEdgeWeights)
6259                 {
6260                     flowList * edgeToNext = fgGetPredForBlock(head->bbNext, head);
6261                     flowList * edgeToJump = fgGetPredForBlock(head->bbJumpDest, head);
6262                     noway_assert(edgeToNext != NULL);
6263                     noway_assert(edgeToJump != NULL);
6264
6265                     loopEnteredCount = ((double) edgeToNext->flEdgeWeightMin  + (double) edgeToNext->flEdgeWeightMax)  / 2.0;
6266                     loopSkippedCount = ((double) edgeToJump->flEdgeWeightMin  + (double) edgeToJump->flEdgeWeightMax)  / 2.0;
6267                 }
6268                 else
6269                 {
6270                     loopEnteredCount = (double) head->bbNext->bbWeight;
6271                     loopSkippedCount = (double) head->bbJumpDest->bbWeight;
6272                 }
6273
6274                 double loopTakenRatio = loopEnteredCount / (loopEnteredCount + loopSkippedCount);
6275
6276                 // Calculate a good approximation of the preHead's block weight
6277                 unsigned preHeadWeight = (unsigned) (((double) head->bbWeight * loopTakenRatio) + 0.5);
6278                 preHead->setBBWeight(max(preHeadWeight, 1));
6279                 noway_assert(!preHead->isRunRarely());
6280              }
6281         }
6282     }
6283
6284     // Link in the preHead block.
6285     fgInsertBBbefore(top, preHead);
6286
6287     // Ideally we would re-run SSA and VN if we optimized by doing loop hoisting.
6288     // However, that is too expensive at this point. Instead, we update the phi
6289     // node block references, if we created pre-header block due to hoisting.
6290     // This is sufficient because any definition participating in SSA that flowed
6291     // into the phi via the loop header block will now flow through the preheader
6292     // block from the header block.
6293
6294     for (GenTreePtr stmt = top->bbTreeList; stmt; stmt = stmt->gtNext)
6295     {
6296         GenTreePtr tree = stmt->gtStmt.gtStmtExpr;
6297         if (tree->OperGet() != GT_ASG)
6298         {
6299             break;
6300         }
6301         GenTreePtr op2 = tree->gtGetOp2();
6302         if (op2->OperGet() != GT_PHI)
6303         {
6304             break;
6305         }
6306         GenTreeArgList* args = op2->gtGetOp1()->AsArgList();
6307         while (args != nullptr)
6308         {
6309             GenTreePhiArg* phiArg = args->Current()->AsPhiArg();
6310             if (phiArg->gtPredBB == head)
6311             {
6312                 phiArg->gtPredBB = preHead;
6313             }
6314             args = args->Rest();
6315         }
6316     }
6317
6318     // The handler can't begin at the top of the loop.  If it did, it would be incorrect
6319     // to set the handler index on the pre header without updating the exception table.
6320     noway_assert(!top->hasHndIndex() || fgFirstBlockOfHandler(top) != top);
6321
6322     // Update the EH table to make the hoisted block part of the loop's EH block.
6323     fgExtendEHRegionBefore(top);
6324
6325     // TODO-CQ: set dominators for this block, to allow loop optimizations requiring them 
6326     //        (e.g: hoisting expression in a loop with the same 'head' as this one)
6327
6328     /* Update the loop entry */
6329
6330     pLoopDsc->lpHead   = preHead;
6331     pLoopDsc->lpFlags |= LPFLG_HAS_PREHEAD;
6332
6333     /* The new block becomes the 'head' of the loop - update bbRefs and bbPreds
6334        All predecessors of 'beg', (which is the entry in the loop)
6335        now have to jump to 'preHead', unless they are dominated by 'head' */
6336
6337     preHead->bbRefs = 0;
6338     fgAddRefPred(preHead, head);
6339     bool checkNestedLoops = false;
6340
6341     for (flowList * pred = top->bbPreds; pred; pred = pred->flNext)
6342     {
6343         BasicBlock  *   predBlock = pred->flBlock;
6344
6345         if (fgDominate(top, predBlock))
6346         {
6347             // note: if 'top' dominates predBlock, 'head' dominates predBlock too
6348             // (we know that 'head' dominates 'top'), but using 'top' instead of
6349             // 'head' in the test allows us to not enter here if 'predBlock == head'
6350
6351             if (predBlock != pLoopDsc->lpBottom)
6352             {
6353                 noway_assert(predBlock != head);
6354                 checkNestedLoops = true;
6355             }
6356             continue;
6357         }
6358
6359         switch (predBlock->bbJumpKind)
6360         {
6361         case BBJ_NONE:
6362             noway_assert(predBlock == head);
6363             break;
6364
6365         case BBJ_COND:
6366             if  (predBlock == head)
6367             {
6368                 noway_assert(predBlock->bbJumpDest != top);
6369                 break;
6370             }
6371             __fallthrough;
6372
6373         case BBJ_ALWAYS:
6374         case BBJ_EHCATCHRET:
6375             noway_assert(predBlock->bbJumpDest == top);
6376             predBlock->bbJumpDest = preHead;
6377             preHead->bbFlags |= BBF_JMP_TARGET|BBF_HAS_LABEL;
6378             
6379             if (predBlock == head)
6380             {
6381                 // This is essentially the same case of predBlock being a BBJ_NONE. We may not be
6382                 // able to make this a BBJ_NONE if it's an internal block (for example, a leave).
6383                 // Just break, pred will be removed after switch.
6384             }
6385             else
6386             {                
6387                 fgRemoveRefPred(top, predBlock);
6388                 fgAddRefPred(preHead, predBlock);
6389             }   
6390             break;
6391
6392         case BBJ_SWITCH:
6393             unsigned        jumpCnt; jumpCnt = predBlock->bbJumpSwt->bbsCount;
6394             BasicBlock * *  jumpTab; jumpTab = predBlock->bbJumpSwt->bbsDstTab;
6395
6396             do
6397             {
6398                 assert (*jumpTab);
6399                 if ((*jumpTab) == top)
6400                 {
6401                     (*jumpTab) = preHead;
6402
6403                     fgRemoveRefPred(top, predBlock);
6404                     fgAddRefPred(preHead, predBlock);
6405                     preHead->bbFlags |= BBF_JMP_TARGET|BBF_HAS_LABEL;
6406                 }
6407             }
6408             while (++jumpTab, --jumpCnt);
6409
6410         default:
6411             noway_assert(!"Unexpected bbJumpKind");
6412             break;
6413         }
6414     }
6415
6416     noway_assert(!fgGetPredForBlock(top, preHead));
6417     fgRemoveRefPred(top, head);
6418     fgAddRefPred(top, preHead);
6419
6420     /* 
6421         If we found at least one back-edge in the flowgraph pointing to the top/entry of the loop
6422         (other than the back-edge of the loop we are considering) then we likely have nested
6423         do-while loops with the same entry block and inserting the preheader block changes the head
6424         of all the nested loops. Now we will update this piece of information in the loop table, and
6425         mark all nested loops as having a preheader (the preheader block can be shared among all nested
6426         do-while loops with the same entry block).
6427     */
6428     if (checkNestedLoops)
6429     {
6430         for (unsigned l = 0; l < optLoopCount; l++)
6431         {
6432             if (optLoopTable[l].lpHead == head)
6433             {
6434                 noway_assert(l != lnum);  // pLoopDsc->lpHead was already changed from 'head' to 'preHead'
6435                 noway_assert(optLoopTable[l].lpEntry == top);
6436                 optUpdateLoopHead(l, optLoopTable[l].lpHead, preHead);
6437                 optLoopTable[l].lpFlags |= LPFLG_HAS_PREHEAD;
6438 #ifdef  DEBUG
6439                 if  (verbose)
6440                     printf("Same PreHeader (BB%02u) can be used for loop L%02u (BB%02u - BB%02u)\n\n",
6441                            preHead->bbNum, l, top->bbNum, optLoopTable[l].lpBottom->bbNum);
6442 #endif
6443             }
6444         }
6445     }
6446 }
6447
6448 bool                Compiler::optBlockIsLoopEntry(BasicBlock* blk, unsigned* pLnum)
6449 {
6450     unsigned lnum = blk->bbNatLoopNum;
6451     while (lnum != BasicBlock::NOT_IN_LOOP)
6452     {
6453         if (optLoopTable[lnum].lpEntry == blk)
6454         {
6455             *pLnum = lnum;
6456             return true;
6457         }
6458         lnum = optLoopTable[lnum].lpParent;
6459     }
6460     return false;
6461 }
6462
6463 void                Compiler::optComputeLoopSideEffects()
6464 {
6465     unsigned  lnum;
6466     for (lnum = 0; lnum < optLoopCount; lnum++)
6467     {
6468         VarSetOps::AssignNoCopy(this, optLoopTable[lnum].lpVarInOut,  VarSetOps::MakeEmpty(this));
6469         VarSetOps::AssignNoCopy(this, optLoopTable[lnum].lpVarUseDef, VarSetOps::MakeEmpty(this));
6470         optLoopTable[lnum].lpContainsCall = false;
6471     }
6472
6473     for (lnum = 0; lnum < optLoopCount; lnum++)
6474     {
6475         if (optLoopTable[lnum].lpFlags & LPFLG_REMOVED)
6476             continue;
6477
6478         if (optLoopTable[lnum].lpParent == BasicBlock::NOT_IN_LOOP) // Is outermost...
6479             optComputeLoopNestSideEffects(lnum);
6480     }
6481
6482     VarSetOps::AssignNoCopy(this, lvaFloatVars,  VarSetOps::MakeEmpty(this));
6483 #ifndef _TARGET_64BIT_
6484     VarSetOps::AssignNoCopy(this, lvaLongVars,  VarSetOps::MakeEmpty(this));
6485 #endif
6486
6487     for (unsigned i = 0; i < lvaCount; i++)
6488     {
6489         LclVarDsc* varDsc = &lvaTable[i];
6490         if (varDsc->lvTracked)
6491         {
6492             if (varTypeIsFloating(varDsc->lvType))
6493             {
6494                 VarSetOps::AddElemD(this, lvaFloatVars, varDsc->lvVarIndex);
6495             }
6496 #ifndef _TARGET_64BIT_
6497             else if (varTypeIsLong(varDsc->lvType))
6498             {
6499                 VarSetOps::AddElemD(this, lvaLongVars, varDsc->lvVarIndex);
6500             }
6501 #endif
6502         }
6503     }
6504 }
6505
6506 void                Compiler::optComputeLoopNestSideEffects(unsigned lnum)
6507 {
6508     assert(optLoopTable[lnum].lpParent == BasicBlock::NOT_IN_LOOP);  // Requires: lnum is outermost.
6509     BasicBlock* botNext = optLoopTable[lnum].lpBottom->bbNext;
6510     for (BasicBlock* bbInLoop = optLoopTable[lnum].lpFirst; bbInLoop != botNext; bbInLoop = bbInLoop->bbNext)
6511     {
6512         optComputeLoopSideEffectsOfBlock(bbInLoop);
6513     }
6514 }
6515
6516 void                Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk)
6517 {
6518     unsigned mostNestedLoop = blk->bbNatLoopNum;
6519     assert(mostNestedLoop != BasicBlock::NOT_IN_LOOP);
6520    
6521     AddVariableLivenessAllContainingLoops(mostNestedLoop, blk);
6522
6523     bool heapHavoc = false;  // True ==> there's a call or a memory store that has arbitrary heap effects.
6524
6525     // Now iterate over the remaining statements, and their trees.
6526     for (GenTreePtr stmts = blk->FirstNonPhiDef(); (stmts != nullptr); stmts = stmts->gtNext)
6527     {
6528         for (GenTreePtr tree = stmts->gtStmt.gtStmtList; (tree != nullptr); tree = tree->gtNext)
6529         {
6530             genTreeOps oper = tree->OperGet();
6531
6532             // Even after we set heapHavoc we still may want to know if a loop contains calls
6533             if (heapHavoc)
6534             {
6535                 if (oper == GT_CALL)
6536                 {
6537                     // Record that this loop contains a call
6538                     AddContainsCallAllContainingLoops(mostNestedLoop);
6539                 }
6540
6541                 // If we just set lpContainsCall or it was previously set 
6542                 if  (optLoopTable[mostNestedLoop].lpContainsCall)
6543                 {
6544                     // We can early exit after both heapHavoc and lpContainsCall are both set to true.
6545                     break;
6546                 }
6547
6548                 // We are just looking for GT_CALL nodes after heapHavoc was set.
6549                 continue;
6550             }
6551
6552             // otherwise heapHavoc is not set
6553             assert(!heapHavoc);
6554
6555             // This body is a distillation of the heap-side effect code of value numbering.
6556             // We also do a very limited analysis if byref PtrTo values, to cover some cases
6557             // that the compiler creates.
6558
6559             if (GenTree::OperIsAssignment(oper))
6560             {
6561                 GenTreePtr lhs = tree->gtOp.gtOp1->gtEffectiveVal(/*commaOnly*/true);
6562
6563                 if (lhs->OperGet() == GT_IND)
6564                 {
6565                     GenTreePtr arg = lhs->gtOp.gtOp1->gtEffectiveVal(/*commaOnly*/true);
6566                     FieldSeqNode* fldSeqArrElem = nullptr;
6567
6568                     if ((tree->gtFlags & GTF_IND_VOLATILE) != 0)
6569                     {
6570                         heapHavoc = true;
6571                         continue;
6572                     }
6573
6574                     ArrayInfo arrInfo;
6575
6576                     if (arg->TypeGet() == TYP_BYREF && arg->OperGet() == GT_LCL_VAR)
6577                     {
6578                         // If it's a local byref for which we recorded a value number, use that...
6579                         GenTreeLclVar* argLcl = arg->AsLclVar();
6580                         if (!fgExcludeFromSsa(argLcl->GetLclNum()))
6581                         {
6582                             ValueNum argVN = lvaTable[argLcl->GetLclNum()].GetPerSsaData(argLcl->GetSsaNum())->m_vnPair.GetLiberal();
6583                             VNFuncApp funcApp;
6584                             if (argVN != ValueNumStore::NoVN && vnStore->GetVNFunc(argVN, &funcApp) && funcApp.m_func == VNF_PtrToArrElem)
6585                             {
6586                                 assert(vnStore->IsVNHandle(funcApp.m_args[0]));
6587                                 CORINFO_CLASS_HANDLE elemType = CORINFO_CLASS_HANDLE(vnStore->ConstantValue<size_t>(funcApp.m_args[0]));
6588                                 AddModifiedElemTypeAllContainingLoops(mostNestedLoop, elemType);
6589                                 // Don't set heapHavoc below.
6590                                 continue;
6591                             }
6592                         }
6593                         // Otherwise...
6594                         heapHavoc = true;
6595                     }
6596                     // Is the LHS an array index expression?
6597                     else if (lhs->ParseArrayElemForm(this, &arrInfo, &fldSeqArrElem))
6598                     {
6599                         // We actually ignore "fldSeq" -- any modification to an S[], at any
6600                         // field of "S", will lose all information about the array type.
6601                         CORINFO_CLASS_HANDLE elemTypeEq = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType);
6602                         AddModifiedElemTypeAllContainingLoops(mostNestedLoop, elemTypeEq);
6603                     }
6604                     else 
6605                     {                        
6606                         // We are only interested in IsFieldAddr()'s fldSeq out parameter.
6607                         //
6608                         GenTreePtr obj          = nullptr;  // unused
6609                         GenTreePtr staticOffset = nullptr;  // unused
6610                         FieldSeqNode* fldSeq    = nullptr;
6611
6612                         if (arg->IsFieldAddr(this, &obj, &staticOffset, &fldSeq) &&
6613                             (fldSeq != FieldSeqStore::NotAField()))
6614                         {
6615                             // Get the first (object) field from field seq.  Heap[field] will yield the "field map".
6616                             assert(fldSeq != nullptr);
6617                             if (fldSeq->IsFirstElemFieldSeq())
6618                             {
6619                                 fldSeq = fldSeq->m_next;
6620                                 assert(fldSeq != nullptr);
6621                             }
6622
6623                             AddModifiedFieldAllContainingLoops(mostNestedLoop, fldSeq->m_fieldHnd);
6624                         }
6625                         else
6626                         {
6627                             heapHavoc = true;
6628                         }
6629                     }
6630                 } 
6631                 else if (lhs->OperGet() == GT_CLS_VAR)
6632                 {
6633                     AddModifiedFieldAllContainingLoops(mostNestedLoop, lhs->gtClsVar.gtClsVarHnd);
6634                 }
6635                 // Otherwise, must be local lhs form.  I should assert that.
6636                 else if (lhs->OperGet() == GT_LCL_VAR)
6637                 {
6638                     GenTreeLclVar* lhsLcl = lhs->AsLclVar();
6639                     GenTreePtr rhs = tree->gtOp.gtOp2;
6640                     ValueNum rhsVN = rhs->gtVNPair.GetLiberal();
6641                     // If we gave the RHS a value number, propagate it.
6642                     if (rhsVN != ValueNumStore::NoVN)
6643                     {
6644                         rhsVN = vnStore->VNNormVal(rhsVN);
6645                         if (!fgExcludeFromSsa(lhsLcl->GetLclNum()))
6646                         {
6647                             lvaTable[lhsLcl->GetLclNum()].GetPerSsaData(lhsLcl->GetSsaNum())->m_vnPair.SetLiberal(rhsVN);
6648                         }
6649                     }
6650                 }
6651             }
6652             else  // not GenTree::OperIsAssignment(oper)
6653             {
6654                 switch (oper)
6655                 {
6656                 case GT_COMMA:
6657                     tree->gtVNPair = tree->gtOp.gtOp2->gtVNPair;
6658                     break;
6659
6660                 case GT_ADDR:
6661                     // Is it an addr of a array index expression?
6662                     {
6663                         GenTreePtr addrArg = tree->gtOp.gtOp1;
6664                         if (addrArg->OperGet() == GT_IND)
6665                         {
6666                             // Is the LHS an array index expression?
6667                             if (addrArg->gtFlags & GTF_IND_ARR_INDEX)
6668                             {
6669                                 ArrayInfo arrInfo;
6670                                 bool b = GetArrayInfoMap()->Lookup(addrArg, &arrInfo);
6671                                 assert(b);
6672                                 CORINFO_CLASS_HANDLE elemType = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType);
6673                                 tree->gtVNPair.SetBoth(vnStore->VNForFunc(TYP_BYREF, VNF_PtrToArrElem,
6674                                                                           vnStore->VNForHandle(ssize_t(elemType), GTF_ICON_CLASS_HDL),  
6675                                                                           // The rest are dummy arguments.
6676                                                                           vnStore->VNForNull(),
6677                                                                           vnStore->VNForNull(),
6678                                                                           vnStore->VNForNull()));
6679                             }
6680                         }
6681                     }
6682                     break;
6683
6684                 case GT_INITBLK:
6685                 case GT_COPYBLK:
6686                 case GT_COPYOBJ:
6687                     {
6688                         GenTreeLclVarCommon* lclVarTree;
6689                         bool                 isEntire;
6690                         if (!tree->DefinesLocal(this, &lclVarTree, &isEntire))
6691                         {
6692                             // For now, assume arbitrary side effects on the heap...
6693                             // TODO-CQ: Why not be complete, and get this case right?
6694                             heapHavoc = true;
6695                         }
6696                     }
6697                     break;
6698
6699                 case GT_LOCKADD:        // Binop
6700                 case GT_XADD:           // Binop
6701                 case GT_XCHG:           // Binop
6702                 case GT_CMPXCHG:        // Specialop
6703                     {
6704                         heapHavoc = true;
6705                     }
6706                     break;
6707
6708                 case GT_CALL:
6709                     {
6710                         GenTreeCall* call = tree->AsCall();
6711
6712                         // Record that this loop contains a call
6713                         AddContainsCallAllContainingLoops(mostNestedLoop);
6714
6715                         if (call->gtCallType == CT_HELPER)
6716                         {
6717                             CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd);
6718                             if (s_helperCallProperties.MutatesHeap(helpFunc))
6719                             {
6720                                 heapHavoc = true;
6721                             }
6722                             else if (s_helperCallProperties.MayRunCctor(helpFunc))
6723                             {
6724                                 // If the call is labeled as "Hoistable", then we've checked the
6725                                 // class that would be constructed, and it is not precise-init, so
6726                                 // the cctor will not be run by this call.  Otherwise, it might be,
6727                                 // and might have arbitrary side effects.
6728                                 if ((tree->gtFlags & GTF_CALL_HOISTABLE) == 0)
6729                                 {
6730                                     heapHavoc = true;
6731                                 }
6732                             }
6733                         }
6734                         else
6735                         {
6736                             heapHavoc = true;
6737                         }
6738                         break;
6739                     }
6740
6741                 default:
6742                     // All other gtOper node kinds, leave 'heapHavoc' unchanged (i.e. false)
6743                     break;
6744                 }
6745             }
6746         }
6747     }
6748
6749     if (heapHavoc)
6750     {
6751         // Record that all loops containing this block have heap havoc effects.
6752         unsigned lnum = mostNestedLoop;
6753         while (lnum != BasicBlock::NOT_IN_LOOP)
6754         {
6755             optLoopTable[lnum].lpLoopHasHeapHavoc = true;
6756             lnum = optLoopTable[lnum].lpParent;
6757         }
6758     }
6759 }
6760
6761 // Marks the containsCall information to "lnum" and any parent loops.
6762 void                Compiler::AddContainsCallAllContainingLoops(unsigned lnum)
6763 {
6764     assert(0 <= lnum && lnum < optLoopCount);
6765     while (lnum != BasicBlock::NOT_IN_LOOP)
6766     {
6767         optLoopTable[lnum].lpContainsCall = true;
6768         lnum = optLoopTable[lnum].lpParent;
6769     }
6770 }
6771
6772 // Adds the variable liveness information for 'blk' to 'this' LoopDsc
6773 void                Compiler::LoopDsc::AddVariableLiveness(Compiler* comp, BasicBlock * blk)
6774 {
6775     VarSetOps::UnionD(comp, this->lpVarInOut,  blk->bbLiveIn);
6776     VarSetOps::UnionD(comp, this->lpVarInOut,  blk->bbLiveOut);
6777
6778     VarSetOps::UnionD(comp, this->lpVarUseDef, blk->bbVarUse);
6779     VarSetOps::UnionD(comp, this->lpVarUseDef, blk->bbVarDef);
6780 }
6781
6782 // Adds the variable liveness information for 'blk' to "lnum" and any parent loops.
6783 void                Compiler::AddVariableLivenessAllContainingLoops(unsigned lnum, BasicBlock * blk)
6784 {
6785     assert(0 <= lnum && lnum < optLoopCount);
6786     while (lnum != BasicBlock::NOT_IN_LOOP)
6787     {
6788         optLoopTable[lnum].AddVariableLiveness(this, blk);
6789         lnum = optLoopTable[lnum].lpParent;
6790     }
6791 }
6792
6793 // Adds "fldHnd" to the set of modified fields of "lnum" and any parent loops.
6794 void                Compiler::AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd)
6795 {
6796     assert(0 <= lnum && lnum < optLoopCount);
6797     while (lnum != BasicBlock::NOT_IN_LOOP)
6798     {
6799         optLoopTable[lnum].AddModifiedField(this, fldHnd);
6800         lnum = optLoopTable[lnum].lpParent;
6801     }
6802 }
6803
6804 // Adds "elemType" to the set of modified array element types of "lnum" and any parent loops.
6805 void                Compiler::AddModifiedElemTypeAllContainingLoops(unsigned lnum, CORINFO_CLASS_HANDLE elemClsHnd)
6806 {
6807     assert(0 <= lnum && lnum < optLoopCount);
6808     while (lnum != BasicBlock::NOT_IN_LOOP)
6809     {
6810         optLoopTable[lnum].AddModifiedElemType(this, elemClsHnd);
6811         lnum = optLoopTable[lnum].lpParent;
6812     }
6813 }
6814
6815 /*****************************************************************************
6816  *
6817  *  Helper passed to Compiler::fgWalkAllTreesPre() to decrement the LclVar usage counts
6818  *  The 'keepList'is either a single tree or a list of trees that are formed by
6819  *  one or more GT_COMMA nodes.  It is the kept side-effects as returned by the
6820  *  gtExtractSideEffList method.
6821  */
6822
6823 /* static */
6824 Compiler::fgWalkResult      Compiler::optRemoveTreeVisitor(GenTreePtr *pTree, fgWalkData *data)
6825 {
6826     GenTreePtr  tree = *pTree;
6827     Compiler *  comp = data->compiler;
6828     GenTreePtr  keepList = (GenTreePtr)(data->pCallbackData);
6829
6830     // We may have a non-NULL side effect list that is being kept
6831     //
6832     if (keepList)
6833     {
6834         GenTreePtr keptTree = keepList;
6835         while (keptTree->OperGet() == GT_COMMA)
6836         {
6837             assert(keptTree->OperKind() & GTK_SMPOP);
6838             GenTreePtr op1 = keptTree->gtOp.gtOp1; 
6839             GenTreePtr op2 = keptTree->gtGetOp2();
6840
6841             // For the GT_COMMA case the op1 is part of the orginal CSE tree 
6842             // that is being kept because it contains some side-effect
6843             //
6844             if (tree == op1)
6845             {
6846                 // This tree and all of its sub trees are being kept.
6847                 return WALK_SKIP_SUBTREES;
6848             }
6849
6850             // For the GT_COMMA case the op2 are the remaining side-effects of the orginal CSE tree
6851             // which can again be another GT_COMMA or the final side-effect part
6852             //
6853             keptTree = op2;
6854         }
6855         if (tree == keptTree)
6856         {
6857             // This tree and all of its sub trees are being kept.
6858             return WALK_SKIP_SUBTREES;
6859         }
6860     }
6861
6862     // This node is being removed from the graph of GenTreePtr
6863
6864     // Look for any local variable references
6865
6866     if  (tree->gtOper == GT_LCL_VAR && comp->lvaLocalVarRefCounted)
6867     {
6868         unsigned        lclNum;
6869         LclVarDsc   *   varDsc;
6870
6871         /* This variable ref is going away, decrease its ref counts */
6872
6873         lclNum = tree->gtLclVarCommon.gtLclNum;
6874         assert(lclNum < comp->lvaCount);
6875         varDsc = comp->lvaTable + lclNum;
6876
6877         // make sure it's been initialized
6878         assert(comp->compCurBB != nullptr);
6879         assert(comp->compCurBB->bbWeight <= BB_MAX_WEIGHT); 
6880
6881         /* Decrement its lvRefCnt and lvRefCntWtd */
6882
6883         // Use getBBWeight to determine the proper block weight.
6884         // This impacts the block weights when we have IBC data.
6885         varDsc->decRefCnts(comp->compCurBB->getBBWeight(comp), comp);
6886     }
6887
6888     return  WALK_CONTINUE;
6889 }
6890
6891 /*****************************************************************************
6892  *
6893  *  Routine called to decrement the LclVar ref counts when removing a tree
6894  *  during the remove RangeCheck phase.
6895  *  This method will decrement the refcounts for any LclVars used below 'deadTree', 
6896  *  unless the node is found in the 'keepList' (which are saved side effects)
6897  *  The keepList is communicated using the walkData.pCallbackData field
6898  *  Also the compCurBB must be set to the current BasicBlock  which contains
6899  *  'deadTree' as we need to fetch the block weight when decrementing the ref counts.
6900  */
6901
6902 void Compiler::optRemoveTree(GenTreePtr deadTree, GenTreePtr keepList)
6903 {
6904     // We communicate this value using the walkData.pCallbackData field
6905     //
6906     fgWalkTreePre(&deadTree, optRemoveTreeVisitor, (void*)keepList);
6907 }
6908
6909 /*****************************************************************************
6910  *
6911  *  Given an array index node, mark it as not needing a range check.
6912  */
6913
6914 void                Compiler::optRemoveRangeCheck(GenTreePtr tree,
6915                                                   GenTreePtr stmt,
6916                                                   bool       updateCSEcounts,
6917                                                   unsigned   sideEffFlags,
6918                                                   bool       forceRemove)
6919 {
6920     GenTreePtr      add1;
6921     GenTreePtr  *   addp;
6922
6923     GenTreePtr      nop1;
6924     GenTreePtr  *   nopp;
6925
6926     GenTreePtr      icon;
6927     GenTreePtr      mult;
6928
6929     GenTreePtr      base;
6930
6931     ssize_t         ival;
6932
6933 #if !REARRANGE_ADDS
6934     noway_assert(!"can't remove range checks without REARRANGE_ADDS right now");
6935 #endif
6936
6937     noway_assert(stmt->gtOper     == GT_STMT);
6938     noway_assert(tree->gtOper     == GT_COMMA);
6939     noway_assert(tree->gtOp.gtOp1->gtOper == GT_ARR_BOUNDS_CHECK);
6940     noway_assert(forceRemove || optIsRangeCheckRemovable(tree->gtOp.gtOp1));
6941
6942     GenTreeBoundsChk* bndsChk = tree->gtOp.gtOp1->AsBoundsChk();
6943     
6944 #ifdef DEBUG
6945     if (verbose)
6946     {
6947         printf("Before optRemoveRangeCheck:\n");
6948         gtDispTree(tree);
6949     }
6950 #endif
6951
6952     GenTreePtr sideEffList = nullptr;
6953     if (sideEffFlags)
6954     {
6955         gtExtractSideEffList(tree->gtOp.gtOp1, &sideEffList, sideEffFlags);
6956     }
6957
6958     // Decrement the ref counts for any LclVars that are being deleted
6959     //                    
6960     optRemoveTree(tree->gtOp.gtOp1, sideEffList);
6961
6962     // Just replace the bndsChk with a NOP as an operand to the GT_COMMA, if there are no side effects.
6963     tree->gtOp.gtOp1 = (sideEffList != NULL) ? sideEffList : gtNewNothingNode();
6964
6965     // TODO-CQ: We should also remove the GT_COMMA, but in any case we can no longer CSE the GT_COMMA.
6966     tree->gtFlags |= GTF_DONT_CSE;
6967
6968     /* Recalculate the gtCostSz, etc... */
6969     gtSetStmtInfo(stmt);
6970
6971     /* Re-thread the nodes if necessary */
6972     if (fgStmtListThreaded)
6973     {
6974         fgSetStmtSeq(stmt);
6975     }
6976
6977 #ifdef DEBUG
6978     if (verbose)
6979     {
6980         printf("After optRemoveRangeCheck:\n");
6981         gtDispTree(tree);
6982     }
6983 #endif
6984
6985 }
6986
6987 /*****************************************************************************
6988  * Return the scale in an array reference, given a pointer to the
6989  * multiplication node.
6990  */
6991
6992 ssize_t                   Compiler::optGetArrayRefScaleAndIndex(GenTreePtr mul, GenTreePtr *pIndex DEBUGARG(bool bRngChk))
6993 {
6994     assert (mul);
6995     assert (mul->gtOper == GT_MUL || mul->gtOper == GT_LSH);
6996     assert (mul->gtOp.gtOp2->IsCnsIntOrI());
6997
6998     ssize_t scale = mul->gtOp.gtOp2->gtIntConCommon.IconValue();
6999
7000     if  (mul->gtOper == GT_LSH)
7001         scale = ((ssize_t)1) << scale;
7002
7003     GenTreePtr index = mul->gtOp.gtOp1;
7004
7005     if (index->gtOper == GT_MUL && index->gtOp.gtOp2->IsCnsIntOrI())
7006     {
7007         // case of two cascading multiplications for constant int (e.g.  * 20 morphed to * 5 * 4):
7008         // When index->gtOper is GT_MUL and index->gtOp.gtOp2->gtOper is GT_CNS_INT (i.e. * 5),
7009         //     we can bump up the scale from 4 to 5*4, and then change index to index->gtOp.gtOp1.
7010         // Otherwise, we cannot optimize it. We will simply keep the original scale and index.
7011         scale *= index->gtOp.gtOp2->gtIntConCommon.IconValue();
7012         index = index->gtOp.gtOp1;
7013     }
7014
7015     assert (!bRngChk || index->gtOper != GT_COMMA);
7016
7017     if (pIndex)
7018         *pIndex = index;
7019
7020     return scale;
7021 }
7022
7023 /*****************************************************************************
7024  * Find the last assignment to of the local variable in the block. Return
7025  * RHS or NULL. If any local variable in the RHS has been killed in
7026  * intervening code, return NULL. If the variable being searched for is killed
7027  * in the intervening code, return NULL.
7028  *
7029  */
7030
7031 GenTreePtr Compiler::optFindLocalInit(BasicBlock *block, GenTreePtr local, VARSET_TP* pKilledInOut, bool* pLhsRhsKilledAfterInit)
7032 {
7033     assert(pKilledInOut);
7034     assert(pLhsRhsKilledAfterInit);
7035
7036     *pLhsRhsKilledAfterInit = false;
7037
7038     unsigned LclNum = local->gtLclVarCommon.gtLclNum;
7039
7040     GenTreePtr list = block->bbTreeList;
7041     if  (list == NULL)
7042     {
7043         return NULL;
7044     }
7045
7046     GenTreePtr rhs = NULL;
7047     GenTreePtr stmt = list;
7048     do
7049     {
7050         stmt = stmt->gtPrev;
7051         if  (stmt == NULL)
7052         {
7053             break;
7054         }
7055
7056         GenTreePtr tree = stmt->gtStmt.gtStmtExpr;
7057         // If we encounter an assignment to a local variable,
7058         if ((tree->OperKind() & GTK_ASGOP) && tree->gtOp.gtOp1->gtOper == GT_LCL_VAR)
7059         {
7060             // And the assigned variable equals the input local,
7061             if (tree->gtOp.gtOp1->gtLclVarCommon.gtLclNum == LclNum)
7062             {
7063                 // If the assignment is '=' and it is not a conditional, then return rhs.
7064                 if (tree->gtOper == GT_ASG && !(tree->gtFlags & GTF_COLON_COND))
7065                 {
7066                     rhs = tree->gtOp.gtOp2;
7067                 }
7068                 // If the assignment is 'op=' or a conditional equal, then the search ends here,
7069                 // as we found a kill to the input local.
7070                 else
7071                 {
7072                     *pLhsRhsKilledAfterInit = true;
7073                     assert(rhs == NULL);
7074                 }
7075                 break;
7076             }
7077             else
7078             {
7079                 LclVarDsc* varDsc = optIsTrackedLocal(tree->gtOp.gtOp1);
7080                 if (varDsc == NULL)
7081                 {
7082                     return NULL;
7083                 }
7084                 VarSetOps::AddElemD(this, *pKilledInOut, varDsc->lvVarIndex);
7085             }
7086         }
7087     }
7088     while (stmt != list);
7089
7090     if (rhs == NULL)
7091     {
7092         return NULL;
7093     }
7094
7095     // If any local in the RHS is killed in intervening code, or RHS has an indirection, return NULL.
7096     varRefKinds rhsRefs = VR_NONE;
7097     VARSET_TP VARSET_INIT_NOCOPY(rhsLocals, VarSetOps::UninitVal());
7098     bool b = lvaLclVarRefs(rhs, NULL, &rhsRefs, &rhsLocals);
7099     if (!b ||
7100         !VarSetOps::IsEmptyIntersection(this, rhsLocals, *pKilledInOut) ||
7101         (rhsRefs != VR_NONE))
7102     {
7103         // If RHS has been indirectly referenced, consider it a write and a kill.
7104         *pLhsRhsKilledAfterInit = true;
7105         return NULL;
7106     }
7107
7108     return rhs;
7109 }
7110
7111 /*****************************************************************************
7112  *
7113  *  Return true if "op1" is guaranteed to be less then or equal to "op2".
7114  */
7115
7116 #if FANCY_ARRAY_OPT
7117
7118 bool                Compiler::optIsNoMore(GenTreePtr op1, GenTreePtr op2,
7119                                           int add1, int add2)
7120 {
7121     if  (op1->gtOper == GT_CNS_INT &&
7122          op2->gtOper == GT_CNS_INT)
7123     {
7124         add1 += op1->gtIntCon.gtIconVal;
7125         add2 += op2->gtIntCon.gtIconVal;
7126     }
7127     else
7128     {
7129         /* Check for +/- constant on either operand */
7130
7131         if  (op1->gtOper == GT_ADD && op1->gtOp.gtOp2->gtOper == GT_CNS_INT)
7132         {
7133             add1 += op1->gtOp.gtOp2->gtIntCon.gtIconVal;
7134             op1   = op1->gtOp.gtOp1;
7135         }
7136
7137         if  (op2->gtOper == GT_ADD && op2->gtOp.gtOp2->gtOper == GT_CNS_INT)
7138         {
7139             add2 += op2->gtOp.gtOp2->gtIntCon.gtIconVal;
7140             op2   = op2->gtOp.gtOp1;
7141         }
7142
7143         /* We only allow local variable references */
7144
7145         if  (op1->gtOper != GT_LCL_VAR)
7146             return false;
7147         if  (op2->gtOper != GT_LCL_VAR)
7148             return false;
7149         if  (op1->gtLclVarCommon.gtLclNum != op2->gtLclVarCommon.gtLclNum)
7150             return false;
7151
7152         /* NOTE: Caller ensures that this variable has only one def */
7153
7154         // printf("limit [%d]:\n", add1); gtDispTree(op1);
7155         // printf("size  [%d]:\n", add2); gtDispTree(op2);
7156         // printf("\n");
7157
7158     }
7159
7160     return  (bool)(add1 <= add2);
7161 }
7162
7163 #endif
7164
7165 //------------------------------------------------------------------------------
7166 // optObtainLoopCloningOpts: Identify optimization candidates and update
7167 //      the "context" for array optimizations.
7168 //
7169 // Arguments:
7170 //     context     -  data structure where all loop cloning info is kept. The
7171 //                    optInfo fields of the context are updated with the
7172 //                    identified optimization candidates.
7173 //                      
7174 void Compiler::optObtainLoopCloningOpts(LoopCloneContext* context)
7175 {
7176     for (unsigned i = 0; i < optLoopCount; i++)
7177     {
7178         JITDUMP("Considering loop %d to clone for optimizations.\n", i);
7179         if (optIsLoopClonable(i))
7180         {
7181             if (!(optLoopTable[i].lpFlags & LPFLG_REMOVED))
7182             {
7183                 optIdentifyLoopOptInfo(i, context);
7184             }
7185         }
7186         JITDUMP("------------------------------------------------------------\n");
7187     }
7188     JITDUMP("\n");
7189 }
7190
7191 //------------------------------------------------------------------------
7192 // optIdentifyLoopOptInfo: Identify loop optimization candidates an also
7193 //      check if the loop is suitable for the optimizations performed.
7194 //
7195 // Arguments:
7196 //     loopNum     -  the current loop index for which conditions are derived.
7197 //     context     -  data structure where all loop cloning candidates will be
7198 //                    updated.
7199 //
7200 // Return Value:
7201 //     If the loop is not suitable for the optimizations, return false - context
7202 //     should not contain any optimization candidate for the loop if false.
7203 //     Else return true.
7204 //
7205 // Operation:
7206 //      Check if the loop is well formed for this optimization and identify the
7207 //      optimization candidates and update the "context" parameter with all the
7208 //      contextual information necessary to perform the optimization later.
7209 //
7210 bool               Compiler::optIdentifyLoopOptInfo(unsigned loopNum, LoopCloneContext* context)
7211 {
7212     noway_assert(loopNum < optLoopCount);
7213
7214     LoopDsc* pLoop = &optLoopTable[loopNum];
7215
7216     if (!(pLoop->lpFlags & LPFLG_ITER))
7217     {
7218         JITDUMP("> No iter flag on loop %d.\n", loopNum);
7219         return false;
7220     }
7221
7222     unsigned ivLclNum = pLoop->lpIterVar();
7223     if (lvaVarAddrExposed(ivLclNum))
7224     {
7225         JITDUMP("> Rejected V%02u as iter var because is address-exposed.\n", ivLclNum);
7226         return false;
7227     }
7228
7229     BasicBlock* head = pLoop->lpHead;
7230     BasicBlock* end = pLoop->lpBottom;
7231     BasicBlock* beg = head->bbNext;
7232
7233     if (end->bbJumpKind != BBJ_COND)
7234     {
7235         JITDUMP("> Couldn't find termination test.\n");
7236         return false;
7237     }
7238
7239     if  (end->bbJumpDest != beg)
7240     {
7241         JITDUMP("> Branch at loop 'end' not looping to 'begin'.\n");
7242         return false;
7243     }
7244
7245     // TODO-CQ: CLONE: Mark increasing or decreasing loops.
7246     if ((pLoop->lpIterOper() != GT_ASG_ADD && pLoop->lpIterOper() != GT_ADD) || (pLoop->lpIterConst() != 1))
7247     {
7248         JITDUMP("> Loop iteration operator not matching\n");
7249         return false;
7250     }
7251
7252     if ((pLoop->lpFlags & LPFLG_CONST_LIMIT) == 0 &&
7253         (pLoop->lpFlags & LPFLG_VAR_LIMIT) == 0 &&
7254         (pLoop->lpFlags & LPFLG_ARRLEN_LIMIT) == 0)
7255     {
7256         JITDUMP("> Loop limit is neither constant, variable or array length\n");
7257         return false;
7258     }
7259
7260     if (!(((pLoop->lpTestOper() == GT_LT || pLoop->lpTestOper() == GT_LE) && (pLoop->lpIterOper() == GT_ADD || pLoop->lpIterOper() == GT_ASG_ADD)) ||
7261         ((pLoop->lpTestOper() == GT_GT || pLoop->lpTestOper() == GT_GE) && (pLoop->lpIterOper() == GT_SUB || pLoop->lpIterOper() == GT_ASG_SUB))))
7262     {
7263         JITDUMP("> Loop test (%s) doesn't agree with the direction (%s) of the pLoop->\n",
7264                 GenTree::NodeName(pLoop->lpTestOper()), GenTree::NodeName(pLoop->lpIterOper()));
7265         return false;
7266     }
7267
7268     if (!(pLoop->lpTestTree->OperKind() & GTK_RELOP) || !(pLoop->lpTestTree->gtFlags & GTF_RELOP_ZTT))
7269     {
7270         JITDUMP("> Loop inversion NOT present, loop test [%06u] may not protect entry from head.\n", pLoop->lpTestTree->gtTreeID);
7271         return false;
7272     }
7273
7274 #ifdef DEBUG
7275     GenTreePtr op1 = pLoop->lpIterator();
7276     noway_assert((op1->gtOper == GT_LCL_VAR) && (op1->gtLclVarCommon.gtLclNum == ivLclNum));
7277 #endif
7278
7279     JITDUMP("Checking blocks BB%02d..BB%02d for optimization candidates\n", beg->bbNum, end->bbNext ? end->bbNext->bbNum : 0);
7280
7281     LoopCloneVisitorInfo info(context, loopNum, nullptr);
7282     for (BasicBlock* block = beg; block != end->bbNext; block = block->bbNext)
7283     {
7284         compCurBB = block;
7285         for (GenTreePtr stmt = block->bbTreeList; stmt; stmt = stmt->gtNext)
7286         {
7287             info.stmt = stmt;
7288             fgWalkTreePre(&stmt->gtStmt.gtStmtExpr, optCanOptimizeByLoopCloningVisitor, &info, false, false);
7289         }
7290     }
7291
7292     return true;
7293 }
7294
7295 //---------------------------------------------------------------------------------------------------------------
7296 //  optExtractArrIndex: Try to extract the array index from "tree".
7297 //
7298 //  Arguments:
7299 //      tree        the tree to be checked if it is the array [] operation.
7300 //      result      the extracted GT_INDEX information is updated in result.
7301 //      lhsNum      for the root level (function is recursive) callers should be BAD_VAR_NUM.
7302 //
7303 //  Return Value:
7304 //      Returns true if array index can be extracted, else, return false. See assumption about
7305 //      what will be extracted. The "result" variable's rank parameter is advanced for every
7306 //      dimension of [] encountered.
7307 //
7308 //  Operation:
7309 //      Given a "tree" extract the GT_INDEX node in "result" as ArrIndex. In FlowGraph morph
7310 //      we have converted a GT_INDEX tree into a scaled index base offset expression. We need
7311 //      to reconstruct this to be able to know if this is an array access.
7312 //
7313 //  Assumption:
7314 //      The method extracts only if the array base and indices are GT_LCL_VAR.
7315 //
7316 //  TODO-CQ: CLONE: After morph make sure this method extracts values before morph.
7317 //
7318 //    [000000001AF828D8] ---XG-------                     indir     int   
7319 //    [000000001AF872C8] ------------                           const     long   16 Fseq[#FirstElem]
7320 //    [000000001AF87340] ------------                        +         byref 
7321 //    [000000001AF87160] -------N----                                 const     long   2
7322 //    [000000001AF871D8] ------------                              <<        long  
7323 //    [000000001AF870C0] ------------                                 cast      long <- int
7324 //    [000000001AF86F30] i-----------                                    lclVar    int    V04 loc0         
7325 //    [000000001AF87250] ------------                           +         byref 
7326 //    [000000001AF86EB8] ------------                              lclVar    ref    V01 arg1         
7327 //    [000000001AF87468] ---XG-------                  comma     int   
7328 //    [000000001AF87020] ---X--------                     arrBndsChk void  
7329 //    [000000001AF86FA8] ---X--------                        arrLen    int   
7330 //    [000000001AF827E8] ------------                           lclVar    ref    V01 arg1         
7331 //    [000000001AF82860] ------------                        lclVar    int    V04 loc0         
7332 //    [000000001AF829F0] -A-XG-------               =         int   
7333 //    [000000001AF82978] D------N----                  lclVar    int    V06 tmp0         
7334 //
7335 bool Compiler::optExtractArrIndex(GenTreePtr tree, ArrIndex* result, unsigned lhsNum)
7336 {
7337     if (tree->gtOper != GT_COMMA)
7338     {
7339         return false;
7340     }
7341     GenTreePtr before = tree->gtGetOp1();
7342     if (before->gtOper != GT_ARR_BOUNDS_CHECK)
7343     {
7344         return false;
7345     }
7346     GenTreeBoundsChk* arrBndsChk = before->AsBoundsChk();
7347     if (arrBndsChk->gtArrLen->gtGetOp1()->gtOper != GT_LCL_VAR)
7348     {
7349         return false;
7350     }
7351     if (arrBndsChk->gtIndex->gtOper != GT_LCL_VAR)
7352     {
7353         return false;
7354     }
7355     unsigned arrLcl = arrBndsChk->gtArrLen->gtGetOp1()->gtLclVarCommon.gtLclNum;
7356     if (lhsNum != BAD_VAR_NUM && arrLcl != lhsNum)
7357     {
7358         return false;
7359     }
7360
7361     unsigned indLcl = arrBndsChk->gtIndex->gtLclVarCommon.gtLclNum;
7362
7363     GenTreePtr after = tree->gtGetOp2();
7364
7365     if (after->gtOper != GT_IND)
7366     {
7367         return false;
7368     }
7369     GenTreePtr sibo = after->gtGetOp1();
7370     if (sibo->gtOper != GT_ADD)
7371     {
7372         return false;
7373     }
7374     GenTreePtr sib = sibo->gtGetOp1();
7375     GenTreePtr ofs = sibo->gtGetOp2();
7376     if (ofs->gtOper != GT_CNS_INT)
7377     {
7378         return false;
7379     }
7380     if (sib->gtOper != GT_ADD)
7381     {
7382         return false;
7383     }
7384     GenTreePtr si = sib->gtGetOp2();
7385     GenTreePtr base = sib->gtGetOp1();
7386     if (si->gtOper != GT_LSH)
7387     {
7388         return false;
7389     }
7390     if (base->OperGet() != GT_LCL_VAR || base->gtLclVarCommon.gtLclNum != arrLcl)
7391     {
7392         return false;
7393     }
7394     GenTreePtr scale = si->gtGetOp2();
7395     GenTreePtr index = si->gtGetOp1();
7396     if (scale->gtOper != GT_CNS_INT)
7397     {
7398         return false;
7399     }
7400 #ifdef _TARGET_AMD64_
7401     if (index->gtOper != GT_CAST)
7402     {
7403         return false;
7404     }
7405     GenTreePtr indexVar = index->gtGetOp1();
7406 #else
7407     GenTreePtr indexVar = index;
7408 #endif
7409     if (indexVar->gtOper != GT_LCL_VAR || indexVar->gtLclVarCommon.gtLclNum != indLcl)
7410     {
7411         return false;
7412     }
7413     if (lhsNum == BAD_VAR_NUM)
7414     {
7415         result->arrLcl = arrLcl;
7416     }
7417     result->indLcls.Push(indLcl);
7418     result->bndsChks.Push(tree);
7419     result->useBlock = compCurBB;
7420     result->rank++;
7421
7422     return true;
7423 }
7424
7425 //---------------------------------------------------------------------------------------------------------------
7426 //  optReconstructArrIndex: Reconstruct array index.
7427 //
7428 //  Arguments:
7429 //      tree        the tree to be checked if it is an array [][][] operation.
7430 //      result      the extracted GT_INDEX information.
7431 //      lhsNum      for the root level (function is recursive) callers should be BAD_VAR_NUM.
7432 //
7433 //  Return Value:
7434 //      Returns true if array index can be extracted, else, return false. "rank" field in
7435 //      "result" contains the array access depth. The "indLcls" fields contain the indices.
7436 //
7437 //  Operation:
7438 //      Recursively look for a list of array indices. In the example below, we encounter,
7439 //      V03 = ((V05 = V00[V01]), (V05[V02])) which corresponds to access of V00[V01][V02]
7440 //      The return value would then be:
7441 //      ArrIndex result { arrLcl: V00, indLcls: [V01, V02], rank: 2 }
7442 //
7443 //      V00[V01][V02] would be morphed as:
7444 //
7445 //      [000000001B366848] ---XG-------                        indir     int   
7446 //      [000000001B36BC50] ------------                                 V05 + (V02 << 2) + 16
7447 //      [000000001B36C200] ---XG-------                     comma     int   
7448 //      [000000001B36BDB8] ---X--------                        arrBndsChk(V05, V02)
7449 //      [000000001B36C278] -A-XG-------                  comma     int   
7450 //      [000000001B366730] R--XG-------                           indir     ref
7451 //      [000000001B36C2F0] ------------                             V00 + (V01 << 3) + 24
7452 //      [000000001B36C818] ---XG-------                        comma     ref   
7453 //      [000000001B36C458] ---X--------                           arrBndsChk(V00, V01)
7454 //      [000000001B36BB60] -A-XG-------                     =         ref   
7455 //      [000000001B36BAE8] D------N----                        lclVar    ref    V05 tmp2         
7456 //      [000000001B36A668] -A-XG-------               =         int   
7457 //      [000000001B36A5F0] D------N----                  lclVar    int    V03 tmp0
7458 //
7459 //  Assumption:
7460 //      The method extracts only if the array base and indices are GT_LCL_VAR.
7461 //
7462 bool Compiler::optReconstructArrIndex(GenTreePtr tree, ArrIndex* result, unsigned lhsNum)
7463 {
7464     // If we can extract "tree" (which is a top level comma) return.
7465     if (optExtractArrIndex(tree, result, lhsNum))
7466     {
7467         return true;
7468     }
7469     // We have a comma (check if array base expr is computed in "before"), descend further.
7470     else if (tree->OperGet() == GT_COMMA)
7471     {
7472         GenTreePtr before = tree->gtGetOp1();
7473         // "before" should evaluate an array base for the "after" indexing.
7474         if (before->OperGet() != GT_ASG)
7475         {
7476             return false;
7477         }
7478         GenTreePtr lhs = before->gtGetOp1();
7479         GenTreePtr rhs = before->gtGetOp2();
7480
7481         // "rhs" should contain an GT_INDEX
7482         if (!lhs->IsLocal() || !optReconstructArrIndex(rhs, result, lhsNum))
7483         {
7484             return false;
7485         }
7486         unsigned lhsNum = lhs->gtLclVarCommon.gtLclNum;
7487         GenTreePtr after = tree->gtGetOp2();
7488         // Pass the "lhsNum", so we can verify if indeed it is used as the array base.
7489         return optExtractArrIndex(after, result, lhsNum);
7490     }
7491     return false;
7492 }
7493
7494 /* static */
7495 Compiler::fgWalkResult Compiler::optCanOptimizeByLoopCloningVisitor(GenTreePtr* pTree, Compiler::fgWalkData* data)
7496 {
7497     return data->compiler->optCanOptimizeByLoopCloning(*pTree, (LoopCloneVisitorInfo*) data->pCallbackData);
7498 }
7499
7500
7501 //-------------------------------------------------------------------------
7502 //  optIsStackLocalInvariant: Is stack local invariant in loop.
7503 //
7504 //  Arguments:
7505 //      loopNum      The loop in which the variable is tested for invariance.
7506 //      lclNum       The local that is tested for invariance in the loop.
7507 //
7508 //  Return Value:
7509 //      Returns true if the variable is loop invariant in loopNum.
7510 //
7511 bool Compiler::optIsStackLocalInvariant(unsigned loopNum, unsigned lclNum)
7512 {
7513     if (lvaVarAddrExposed(lclNum))
7514     {
7515         return false;
7516     }
7517     if (optIsVarAssgLoop(loopNum, lclNum))
7518     {
7519         return false;
7520     }
7521     return true;
7522 }
7523
7524 //----------------------------------------------------------------------------------------------
7525 //  optCanOptimizeByLoopCloning: Check if the tree can be optimized by loop cloning and if so,
7526 //      identify as potential candidate and update the loop context.
7527 //
7528 //  Arguments:
7529 //      tree         The tree encountered during the tree walk.
7530 //      info         Supplies information about the current block or stmt in which the tree is.
7531 //                   Also supplies the "context" pointer for updating with loop cloning
7532 //                   candidates. Also supplies loopNum.
7533 //
7534 //  Operation:
7535 //      If array index can be reconstructed, check if the iter var of the loop matches the
7536 //      array index var in some dim. Also ensure other index vars before the identified
7537 //      dim are loop invariant.
7538 //  
7539 //  Return Value:
7540 //      Skip sub trees if the optimization candidate is identified or else continue walking
7541 //
7542 Compiler::fgWalkResult Compiler::optCanOptimizeByLoopCloning(GenTreePtr tree, LoopCloneVisitorInfo* info)
7543 {
7544     ArrIndex arrIndex(getAllocator());
7545
7546     // Check if array index can be optimized.
7547     if (optReconstructArrIndex(tree, &arrIndex, BAD_VAR_NUM))
7548     {
7549         assert(tree->gtOper == GT_COMMA);
7550 #ifdef DEBUG
7551         if (verbose)
7552         {
7553             JITDUMP("Found ArrIndex at tree ");
7554             printTreeID(tree);
7555             printf(" which is equivalent to: ");
7556             arrIndex.Print();
7557             JITDUMP("\n");
7558         }
7559 #endif
7560         if (!optIsStackLocalInvariant(info->loopNum, arrIndex.arrLcl))
7561         {
7562             return WALK_SKIP_SUBTREES;
7563         }
7564
7565         // Walk the dimensions and see if iterVar of the loop is used as index.
7566         for (unsigned dim = 0; dim < arrIndex.rank; ++dim)
7567         {
7568             // Is index variable also used as the loop iter var.
7569             if (arrIndex.indLcls[dim] == optLoopTable[info->loopNum].lpIterVar())
7570             {
7571                 // Check the previous indices are all loop invariant.
7572                 for (unsigned dim2 = 0; dim2 < dim; ++dim2)
7573                 {
7574                     if (optIsVarAssgLoop(info->loopNum, arrIndex.indLcls[dim2]))
7575                     {
7576                         JITDUMP("V%02d is assigned in loop\n", arrIndex.indLcls[dim2]);
7577                         return WALK_SKIP_SUBTREES;
7578                     }
7579                 }
7580 #ifdef DEBUG
7581                 if (verbose)
7582                 {
7583                     JITDUMP("Loop %d can be cloned for ArrIndex ", info->loopNum);
7584                     arrIndex.Print();
7585                     JITDUMP(" on dim %d\n", dim);
7586                 }
7587 #endif
7588                 // Update the loop context.
7589                 info->context->EnsureLoopOptInfo(info->loopNum)->Push(new (this, CMK_LoopOpt) LcJaggedArrayOptInfo(arrIndex, dim, info->stmt));
7590             }
7591             else
7592             {
7593                 JITDUMP("Induction V%02d is not used as index on dim %d\n", optLoopTable[info->loopNum].lpIterVar(), dim);
7594             }
7595         }
7596         return WALK_SKIP_SUBTREES;
7597     }
7598     else if (tree->gtOper == GT_ARR_ELEM)
7599     {
7600         // TODO-CQ: CLONE: Implement.
7601         return WALK_SKIP_SUBTREES;
7602     }
7603     return WALK_CONTINUE;
7604 }
7605
7606 struct optRangeCheckDsc
7607 {
7608     Compiler* pCompiler;
7609     bool      bValidIndex;
7610 };
7611 /*
7612     Walk to make sure that only locals and constants are contained in the index
7613     for a range check
7614 */
7615 Compiler::fgWalkResult      Compiler::optValidRangeCheckIndex(GenTreePtr * pTree, fgWalkData *data)
7616 {
7617     GenTreePtr        tree = *pTree;
7618     optRangeCheckDsc* pData= (optRangeCheckDsc*) data->pCallbackData;
7619
7620     if (tree->gtOper == GT_IND || tree->gtOper == GT_CLS_VAR || 
7621         tree->gtOper == GT_FIELD || tree->gtOper == GT_LCL_FLD)
7622     {
7623         pData->bValidIndex = false;
7624         return WALK_ABORT;
7625     }
7626
7627     if (tree->gtOper == GT_LCL_VAR)
7628     {
7629         if (pData->pCompiler->lvaTable[tree->gtLclVarCommon.gtLclNum].lvAddrExposed)
7630         {
7631             pData->bValidIndex = false;
7632             return WALK_ABORT;
7633         }
7634     }
7635
7636     return WALK_CONTINUE;
7637 }
7638
7639 /*
7640     returns true if a range check can legally be removed (for the moment it checks
7641     that the array is a local array (non subject to racing conditions) and that the
7642     index is either a constant or a local
7643 */
7644 bool Compiler::optIsRangeCheckRemovable(GenTreePtr tree)
7645 {
7646     noway_assert(tree->gtOper == GT_ARR_BOUNDS_CHECK);
7647     GenTreeBoundsChk* bndsChk = tree->AsBoundsChk();
7648     GenTreePtr pArray = bndsChk->GetArray();
7649     if (pArray == NULL && !bndsChk->gtArrLen->IsCnsIntOrI())
7650     {
7651         return false;
7652     }
7653     GenTreePtr pIndex = bndsChk->gtIndex;
7654     
7655     // The length must be a constant (the pArray == NULL case) or the array reference must be a local. 
7656     // Otherwise we can be targeted by malicious race-conditions.
7657     if (pArray != NULL)
7658     {
7659         if ( pArray->gtOper != GT_LCL_VAR )
7660         {        
7661
7662 #ifdef DEBUG
7663             if (verbose)
7664             {
7665                 printf("Can't remove range check if the array isn't referenced with a local\n");
7666                 gtDispTree(pArray);
7667             }
7668 #endif
7669             return false;
7670         }
7671         else
7672         {
7673             noway_assert(pArray->gtType == TYP_REF);    
7674             noway_assert(pArray->gtLclVarCommon.gtLclNum < lvaCount);
7675
7676             if (lvaTable[pArray->gtLclVarCommon.gtLclNum].lvAddrExposed)
7677             {
7678                 // If the array address has been taken, don't do the optimization
7679                 // (this restriction can be lowered a bit, but i don't think it's worth it)
7680                 CLANG_FORMAT_COMMENT_ANCHOR;
7681 #ifdef DEBUG
7682                 if (verbose)
7683                 {
7684                     printf("Can't remove range check if the array has its address taken\n");
7685                     gtDispTree(pArray);
7686                 }
7687 #endif
7688                 return false;
7689             }
7690         }
7691     }
7692     
7693     
7694     optRangeCheckDsc Data;
7695     Data.pCompiler  =this;
7696     Data.bValidIndex=true;
7697
7698     fgWalkTreePre(&pIndex, optValidRangeCheckIndex, &Data);
7699         
7700     if (!Data.bValidIndex)
7701     {
7702         #ifdef DEBUG
7703         if (verbose)
7704         {
7705             printf("Can't remove range check with this index");
7706             gtDispTree(pIndex);
7707         }
7708         #endif
7709
7710         return false;
7711     }
7712     
7713
7714     return true;
7715 }
7716
7717 /******************************************************************************
7718  *
7719  * Replace x==null with (x|x)==0 if x is a GC-type.
7720  * This will stress code-gen and the emitter to make sure they support such trees.
7721  */
7722
7723 #ifdef DEBUG
7724
7725 void            Compiler::optOptimizeBoolsGcStress(BasicBlock * condBlock)
7726 {
7727     if (!compStressCompile(STRESS_OPT_BOOLS_GC, 20))
7728         return;
7729     
7730     noway_assert(condBlock->bbJumpKind == BBJ_COND);
7731     GenTreePtr  condStmt = condBlock->bbTreeList->gtPrev->gtStmt.gtStmtExpr;
7732
7733     noway_assert(condStmt->gtOper == GT_JTRUE);
7734
7735     bool        isBool;
7736     GenTreePtr  relop;
7737
7738     GenTreePtr  comparand = optIsBoolCond(condStmt, &relop, &isBool);
7739     
7740     if (comparand == NULL || !varTypeIsGC(comparand->TypeGet()))
7741         return;
7742
7743     if (comparand->gtFlags & (GTF_ASG|GTF_CALL|GTF_ORDER_SIDEEFF))
7744         return;
7745
7746     GenTreePtr  comparandClone = gtCloneExpr(comparand);
7747
7748     // Bump up the ref-counts of any variables in 'comparandClone'
7749     compCurBB = condBlock;
7750     fgWalkTreePre(&comparandClone, Compiler::lvaIncRefCntsCB, (void *)this, true);
7751     
7752     noway_assert(relop->gtOp.gtOp1 == comparand);
7753     genTreeOps oper = compStressCompile(STRESS_OPT_BOOLS_GC, 50) ? GT_OR : GT_AND;
7754     relop->gtOp.gtOp1 = gtNewOperNode(oper, TYP_I_IMPL, comparand, comparandClone);
7755
7756     // Comparand type is already checked, and we have const int, there is no harm
7757     // morphing it into a TYP_I_IMPL.
7758     noway_assert(relop->gtOp.gtOp2->gtOper == GT_CNS_INT);
7759     relop->gtOp.gtOp2->gtType = TYP_I_IMPL;
7760 }
7761
7762 #endif
7763
7764 /******************************************************************************
7765  * Function used by folding of boolean conditionals
7766  * Given a GT_JTRUE node, checks that it is a boolean comparison of the form
7767  *    "if (boolVal ==/!=  0/1)". This is translated into a GT_EQ node with "op1"
7768  *    being a boolean lclVar and "op2" the const 0/1.
7769  * On success, the comparand (ie. boolVal) is returned.   Else NULL.
7770  * compPtr returns the compare node (i.e. GT_EQ or GT_NE node)
7771  * boolPtr returns whether the comparand is a boolean value (must be 0 or 1).
7772  * When return boolPtr equal to true, if the comparison was against a 1 (i.e true)
7773  * value then we morph the tree by reversing the GT_EQ/GT_NE and change the 1 to 0.
7774  */
7775
7776 GenTree *           Compiler::optIsBoolCond(GenTree *   condBranch,
7777                                             GenTree * * compPtr,
7778                                             bool      * boolPtr)
7779 {
7780     bool isBool = false;
7781
7782     noway_assert(condBranch->gtOper == GT_JTRUE);
7783     GenTree *   cond = condBranch->gtOp.gtOp1;
7784
7785     /* The condition must be "!= 0" or "== 0" */
7786
7787     if ((cond->gtOper != GT_EQ) && (cond->gtOper != GT_NE))
7788         return nullptr;
7789
7790     /* Return the compare node to the caller */
7791
7792     *compPtr = cond;
7793
7794     /* Get hold of the comparands */
7795
7796     GenTree *   opr1 = cond->gtOp.gtOp1;
7797     GenTree *   opr2 = cond->gtOp.gtOp2;
7798
7799     if  (opr2->gtOper != GT_CNS_INT)
7800         return  nullptr;
7801
7802     if (!opr2->IsIntegralConst(0) && !opr2->IsIntegralConst(1))
7803         return nullptr;
7804
7805     ssize_t ival2 = opr2->gtIntCon.gtIconVal;
7806
7807     /* Is the value a boolean?
7808      * We can either have a boolean expression (marked GTF_BOOLEAN) or
7809      * a local variable that is marked as being boolean (lvIsBoolean) */
7810
7811     if  (opr1->gtFlags & GTF_BOOLEAN)
7812     {
7813         isBool = true;
7814     }
7815     else if ((opr1->gtOper == GT_CNS_INT) &&
7816              (opr1->IsIntegralConst(0) || opr1->IsIntegralConst(1)))
7817     {
7818         isBool = true;
7819     }
7820     else if (opr1->gtOper == GT_LCL_VAR)
7821     {
7822         /* is it a boolean local variable */
7823
7824         unsigned    lclNum = opr1->gtLclVarCommon.gtLclNum;
7825         noway_assert(lclNum < lvaCount);
7826
7827         if (lvaTable[lclNum].lvIsBoolean)
7828             isBool = true;
7829     }
7830
7831     /* Was our comparison against the constant 1 (i.e. true) */
7832     if  (ival2 == 1)
7833     {
7834         // If this is a boolean expression tree we can reverse the relop 
7835         // and change the true to false.
7836         if (isBool)
7837         {
7838             gtReverseCond(cond);
7839             opr2->gtIntCon.gtIconVal = 0;
7840         }
7841         else
7842             return NULL;
7843     }
7844
7845     *boolPtr = isBool;
7846     return opr1;
7847 }
7848
7849
7850 void                Compiler::optOptimizeBools()
7851 {
7852 #ifdef DEBUG
7853     if  (verbose) 
7854     {
7855         printf("*************** In optOptimizeBools()\n");
7856         if (verboseTrees)
7857         {
7858             printf("Blocks/Trees before phase\n");
7859             fgDispBasicBlocks(true);
7860         }
7861     }
7862 #endif
7863     bool            change;
7864
7865     do
7866     {
7867         change = false;
7868
7869         for (BasicBlock * b1 = fgFirstBB; b1; b1 = b1->bbNext)
7870         {
7871             /* We're only interested in conditional jumps here */
7872
7873             if  (b1->bbJumpKind != BBJ_COND)
7874                 continue;
7875
7876             /* If there is no next block, we're done */
7877
7878             BasicBlock * b2 = b1->bbNext;
7879             if  (!b2)
7880                 break;
7881
7882             /* The next block must not be marked as BBF_DONT_REMOVE */
7883             if  (b2->bbFlags & BBF_DONT_REMOVE)
7884                 continue;
7885
7886             /* The next block also needs to be a condition */
7887
7888             if  (b2->bbJumpKind != BBJ_COND)
7889             {
7890 #ifdef DEBUG
7891                 optOptimizeBoolsGcStress(b1);
7892 #endif
7893                 continue;
7894             }
7895
7896             bool    sameTarget; // Do b1 and b2 have the same bbJumpDest?
7897
7898             if      (b1->bbJumpDest == b2->bbJumpDest)
7899             {
7900                 /* Given the following sequence of blocks :
7901                         B1: brtrue(t1, BX)
7902                         B2: brtrue(t2, BX)
7903                         B3:
7904                    we wil try to fold it to :
7905                         B1: brtrue(t1|t2, BX)
7906                         B3:
7907                 */
7908
7909                 sameTarget = true;
7910             }
7911             else if (b1->bbJumpDest == b2->bbNext)  /*b1->bbJumpDest->bbNum == n1+2*/
7912             {
7913                 /* Given the following sequence of blocks :
7914                         B1: brtrue(t1, B3)
7915                         B2: brtrue(t2, BX)
7916                         B3:
7917                    we will try to fold it to :
7918                         B1: brtrue((!t1)&&t2, B3)
7919                         B3:
7920                 */
7921
7922                 sameTarget = false;
7923             }
7924             else
7925             {
7926                 continue;
7927             }
7928
7929             /* The second block must contain a single statement */
7930
7931             GenTreePtr s2 = b2->bbTreeList;
7932             if  (s2->gtPrev != s2)
7933                 continue;
7934
7935             noway_assert(s2->gtOper == GT_STMT);
7936             GenTreePtr  t2 = s2->gtStmt.gtStmtExpr;
7937             noway_assert(t2->gtOper == GT_JTRUE);
7938
7939             /* Find the condition for the first block */
7940
7941             GenTreePtr  s1 = b1->bbTreeList->gtPrev;
7942
7943             noway_assert(s1->gtOper == GT_STMT);
7944             GenTreePtr  t1 = s1->gtStmt.gtStmtExpr;
7945             noway_assert(t1->gtOper == GT_JTRUE);
7946
7947             if  (b2->countOfInEdges() > 1)
7948                 continue;
7949
7950             /* Find the branch conditions of b1 and b2 */
7951
7952             bool        bool1, bool2;
7953
7954             GenTreePtr  c1 = optIsBoolCond(t1, &t1, &bool1);
7955             if (!c1) continue;
7956
7957             GenTreePtr  c2 = optIsBoolCond(t2, &t2, &bool2);
7958             if (!c2) continue;
7959
7960             noway_assert(t1->gtOper == GT_EQ || t1->gtOper == GT_NE && t1->gtOp.gtOp1 == c1);
7961             noway_assert(t2->gtOper == GT_EQ || t2->gtOper == GT_NE && t2->gtOp.gtOp1 == c2);
7962
7963             // Leave out floats where the bit-representation is more complicated 
7964             // - there are two representations for 0.
7965             //            
7966             if (varTypeIsFloating(c1->TypeGet()) || varTypeIsFloating(c2->TypeGet()))
7967                 continue;
7968
7969             // Make sure the types involved are of the same sizes
7970             if (genTypeSize(c1->TypeGet()) != genTypeSize(c2->TypeGet()))
7971                 continue;
7972             if (genTypeSize(t1->TypeGet()) != genTypeSize(t2->TypeGet()))
7973                 continue;
7974 #ifdef _TARGET_ARMARCH_
7975             // Skip the small operand which we cannot encode.
7976             if (varTypeIsSmall(c1->TypeGet()))
7977                 continue;
7978 #endif
7979             /* The second condition must not contain side effects */
7980
7981             if  (c2->gtFlags & GTF_GLOB_EFFECT)
7982                 continue;
7983
7984             /* The second condition must not be too expensive */
7985
7986             gtPrepareCost(c2);
7987
7988             if (c2->gtCostEx > 12)
7989                 continue;
7990
7991             genTreeOps      foldOp;
7992             genTreeOps      cmpOp;
7993             var_types       foldType = c1->TypeGet();
7994             if (varTypeIsGC(foldType))
7995             {
7996                 foldType = TYP_I_IMPL;
7997             }
7998
7999             if (sameTarget)
8000             {
8001                 /* Both conditions must be the same */
8002
8003                 if (t1->gtOper != t2->gtOper)
8004                     continue;
8005
8006                 if (t1->gtOper == GT_EQ)
8007                 {
8008                     /* t1:c1==0 t2:c2==0 ==> Branch to BX if either value is 0
8009                        So we will branch to BX if (c1&c2)==0 */
8010
8011                     foldOp = GT_AND;
8012                     cmpOp  = GT_EQ;
8013                 }
8014                 else
8015                 {
8016                     /* t1:c1!=0 t2:c2!=0 ==> Branch to BX if either value is non-0
8017                        So we will branch to BX if (c1|c2)!=0 */
8018
8019                     foldOp = GT_OR;
8020                     cmpOp  = GT_NE;
8021                 }
8022             }
8023             else
8024             {
8025                 /* The b1 condition must be the reverse of the b2 condition */
8026
8027                 if (t1->gtOper == t2->gtOper)
8028                     continue;
8029
8030                 if (t1->gtOper == GT_EQ)
8031                 {
8032                     /* t1:c1==0 t2:c2!=0 ==> Branch to BX if both values are non-0
8033                        So we will branch to BX if (c1&c2)!=0 */
8034
8035                     foldOp = GT_AND;
8036                     cmpOp  = GT_NE;
8037                 }
8038                 else
8039                 {
8040                     /* t1:c1!=0 t2:c2==0 ==> Branch to BX if both values are 0
8041                        So we will branch to BX if (c1|c2)==0 */
8042
8043                     foldOp = GT_OR;
8044                     cmpOp  = GT_EQ;
8045                 }
8046             }
8047
8048             // Anding requires both values to be 0 or 1
8049
8050             if ((foldOp == GT_AND) && (!bool1 || !bool2))
8051                 continue;
8052
8053             //
8054             // Now update the trees
8055             //
8056             GenTreePtr cmpOp1 = gtNewOperNode(foldOp, foldType, c1, c2);
8057             if (bool1 && bool2)
8058             {
8059                 /* When we 'OR'/'AND' two booleans, the result is boolean as well */
8060                 cmpOp1->gtFlags |= GTF_BOOLEAN;
8061             }
8062
8063             t1->SetOper(cmpOp);
8064             t1->gtOp.gtOp1 = cmpOp1;
8065             t1->gtOp.gtOp2->gtType = foldType; // Could have been varTypeIsGC()
8066
8067 #if FEATURE_SET_FLAGS
8068             // For comparisons against zero we will have the GTF_SET_FLAGS set
8069             // and this can cause an assert to fire in fgMoveOpsLeft(GenTreePtr tree)
8070             // during the CSE phase.
8071             //
8072             // So make sure to clear any GTF_SET_FLAGS bit on these operations
8073             // as they are no longer feeding directly into a comparisons against zero
8074
8075             // Make sure that the GTF_SET_FLAGS bit is cleared.
8076             // Fix 388436 ARM JitStress WP7
8077             c1->gtFlags &= ~GTF_SET_FLAGS;
8078             c2->gtFlags &= ~GTF_SET_FLAGS;
8079
8080             // The new top level node that we just created does feed directly into
8081             // a comparison against zero, so set the GTF_SET_FLAGS bit so that
8082             // we generate an instuction that sets the flags, which allows us 
8083             // to omit the cmp with zero instruction.
8084
8085             // Request that the codegen for cmpOp1 sets the condition flags
8086             // when it generates the code for cmpOp1.
8087             //
8088             cmpOp1->gtRequestSetFlags();
8089 #endif      
8090
8091              flowList * edge1 = fgGetPredForBlock(b1->bbJumpDest, b1);
8092              flowList * edge2;
8093
8094             /* Modify the target of the conditional jump and update bbRefs and bbPreds */
8095
8096             if (sameTarget)
8097             {
8098                 edge2 = fgGetPredForBlock(b2->bbJumpDest, b2);
8099             }
8100             else
8101             {
8102                 edge2 = fgGetPredForBlock(b2->bbNext, b2);
8103
8104                 fgRemoveRefPred(b1->bbJumpDest, b1);
8105
8106                 b1->bbJumpDest = b2->bbJumpDest;
8107
8108                 fgAddRefPred(b2->bbJumpDest, b1);
8109             }
8110
8111             noway_assert(edge1 != NULL);
8112             noway_assert(edge2 != NULL);
8113
8114             BasicBlock::weight_t edgeSumMin = edge1->flEdgeWeightMin + edge2->flEdgeWeightMin;
8115             BasicBlock::weight_t edgeSumMax = edge1->flEdgeWeightMax + edge2->flEdgeWeightMax;
8116             if ((edgeSumMax >= edge1->flEdgeWeightMax) && (edgeSumMax >= edge2->flEdgeWeightMax))
8117             {
8118                 edge1->flEdgeWeightMin = edgeSumMin;
8119                 edge1->flEdgeWeightMax = edgeSumMax;
8120             }
8121             else
8122             {
8123                 edge1->flEdgeWeightMin = BB_ZERO_WEIGHT;
8124                 edge1->flEdgeWeightMax = BB_MAX_WEIGHT;
8125             }
8126
8127             /* Get rid of the second block (which is a BBJ_COND) */
8128
8129             noway_assert(b1->bbJumpKind == BBJ_COND);
8130             noway_assert(b2->bbJumpKind == BBJ_COND);
8131             noway_assert(b1->bbJumpDest == b2->bbJumpDest);
8132             noway_assert(b1->bbNext == b2); noway_assert(b2->bbNext);           
8133
8134             fgUnlinkBlock(b2);
8135             b2->bbFlags |= BBF_REMOVED;
8136
8137             // If b2 was the last block of a try or handler, update the EH table.
8138
8139             ehUpdateForDeletedBlock(b2);
8140
8141             /* Update bbRefs and bbPreds */
8142
8143             /* Replace pred 'b2' for 'b2->bbNext' with 'b1'
8144              * Remove  pred 'b2' for 'b2->bbJumpDest' */
8145
8146             fgReplacePred(b2->bbNext, b2, b1);
8147
8148             fgRemoveRefPred(b2->bbJumpDest, b2);
8149
8150             /* Update the block numbers and try again */
8151
8152             change = true;
8153 /*
8154             do
8155             {
8156                 b2->bbNum = ++n1;
8157                 b2 = b2->bbNext;
8158             }
8159             while (b2);
8160 */
8161
8162             // Update loop table
8163             fgUpdateLoopsAfterCompacting(b1, b2);
8164             
8165 #ifdef DEBUG
8166             if  (verbose)
8167             {
8168                 printf("Folded %sboolean conditions of BB%02u and BB%02u to :\n",
8169                        c2->OperIsLeaf() ? "" : "non-leaf ",
8170                        b1->bbNum, b2->bbNum);
8171                 gtDispTree(s1); printf("\n");
8172             }
8173 #endif
8174         }
8175     }
8176     while (change);
8177
8178 #ifdef DEBUG
8179     fgDebugCheckBBlist();
8180 #endif
8181 }