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