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