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