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