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