Make GT_LIST processing non-recursive to avoid StackOverflow.
[platform/upstream/coreclr.git] / src / jit / flowgraph.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                          FlowGraph                                        XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13
14 #include "jitpch.h"
15 #ifdef _MSC_VER
16 #pragma hdrstop
17 #endif
18
19 #include "allocacheck.h" // for alloca
20
21 /*****************************************************************************/
22
23 void Compiler::fgInit()
24 {
25     impInit();
26
27     /* Initialization for fgWalkTreePre() and fgWalkTreePost() */
28
29     fgFirstBBScratch = nullptr;
30
31 #ifdef DEBUG
32     fgPrintInlinedMethods = JitConfig.JitPrintInlinedMethods() == 1;
33 #endif // DEBUG
34
35     /* We haven't yet computed the bbPreds lists */
36     fgComputePredsDone = false;
37
38     /* We haven't yet computed the bbCheapPreds lists */
39     fgCheapPredsValid = false;
40
41     /* We haven't yet computed the edge weight */
42     fgEdgeWeightsComputed    = false;
43     fgHaveValidEdgeWeights   = false;
44     fgSlopUsedInEdgeWeights  = false;
45     fgRangeUsedInEdgeWeights = true;
46     fgNeedsUpdateFlowGraph   = false;
47     fgCalledWeight           = BB_ZERO_WEIGHT;
48
49     /* We haven't yet computed the dominator sets */
50     fgDomsComputed = false;
51
52 #ifdef DEBUG
53     fgReachabilitySetsValid = false;
54 #endif // DEBUG
55
56     /* We don't know yet which loops will always execute calls */
57     fgLoopCallMarked = false;
58
59     /* We haven't created GC Poll blocks yet. */
60     fgGCPollsCreated = false;
61
62     /* Initialize the basic block list */
63
64     fgFirstBB        = nullptr;
65     fgLastBB         = nullptr;
66     fgFirstColdBlock = nullptr;
67
68 #if FEATURE_EH_FUNCLETS
69     fgFirstFuncletBB  = nullptr;
70     fgFuncletsCreated = false;
71 #endif // FEATURE_EH_FUNCLETS
72
73     fgBBcount = 0;
74
75 #ifdef DEBUG
76     fgBBcountAtCodegen = 0;
77 #endif // DEBUG
78
79     fgBBNumMax        = 0;
80     fgEdgeCount       = 0;
81     fgDomBBcount      = 0;
82     fgBBVarSetsInited = false;
83     fgReturnCount     = 0;
84
85     // Initialize BlockSet data.
86     fgCurBBEpoch             = 0;
87     fgCurBBEpochSize         = 0;
88     fgBBSetCountInSizeTUnits = 0;
89
90     genReturnBB = nullptr;
91
92     /* We haven't reached the global morphing phase */
93     fgGlobalMorph  = false;
94     fgExpandInline = false;
95     fgModified     = false;
96
97 #ifdef DEBUG
98     fgSafeBasicBlockCreation = true;
99 #endif // DEBUG
100
101     fgLocalVarLivenessDone = false;
102
103     /* Statement list is not threaded yet */
104
105     fgStmtListThreaded = false;
106
107     // Initialize the logic for adding code. This is used to insert code such
108     // as the code that raises an exception when an array range check fails.
109
110     fgAddCodeList = nullptr;
111     fgAddCodeModf = false;
112
113     for (int i = 0; i < SCK_COUNT; i++)
114     {
115         fgExcptnTargetCache[i] = nullptr;
116     }
117
118     /* Keep track of the max count of pointer arguments */
119
120     fgPtrArgCntCur = 0;
121     fgPtrArgCntMax = 0;
122
123     /* This global flag is set whenever we remove a statement */
124     fgStmtRemoved = false;
125
126     /* This global flag is set whenever we add a throw block for a RngChk */
127     fgRngChkThrowAdded = false; /* reset flag for fgIsCodeAdded() */
128
129     fgIncrCount = 0;
130
131     /* We will record a list of all BBJ_RETURN blocks here */
132     fgReturnBlocks = nullptr;
133
134     /* This is set by fgComputeReachability */
135     fgEnterBlks = BlockSetOps::UninitVal();
136
137 #ifdef DEBUG
138     fgEnterBlksSetValid = false;
139 #endif // DEBUG
140
141 #if !FEATURE_EH_FUNCLETS
142     ehMaxHndNestingCount = 0;
143 #endif // !FEATURE_EH_FUNCLETS
144
145     /* Init the fgBigOffsetMorphingTemps to be BAD_VAR_NUM. */
146     for (int i = 0; i < TYP_COUNT; i++)
147     {
148         fgBigOffsetMorphingTemps[i] = BAD_VAR_NUM;
149     }
150
151     fgNoStructPromotion      = false;
152     fgNoStructParamPromotion = false;
153
154     optValnumCSE_phase = false; // referenced in fgMorphSmpOp()
155
156 #ifdef DEBUG
157     fgNormalizeEHDone = false;
158 #endif // DEBUG
159
160 #ifdef DEBUG
161     if (!compIsForInlining())
162     {
163         if ((JitConfig.JitNoStructPromotion() & 1) == 1)
164         {
165             fgNoStructPromotion = true;
166         }
167         if ((JitConfig.JitNoStructPromotion() & 2) == 2)
168         {
169             fgNoStructParamPromotion = true;
170         }
171     }
172 #endif // DEBUG
173
174     if (!compIsForInlining())
175     {
176         m_promotedStructDeathVars = nullptr;
177     }
178 #ifdef FEATURE_SIMD
179     fgPreviousCandidateSIMDFieldAsgStmt = nullptr;
180 #endif
181 }
182
183 bool Compiler::fgHaveProfileData()
184 {
185     if (compIsForInlining() || compIsForImportOnly())
186     {
187         return false;
188     }
189
190     return (fgProfileBuffer != nullptr);
191 }
192
193 bool Compiler::fgGetProfileWeightForBasicBlock(IL_OFFSET offset, unsigned* weightWB)
194 {
195     noway_assert(weightWB != nullptr);
196     unsigned weight = 0;
197
198 #ifdef DEBUG
199     unsigned hashSeed = fgStressBBProf();
200     if (hashSeed != 0)
201     {
202         unsigned hash = (info.compMethodHash() * hashSeed) ^ (offset * 1027);
203
204         // We need to especially stress the procedure splitting codepath.  Therefore
205         // one third the time we should return a weight of zero.
206         // Otherwise we should return some random weight (usually between 0 and 288).
207         // The below gives a weight of zero, 44% of the time
208
209         if (hash % 3 == 0)
210         {
211             weight = 0;
212         }
213         else if (hash % 11 == 0)
214         {
215             weight = (hash % 23) * (hash % 29) * (hash % 31);
216         }
217         else
218         {
219             weight = (hash % 17) * (hash % 19);
220         }
221
222         // The first block is never given a weight of zero
223         if ((offset == 0) && (weight == 0))
224         {
225             weight = 1 + (hash % 5);
226         }
227
228         *weightWB = weight;
229         return true;
230     }
231 #endif // DEBUG
232
233     if (fgHaveProfileData() == false)
234     {
235         return false;
236     }
237
238     noway_assert(!compIsForInlining());
239     for (unsigned i = 0; i < fgProfileBufferCount; i++)
240     {
241         if (fgProfileBuffer[i].ILOffset == offset)
242         {
243             weight = fgProfileBuffer[i].ExecutionCount;
244
245             *weightWB = weight;
246             return true;
247         }
248     }
249
250     *weightWB = 0;
251     return true;
252 }
253
254 void Compiler::fgInstrumentMethod()
255 {
256     noway_assert(!compIsForInlining());
257
258     // Count the number of basic blocks in the method
259
260     int         countOfBlocks = 0;
261     BasicBlock* block;
262     for (block = fgFirstBB; block; block = block->bbNext)
263     {
264         if (!(block->bbFlags & BBF_IMPORTED) || (block->bbFlags & BBF_INTERNAL))
265         {
266             continue;
267         }
268         countOfBlocks++;
269     }
270
271     // Allocate the profile buffer
272
273     ICorJitInfo::ProfileBuffer* bbProfileBuffer;
274
275     HRESULT res = info.compCompHnd->allocBBProfileBuffer(countOfBlocks, &bbProfileBuffer);
276
277     ICorJitInfo::ProfileBuffer* bbProfileBufferStart = bbProfileBuffer;
278
279     GenTreePtr stmt;
280
281     if (!SUCCEEDED(res))
282     {
283         // The E_NOTIMPL status is returned when we are profiling a generic method from a different assembly
284         if (res == E_NOTIMPL)
285         {
286             // In such cases we still want to add the method entry callback node
287
288             GenTreeArgList* args = gtNewArgList(gtNewIconEmbMethHndNode(info.compMethodHnd));
289             GenTreePtr      call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, 0, args);
290
291             stmt = gtNewStmt(call);
292         }
293         else
294         {
295             noway_assert(!"Error:  failed to allocate bbProfileBuffer");
296             return;
297         }
298     }
299     else
300     {
301         // Assign a buffer entry for each basic block
302
303         for (block = fgFirstBB; block; block = block->bbNext)
304         {
305             if (!(block->bbFlags & BBF_IMPORTED) || (block->bbFlags & BBF_INTERNAL))
306             {
307                 continue;
308             }
309
310             bbProfileBuffer->ILOffset = block->bbCodeOffs;
311
312             GenTreePtr addr;
313             GenTreePtr value;
314
315             value = gtNewOperNode(GT_IND, TYP_INT, gtNewIconEmbHndNode((void*)&bbProfileBuffer->ExecutionCount, nullptr,
316                                                                        GTF_ICON_BBC_PTR));
317             value = gtNewOperNode(GT_ADD, TYP_INT, value, gtNewIconNode(1));
318
319             addr = gtNewOperNode(GT_IND, TYP_INT, gtNewIconEmbHndNode((void*)&bbProfileBuffer->ExecutionCount, nullptr,
320                                                                       GTF_ICON_BBC_PTR));
321
322             addr = gtNewAssignNode(addr, value);
323
324             fgInsertStmtAtBeg(block, addr);
325
326             countOfBlocks--;
327             bbProfileBuffer++;
328         }
329         noway_assert(countOfBlocks == 0);
330
331         // Add the method entry callback node
332
333         GenTreeArgList* args = gtNewArgList(gtNewIconEmbMethHndNode(info.compMethodHnd));
334         GenTreePtr      call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, 0, args);
335
336         GenTreePtr handle =
337             gtNewIconEmbHndNode((void*)&bbProfileBufferStart->ExecutionCount, nullptr, GTF_ICON_BBC_PTR);
338         GenTreePtr value = gtNewOperNode(GT_IND, TYP_INT, handle);
339         GenTreePtr relop = gtNewOperNode(GT_NE, TYP_INT, value, gtNewIconNode(0, TYP_INT));
340         relop->gtFlags |= GTF_RELOP_QMARK;
341         GenTreePtr colon = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), call);
342         GenTreePtr cond  = gtNewQmarkNode(TYP_VOID, relop, colon);
343         stmt             = gtNewStmt(cond);
344     }
345
346     fgEnsureFirstBBisScratch();
347
348     fgInsertStmtAtEnd(fgFirstBB, stmt);
349 }
350
351 /*****************************************************************************
352  *
353  *  Create a basic block and append it to the current BB list.
354  */
355
356 BasicBlock* Compiler::fgNewBasicBlock(BBjumpKinds jumpKind)
357 {
358     // This method must not be called after the exception table has been
359     // constructed, because it doesn't not provide support for patching
360     // the exception table.
361
362     noway_assert(compHndBBtabCount == 0);
363
364     BasicBlock* block;
365
366     /* Allocate the block descriptor */
367
368     block = bbNewBasicBlock(jumpKind);
369     noway_assert(block->bbJumpKind == jumpKind);
370
371     /* Append the block to the end of the global basic block list */
372
373     if (fgFirstBB)
374     {
375         fgLastBB->setNext(block);
376     }
377     else
378     {
379         fgFirstBB     = block;
380         block->bbPrev = nullptr;
381     }
382
383     fgLastBB = block;
384
385     return block;
386 }
387
388 /*****************************************************************************
389  *
390  *  Ensures that fgFirstBB is a scratch BasicBlock that we have added.
391  *  This can be used to add initialization code (without worrying
392  *  about other blocks jumping to it).
393  *
394  *  Callers have to be careful that they do not mess up the order of things
395  *  added to fgEnsureFirstBBisScratch in a way as to change semantics.
396  */
397
398 void Compiler::fgEnsureFirstBBisScratch()
399 {
400     // Have we already allocated a scratch block?
401
402     if (fgFirstBBisScratch())
403     {
404         return;
405     }
406
407     assert(fgFirstBBScratch == nullptr);
408
409     BasicBlock* block = bbNewBasicBlock(BBJ_NONE);
410
411     if (fgFirstBB != nullptr)
412     {
413         // If we have profile data the new block will inherit fgFirstBlock's weight
414         if (fgFirstBB->bbFlags & BBF_PROF_WEIGHT)
415         {
416             block->inheritWeight(fgFirstBB);
417         }
418         fgInsertBBbefore(fgFirstBB, block);
419     }
420     else
421     {
422         noway_assert(fgLastBB == nullptr);
423         fgFirstBB = block;
424         fgLastBB  = block;
425     }
426
427     noway_assert(fgLastBB != nullptr);
428
429     block->bbFlags |= (BBF_INTERNAL | BBF_IMPORTED);
430
431     fgFirstBBScratch = fgFirstBB;
432
433 #ifdef DEBUG
434     if (verbose)
435     {
436         printf("New scratch BB%02u\n", block->bbNum);
437     }
438 #endif
439 }
440
441 bool Compiler::fgFirstBBisScratch()
442 {
443     if (fgFirstBBScratch != nullptr)
444     {
445         assert(fgFirstBBScratch == fgFirstBB);
446         assert(fgFirstBBScratch->bbFlags & BBF_INTERNAL);
447         assert(fgFirstBBScratch->countOfInEdges() == 1);
448
449         // Normally, the first scratch block is a fall-through block. However, if the block after it was an empty
450         // BBJ_ALWAYS block, it might get removed, and the code that removes it will make the first scratch block
451         // a BBJ_ALWAYS block.
452         assert((fgFirstBBScratch->bbJumpKind == BBJ_NONE) || (fgFirstBBScratch->bbJumpKind == BBJ_ALWAYS));
453
454         return true;
455     }
456     else
457     {
458         return false;
459     }
460 }
461
462 bool Compiler::fgBBisScratch(BasicBlock* block)
463 {
464     return fgFirstBBisScratch() && (block == fgFirstBB);
465 }
466
467 #ifdef DEBUG
468 // Check to see if block contains a statement but don't spend more than a certain
469 // budget doing this per method compiled.
470 // If the budget is exceeded, return 'answerOnBoundExceeded' as the answer.
471 /* static */
472 bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, GenTree* stmt, bool answerOnBoundExceeded /*= true*/)
473 {
474     const __int64 maxLinks = 1000000000;
475
476     assert(stmt->gtOper == GT_STMT);
477
478     __int64* numTraversed = &JitTls::GetCompiler()->compNumStatementLinksTraversed;
479
480     if (*numTraversed > maxLinks)
481     {
482         return answerOnBoundExceeded;
483     }
484
485     GenTree* curr = block->firstStmt();
486     do
487     {
488         (*numTraversed)++;
489         if (curr == stmt)
490         {
491             break;
492         }
493         curr = curr->gtNext;
494     } while (curr);
495     return curr != nullptr;
496 }
497 #endif // DEBUG
498
499 //------------------------------------------------------------------------
500 // fgInsertStmtAtBeg: Insert the given tree or statement at the start of the given basic block.
501 //
502 // Arguments:
503 //    block     - The block into which 'stmt' will be inserted.
504 //    stmt      - The statement to be inserted.
505 //
506 // Return Value:
507 //    Returns the new (potentially) GT_STMT node.
508 //
509 // Notes:
510 //    If 'stmt' is not already a statement, a new statement is created from it.
511 //    We always insert phi statements at the beginning.
512 //    In other cases, if there are any phi assignments and/or an assignment of
513 //    the GT_CATCH_ARG, we insert after those.
514
515 GenTreePtr Compiler::fgInsertStmtAtBeg(BasicBlock* block, GenTreePtr stmt)
516 {
517     if (stmt->gtOper != GT_STMT)
518     {
519         stmt = gtNewStmt(stmt);
520     }
521
522     GenTreePtr list = block->firstStmt();
523
524     if (!stmt->IsPhiDefnStmt())
525     {
526         GenTreePtr insertBeforeStmt = block->FirstNonPhiDefOrCatchArgAsg();
527         if (insertBeforeStmt != nullptr)
528         {
529             return fgInsertStmtBefore(block, insertBeforeStmt, stmt);
530         }
531         else if (list != nullptr)
532         {
533             return fgInsertStmtAtEnd(block, stmt);
534         }
535         // Otherwise, we will simply insert at the beginning, below.
536     }
537
538     /* The new tree will now be the first one of the block */
539
540     block->bbTreeList = stmt;
541     stmt->gtNext      = list;
542
543     /* Are there any statements in the block? */
544
545     if (list)
546     {
547         GenTreePtr last;
548
549         /* There is at least one statement already */
550
551         last = list->gtPrev;
552         noway_assert(last && last->gtNext == nullptr);
553
554         /* Insert the statement in front of the first one */
555
556         list->gtPrev = stmt;
557         stmt->gtPrev = last;
558     }
559     else
560     {
561         /* The block was completely empty */
562
563         stmt->gtPrev = stmt;
564     }
565
566     return stmt;
567 }
568
569 /*****************************************************************************
570  *
571  *  Insert the given tree or statement at the end of the given basic block.
572  *  Returns the (potentially) new GT_STMT node.
573  *  If the block can be a conditional block, use fgInsertStmtNearEnd.
574  */
575
576 GenTreeStmt* Compiler::fgInsertStmtAtEnd(BasicBlock* block, GenTreePtr node)
577 {
578     GenTreePtr   list = block->firstStmt();
579     GenTreeStmt* stmt;
580
581     if (node->gtOper != GT_STMT)
582     {
583         stmt = gtNewStmt(node);
584     }
585     else
586     {
587         stmt = node->AsStmt();
588     }
589
590     assert(stmt->gtNext == nullptr); // We don't set it, and it needs to be this after the insert
591
592     if (list)
593     {
594         GenTreePtr last;
595
596         /* There is at least one statement already */
597
598         last = list->gtPrev;
599         noway_assert(last && last->gtNext == nullptr);
600
601         /* Append the statement after the last one */
602
603         last->gtNext = stmt;
604         stmt->gtPrev = last;
605         list->gtPrev = stmt;
606     }
607     else
608     {
609         /* The block is completely empty */
610
611         block->bbTreeList = stmt;
612         stmt->gtPrev      = stmt;
613     }
614
615     return stmt;
616 }
617
618 /*****************************************************************************
619  *
620  *  Insert the given tree or statement at the end of the given basic block, but before
621  *  the GT_JTRUE, if present.
622  *  Returns the (potentially) new GT_STMT node.
623  */
624
625 GenTreeStmt* Compiler::fgInsertStmtNearEnd(BasicBlock* block, GenTreePtr node)
626 {
627     GenTreeStmt* stmt;
628
629     // This routine can only be used when in tree order.
630     assert(fgOrder == FGOrderTree);
631
632     if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH) || (block->bbJumpKind == BBJ_RETURN))
633     {
634         if (node->gtOper != GT_STMT)
635         {
636             stmt = gtNewStmt(node);
637         }
638         else
639         {
640             stmt = node->AsStmt();
641         }
642
643         GenTreeStmt* first = block->firstStmt();
644         noway_assert(first);
645         GenTreeStmt* last = block->lastStmt();
646         noway_assert(last && last->gtNext == nullptr);
647         GenTreePtr after = last->gtPrev;
648
649 #if DEBUG
650         if (block->bbJumpKind == BBJ_COND)
651         {
652             noway_assert(last->gtStmtExpr->gtOper == GT_JTRUE);
653         }
654         else if (block->bbJumpKind == BBJ_RETURN)
655         {
656             noway_assert((last->gtStmtExpr->gtOper == GT_RETURN) || (last->gtStmtExpr->gtOper == GT_JMP) ||
657                          // BBJ_RETURN blocks in functions returning void do not get a GT_RETURN node if they
658                          // have a .tail prefix (even if canTailCall returns false for these calls)
659                          // code:Compiler::impImportBlockCode (search for the RET: label)
660                          // Ditto for real tail calls (all code after them has been removed)
661                          ((last->gtStmtExpr->gtOper == GT_CALL) &&
662                           ((info.compRetType == TYP_VOID) || last->gtStmtExpr->AsCall()->IsTailCall())));
663         }
664         else
665         {
666             noway_assert(block->bbJumpKind == BBJ_SWITCH);
667             noway_assert(last->gtStmtExpr->gtOper == GT_SWITCH);
668         }
669 #endif // DEBUG
670
671         /* Append 'stmt' before 'last' */
672
673         stmt->gtNext = last;
674         last->gtPrev = stmt;
675
676         if (first == last)
677         {
678             /* There is only one stmt in the block */
679
680             block->bbTreeList = stmt;
681             stmt->gtPrev      = last;
682         }
683         else
684         {
685             noway_assert(after && (after->gtNext == last));
686
687             /* Append 'stmt' after 'after' */
688
689             after->gtNext = stmt;
690             stmt->gtPrev  = after;
691         }
692
693         return stmt;
694     }
695     else
696     {
697         return fgInsertStmtAtEnd(block, node);
698     }
699 }
700
701 /*****************************************************************************
702  *
703  *  Insert the given statement "stmt" after GT_STMT node "insertionPoint".
704  *  Returns the newly inserted GT_STMT node.
705  *  Note that the gtPrev list of statement nodes is circular, but the gtNext list is not.
706  */
707
708 GenTreePtr Compiler::fgInsertStmtAfter(BasicBlock* block, GenTreePtr insertionPoint, GenTreePtr stmt)
709 {
710     assert(block->bbTreeList != nullptr);
711     noway_assert(insertionPoint->gtOper == GT_STMT);
712     noway_assert(stmt->gtOper == GT_STMT);
713     assert(fgBlockContainsStatementBounded(block, insertionPoint));
714     assert(!fgBlockContainsStatementBounded(block, stmt, false));
715
716     if (insertionPoint->gtNext == nullptr)
717     {
718         // Ok, we want to insert after the last statement of the block.
719         stmt->gtNext = nullptr;
720         stmt->gtPrev = insertionPoint;
721
722         insertionPoint->gtNext = stmt;
723
724         // Update the backward link of the first statement of the block
725         // to point to the new last statement.
726         assert(block->bbTreeList->gtPrev == insertionPoint);
727         block->bbTreeList->gtPrev = stmt;
728     }
729     else
730     {
731         stmt->gtNext = insertionPoint->gtNext;
732         stmt->gtPrev = insertionPoint;
733
734         insertionPoint->gtNext->gtPrev = stmt;
735         insertionPoint->gtNext         = stmt;
736     }
737
738     return stmt;
739 }
740
741 //  Insert the given tree or statement before GT_STMT node "insertionPoint".
742 //  Returns the newly inserted GT_STMT node.
743
744 GenTreePtr Compiler::fgInsertStmtBefore(BasicBlock* block, GenTreePtr insertionPoint, GenTreePtr stmt)
745 {
746     assert(block->bbTreeList != nullptr);
747     noway_assert(insertionPoint->gtOper == GT_STMT);
748     noway_assert(stmt->gtOper == GT_STMT);
749     assert(fgBlockContainsStatementBounded(block, insertionPoint));
750     assert(!fgBlockContainsStatementBounded(block, stmt, false));
751
752     if (insertionPoint == block->bbTreeList)
753     {
754         // We're inserting before the first statement in the block.
755         GenTreePtr list = block->bbTreeList;
756         GenTreePtr last = list->gtPrev;
757
758         stmt->gtNext = list;
759         stmt->gtPrev = last;
760
761         block->bbTreeList = stmt;
762         list->gtPrev      = stmt;
763     }
764     else
765     {
766         stmt->gtNext = insertionPoint;
767         stmt->gtPrev = insertionPoint->gtPrev;
768
769         insertionPoint->gtPrev->gtNext = stmt;
770         insertionPoint->gtPrev         = stmt;
771     }
772
773     return stmt;
774 }
775
776 /*****************************************************************************
777  *
778  *  Insert the list of statements stmtList after the stmtAfter in block.
779  *  Return the last statement stmtList.
780  */
781
782 GenTreePtr Compiler::fgInsertStmtListAfter(BasicBlock* block,     // the block where stmtAfter is in.
783                                            GenTreePtr  stmtAfter, // the statement where stmtList should be inserted
784                                                                   // after.
785                                            GenTreePtr stmtList)
786 {
787     // Currently we can handle when stmtAfter and stmtList are non-NULL. This makes everything easy.
788     noway_assert(stmtAfter && stmtAfter->gtOper == GT_STMT);
789     noway_assert(stmtList && stmtList->gtOper == GT_STMT);
790
791     GenTreePtr stmtLast = stmtList->gtPrev; // Last statement in a non-empty list, circular in the gtPrev list.
792     noway_assert(stmtLast);
793     noway_assert(stmtLast->gtNext == nullptr);
794
795     GenTreePtr stmtNext = stmtAfter->gtNext;
796
797     if (!stmtNext)
798     {
799         stmtAfter->gtNext         = stmtList;
800         stmtList->gtPrev          = stmtAfter;
801         block->bbTreeList->gtPrev = stmtLast;
802         goto _Done;
803     }
804
805     stmtAfter->gtNext = stmtList;
806     stmtList->gtPrev  = stmtAfter;
807
808     stmtLast->gtNext = stmtNext;
809     stmtNext->gtPrev = stmtLast;
810
811 _Done:
812
813     noway_assert(block->bbTreeList == nullptr || block->bbTreeList->gtPrev->gtNext == nullptr);
814
815     return stmtLast;
816 }
817
818 /*
819     Removes a block from the return block list
820 */
821 void Compiler::fgRemoveReturnBlock(BasicBlock* block)
822 {
823     if (fgReturnBlocks == nullptr)
824     {
825         return;
826     }
827
828     if (fgReturnBlocks->block == block)
829     {
830         // It's the 1st entry, assign new head of list.
831         fgReturnBlocks = fgReturnBlocks->next;
832         return;
833     }
834
835     for (BasicBlockList* retBlocks = fgReturnBlocks; retBlocks->next != nullptr; retBlocks = retBlocks->next)
836     {
837         if (retBlocks->next->block == block)
838         {
839             // Found it; splice it out.
840             retBlocks->next = retBlocks->next->next;
841             return;
842         }
843     }
844 }
845
846 //------------------------------------------------------------------------
847 // fgGetPredForBlock: Find and return the predecessor edge corresponding to a given predecessor block.
848 //
849 // Arguments:
850 //    block -- The block with the predecessor list to operate on.
851 //    blockPred -- The predecessor block to find in the predecessor list.
852 //
853 // Return Value:
854 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
855 //    then returns nullptr.
856 //
857 // Assumptions:
858 //    -- This only works on the full predecessor lists, not the cheap preds lists.
859
860 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred)
861 {
862     noway_assert(block);
863     noway_assert(blockPred);
864     assert(!fgCheapPredsValid);
865
866     flowList* pred;
867
868     for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
869     {
870         if (blockPred == pred->flBlock)
871         {
872             return pred;
873         }
874     }
875
876     return nullptr;
877 }
878
879 //------------------------------------------------------------------------
880 // fgGetPredForBlock: Find and return the predecessor edge corresponding to a given predecessor block.
881 // Also returns the address of the pointer that points to this edge, to make it possible to remove this edge from the
882 // predecessor list without doing another linear search over the edge list.
883 //
884 // Arguments:
885 //    block -- The block with the predecessor list to operate on.
886 //    blockPred -- The predecessor block to find in the predecessor list.
887 //    ptrToPred -- Out parameter: set to the address of the pointer that points to the returned predecessor edge.
888 //
889 // Return Value:
890 //    The flowList edge corresponding to "blockPred". If "blockPred" is not in the predecessor list of "block",
891 //    then returns nullptr.
892 //
893 // Assumptions:
894 //    -- This only works on the full predecessor lists, not the cheap preds lists.
895
896 flowList* Compiler::fgGetPredForBlock(BasicBlock* block, BasicBlock* blockPred, flowList*** ptrToPred)
897 {
898     assert(block);
899     assert(blockPred);
900     assert(ptrToPred);
901     assert(!fgCheapPredsValid);
902
903     flowList** predPrevAddr;
904     flowList*  pred;
905
906     for (predPrevAddr = &block->bbPreds, pred = *predPrevAddr; pred != nullptr;
907          predPrevAddr = &pred->flNext, pred = *predPrevAddr)
908     {
909         if (blockPred == pred->flBlock)
910         {
911             *ptrToPred = predPrevAddr;
912             return pred;
913         }
914     }
915
916     *ptrToPred = nullptr;
917     return nullptr;
918 }
919
920 //------------------------------------------------------------------------
921 // fgSpliceOutPred: Removes a predecessor edge for a block from the predecessor list.
922 //
923 // Arguments:
924 //    block -- The block with the predecessor list to operate on.
925 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
926 //
927 // Return Value:
928 //    The flowList edge that was removed.
929 //
930 // Assumptions:
931 //    -- "blockPred" must be a predecessor block of "block".
932 //    -- This simply splices out the flowList object. It doesn't update block ref counts, handle duplicate counts, etc.
933 //       For that, use fgRemoveRefPred() or fgRemoveAllRefPred().
934 //    -- This only works on the full predecessor lists, not the cheap preds lists.
935 //
936 // Notes:
937 //    -- This must walk the predecessor list to find the block in question. If the predecessor edge
938 //       is found using fgGetPredForBlock(), consider using the version that hands back the predecessor pointer
939 //       address instead, to avoid this search.
940 //    -- Marks fgModified = true, since the flow graph has changed.
941
942 flowList* Compiler::fgSpliceOutPred(BasicBlock* block, BasicBlock* blockPred)
943 {
944     assert(!fgCheapPredsValid);
945     noway_assert(block->bbPreds);
946
947     flowList* oldEdge = nullptr;
948
949     // Is this the first block in the pred list?
950     if (blockPred == block->bbPreds->flBlock)
951     {
952         oldEdge        = block->bbPreds;
953         block->bbPreds = block->bbPreds->flNext;
954     }
955     else
956     {
957         flowList* pred;
958         for (pred = block->bbPreds; (pred->flNext != nullptr) && (blockPred != pred->flNext->flBlock);
959              pred = pred->flNext)
960         {
961             // empty
962         }
963         oldEdge = pred->flNext;
964         if (oldEdge == nullptr)
965         {
966             noway_assert(!"Should always find the blockPred");
967         }
968         pred->flNext = pred->flNext->flNext;
969     }
970
971     // Any changes to the flow graph invalidate the dominator sets.
972     fgModified = true;
973
974     return oldEdge;
975 }
976
977 //------------------------------------------------------------------------
978 // fgAddRefPred: Increment block->bbRefs by one and add "blockPred" to the predecessor list of "block".
979 //
980 // Arguments:
981 //    block -- A block to operate on.
982 //    blockPred -- The predecessor block to add to the predecessor list.
983 //    oldEdge -- Optional (default: nullptr). If non-nullptr, and a new edge is created (and the dup count
984 //               of an existing edge is not just incremented), the edge weights are copied from this edge.
985 //    initializingPreds -- Optional (default: false). Only set to "true" when the initial preds computation is
986 //    happening.
987 //
988 // Return Value:
989 //    The flow edge representing the predecessor.
990 //
991 // Assumptions:
992 //    -- This only works on the full predecessor lists, not the cheap preds lists.
993 //
994 // Notes:
995 //    -- block->bbRefs is incremented by one to account for the reduction in incoming edges.
996 //    -- block->bbRefs is adjusted even if preds haven't been computed. If preds haven't been computed,
997 //       the preds themselves aren't touched.
998 //    -- fgModified is set if a new flow edge is created (but not if an existing flow edge dup count is incremented),
999 //       indicating that the flow graph shape has changed.
1000
1001 flowList* Compiler::fgAddRefPred(BasicBlock* block,
1002                                  BasicBlock* blockPred,
1003                                  flowList*   oldEdge /* = nullptr */,
1004                                  bool        initializingPreds /* = false */)
1005 {
1006     assert(block != nullptr);
1007     assert(blockPred != nullptr);
1008
1009     block->bbRefs++;
1010
1011     if (!fgComputePredsDone && !initializingPreds)
1012     {
1013         // Why is someone trying to update the preds list when the preds haven't been created?
1014         // Ignore them! This can happen when fgMorph is called before the preds list is created.
1015         return nullptr;
1016     }
1017
1018     assert(!fgCheapPredsValid);
1019
1020     flowList* flow = fgGetPredForBlock(block, blockPred);
1021
1022     if (flow)
1023     {
1024         noway_assert(flow->flDupCount > 0);
1025         flow->flDupCount++;
1026     }
1027     else
1028     {
1029         flow = new (this, CMK_FlowList) flowList();
1030
1031 #if MEASURE_BLOCK_SIZE
1032         genFlowNodeCnt += 1;
1033         genFlowNodeSize += sizeof(flowList);
1034 #endif // MEASURE_BLOCK_SIZE
1035
1036         // Any changes to the flow graph invalidate the dominator sets.
1037         fgModified = true;
1038
1039         // Keep the predecessor list in lowest to highest bbNum order
1040         // This allows us to discover the loops in optFindNaturalLoops
1041         //  from innermost to outermost.
1042
1043         // TODO-Throughput: This search is quadratic if you have many jumps
1044         // to the same target.   We need to either not bother sorting for
1045         // debuggable code, or sort in optFindNaturalLoops, or better, make
1046         // the code in optFindNaturalLoops not depend on order.
1047
1048         flowList** listp = &block->bbPreds;
1049         while (*listp && ((*listp)->flBlock->bbNum < blockPred->bbNum))
1050         {
1051             listp = &(*listp)->flNext;
1052         }
1053
1054         flow->flNext = *listp;
1055         *listp       = flow;
1056
1057         flow->flBlock    = blockPred;
1058         flow->flDupCount = 1;
1059
1060         if (fgHaveValidEdgeWeights)
1061         {
1062             // We are creating an edge from blockPred to block
1063             // and we have already computed the edge weights, so
1064             // we will try to setup this new edge with valid edge weights.
1065             //
1066             if (oldEdge != nullptr)
1067             {
1068                 // If our caller has given us the old edge weights
1069                 // then we will use them.
1070                 //
1071                 flow->flEdgeWeightMin = oldEdge->flEdgeWeightMin;
1072                 flow->flEdgeWeightMax = oldEdge->flEdgeWeightMax;
1073             }
1074             else
1075             {
1076                 // Set the max edge weight to be the minimum of block's or blockPred's weight
1077                 //
1078                 flow->flEdgeWeightMax = min(block->bbWeight, blockPred->bbWeight);
1079
1080                 // If we are inserting a conditional block the minimum weight is zero,
1081                 // otherwise it is the same as the edge's max weight.
1082                 if (blockPred->NumSucc() > 1)
1083                 {
1084                     flow->flEdgeWeightMin = BB_ZERO_WEIGHT;
1085                 }
1086                 else
1087                 {
1088                     flow->flEdgeWeightMin = flow->flEdgeWeightMax;
1089                 }
1090             }
1091         }
1092         else
1093         {
1094             flow->flEdgeWeightMin = BB_ZERO_WEIGHT;
1095             flow->flEdgeWeightMax = BB_MAX_WEIGHT;
1096         }
1097     }
1098     return flow;
1099 }
1100
1101 //------------------------------------------------------------------------
1102 // fgRemoveRefPred: Decrements the reference count of a predecessor edge from "blockPred" to "block",
1103 // removing the edge if it is no longer necessary.
1104 //
1105 // Arguments:
1106 //    block -- A block to operate on.
1107 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
1108 //
1109 // Return Value:
1110 //    If the flow edge was removed (the predecessor has a "dup count" of 1),
1111 //        returns the flow graph edge that was removed. This means "blockPred" is no longer a predecessor of "block".
1112 //    Otherwise, returns nullptr. This means that "blockPred" is still a predecessor of "block" (because "blockPred"
1113 //        is a switch with multiple cases jumping to "block", or a BBJ_COND with both conditional and fall-through
1114 //        paths leading to "block").
1115 //
1116 // Assumptions:
1117 //    -- "blockPred" must be a predecessor block of "block".
1118 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1119 //
1120 // Notes:
1121 //    -- block->bbRefs is decremented by one to account for the reduction in incoming edges.
1122 //    -- block->bbRefs is adjusted even if preds haven't been computed. If preds haven't been computed,
1123 //       the preds themselves aren't touched.
1124 //    -- fgModified is set if a flow edge is removed (but not if an existing flow edge dup count is decremented),
1125 //       indicating that the flow graph shape has changed.
1126
1127 flowList* Compiler::fgRemoveRefPred(BasicBlock* block, BasicBlock* blockPred)
1128 {
1129     noway_assert(block != nullptr);
1130     noway_assert(blockPred != nullptr);
1131
1132     noway_assert(block->countOfInEdges() > 0);
1133     block->bbRefs--;
1134
1135     // Do nothing if we haven't calculated the predecessor list yet.
1136     // Yes, this does happen.
1137     // For example the predecessor lists haven't been created yet when we do fgMorph.
1138     // But fgMorph calls fgFoldConditional, which in turn calls fgRemoveRefPred.
1139     if (!fgComputePredsDone)
1140     {
1141         return nullptr;
1142     }
1143
1144     assert(!fgCheapPredsValid);
1145
1146     flowList** ptrToPred;
1147     flowList*  pred = fgGetPredForBlock(block, blockPred, &ptrToPred);
1148     noway_assert(pred);
1149     noway_assert(pred->flDupCount > 0);
1150
1151     pred->flDupCount--;
1152
1153     if (pred->flDupCount == 0)
1154     {
1155         // Splice out the predecessor edge since it's no longer necessary.
1156         *ptrToPred = pred->flNext;
1157
1158         // Any changes to the flow graph invalidate the dominator sets.
1159         fgModified = true;
1160
1161         return pred;
1162     }
1163     else
1164     {
1165         return nullptr;
1166     }
1167 }
1168
1169 //------------------------------------------------------------------------
1170 // fgRemoveAllRefPreds: Removes a predecessor edge from one block to another, no matter what the "dup count" is.
1171 //
1172 // Arguments:
1173 //    block -- A block to operate on.
1174 //    blockPred -- The predecessor block to remove from the predecessor list. It must be a predecessor of "block".
1175 //
1176 // Return Value:
1177 //    Returns the flow graph edge that was removed. The dup count on the edge is no longer valid.
1178 //
1179 // Assumptions:
1180 //    -- "blockPred" must be a predecessor block of "block".
1181 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1182 //
1183 // Notes:
1184 //    block->bbRefs is decremented to account for the reduction in incoming edges.
1185
1186 flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, BasicBlock* blockPred)
1187 {
1188     assert(block != nullptr);
1189     assert(blockPred != nullptr);
1190     assert(fgComputePredsDone);
1191     assert(!fgCheapPredsValid);
1192     assert(block->countOfInEdges() > 0);
1193
1194     flowList** ptrToPred;
1195     flowList*  pred = fgGetPredForBlock(block, blockPred, &ptrToPred);
1196     assert(pred != nullptr);
1197     assert(pred->flDupCount > 0);
1198
1199     assert(block->bbRefs >= pred->flDupCount);
1200     block->bbRefs -= pred->flDupCount;
1201
1202     // Now splice out the predecessor edge.
1203     *ptrToPred = pred->flNext;
1204
1205     // Any changes to the flow graph invalidate the dominator sets.
1206     fgModified = true;
1207
1208     return pred;
1209 }
1210
1211 //------------------------------------------------------------------------
1212 // fgRemoveAllRefPreds: Remove a predecessor edge, given the address of a pointer to it in the
1213 // predecessor list, no matter what the "dup count" is.
1214 //
1215 // Arguments:
1216 //    block -- A block with the predecessor list to operate on.
1217 //    ptrToPred -- The address of a pointer to the predecessor to remove.
1218 //
1219 // Return Value:
1220 //    The removed predecessor edge. The dup count on the edge is no longer valid.
1221 //
1222 // Assumptions:
1223 //    -- The predecessor edge must be in the predecessor list for "block".
1224 //    -- This only works on the full predecessor lists, not the cheap preds lists.
1225 //
1226 // Notes:
1227 //    block->bbRefs is decremented by the dup count of the predecessor edge, to account for the reduction in incoming
1228 //    edges.
1229
1230 flowList* Compiler::fgRemoveAllRefPreds(BasicBlock* block, flowList** ptrToPred)
1231 {
1232     assert(block != nullptr);
1233     assert(ptrToPred != nullptr);
1234     assert(fgComputePredsDone);
1235     assert(!fgCheapPredsValid);
1236     assert(block->countOfInEdges() > 0);
1237
1238     flowList* pred = *ptrToPred;
1239     assert(pred != nullptr);
1240     assert(pred->flDupCount > 0);
1241
1242     assert(block->bbRefs >= pred->flDupCount);
1243     block->bbRefs -= pred->flDupCount;
1244
1245     // Now splice out the predecessor edge.
1246     *ptrToPred = pred->flNext;
1247
1248     // Any changes to the flow graph invalidate the dominator sets.
1249     fgModified = true;
1250
1251     return pred;
1252 }
1253
1254 /*
1255     Removes all the appearances of block as predecessor of others
1256 */
1257
1258 void Compiler::fgRemoveBlockAsPred(BasicBlock* block)
1259 {
1260     assert(!fgCheapPredsValid);
1261
1262     PREFIX_ASSUME(block != nullptr);
1263
1264     BasicBlock* bNext;
1265
1266     switch (block->bbJumpKind)
1267     {
1268         case BBJ_CALLFINALLY:
1269             if (!(block->bbFlags & BBF_RETLESS_CALL))
1270             {
1271                 assert(block->isBBCallAlwaysPair());
1272
1273                 /* The block after the BBJ_CALLFINALLY block is not reachable */
1274                 bNext = block->bbNext;
1275
1276                 /* bNext is an unreachable BBJ_ALWAYS block */
1277                 noway_assert(bNext->bbJumpKind == BBJ_ALWAYS);
1278
1279                 while (bNext->countOfInEdges() > 0)
1280                 {
1281                     fgRemoveRefPred(bNext, bNext->bbPreds->flBlock);
1282                 }
1283             }
1284
1285             __fallthrough;
1286
1287         case BBJ_COND:
1288         case BBJ_ALWAYS:
1289         case BBJ_EHCATCHRET:
1290
1291             /* Update the predecessor list for 'block->bbJumpDest' and 'block->bbNext' */
1292             fgRemoveRefPred(block->bbJumpDest, block);
1293
1294             if (block->bbJumpKind != BBJ_COND)
1295             {
1296                 break;
1297             }
1298
1299             /* If BBJ_COND fall through */
1300             __fallthrough;
1301
1302         case BBJ_NONE:
1303
1304             /* Update the predecessor list for 'block->bbNext' */
1305             fgRemoveRefPred(block->bbNext, block);
1306             break;
1307
1308         case BBJ_EHFILTERRET:
1309
1310             block->bbJumpDest->bbRefs++; // To compensate the bbRefs-- inside fgRemoveRefPred
1311             fgRemoveRefPred(block->bbJumpDest, block);
1312             break;
1313
1314         case BBJ_EHFINALLYRET:
1315         {
1316             /* Remove block as the predecessor of the bbNext of all
1317                BBJ_CALLFINALLY blocks calling this finally. No need
1318                to look for BBJ_CALLFINALLY for fault handlers. */
1319
1320             unsigned  hndIndex = block->getHndIndex();
1321             EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
1322
1323             if (ehDsc->HasFinallyHandler())
1324             {
1325                 BasicBlock* begBlk;
1326                 BasicBlock* endBlk;
1327                 ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
1328
1329                 BasicBlock* finBeg = ehDsc->ebdHndBeg;
1330
1331                 for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
1332                 {
1333                     if ((bcall->bbFlags & BBF_REMOVED) || bcall->bbJumpKind != BBJ_CALLFINALLY ||
1334                         bcall->bbJumpDest != finBeg)
1335                     {
1336                         continue;
1337                     }
1338
1339                     assert(bcall->isBBCallAlwaysPair());
1340                     fgRemoveRefPred(bcall->bbNext, block);
1341                 }
1342             }
1343         }
1344         break;
1345
1346         case BBJ_THROW:
1347         case BBJ_RETURN:
1348             break;
1349
1350         case BBJ_SWITCH:
1351         {
1352             unsigned     jumpCnt = block->bbJumpSwt->bbsCount;
1353             BasicBlock** jumpTab = block->bbJumpSwt->bbsDstTab;
1354
1355             do
1356             {
1357                 fgRemoveRefPred(*jumpTab, block);
1358             } while (++jumpTab, --jumpCnt);
1359
1360             break;
1361         }
1362
1363         default:
1364             noway_assert(!"Block doesn't have a valid bbJumpKind!!!!");
1365             break;
1366     }
1367 }
1368
1369 /*****************************************************************************
1370  * fgChangeSwitchBlock:
1371  *
1372  * We have a BBJ_SWITCH jump at 'oldSwitchBlock' and we want to move this
1373  * switch jump over to 'newSwitchBlock'.  All of the blocks that are jumped
1374  * to from jumpTab[] need to have their predecessor lists updated by removing
1375  * the 'oldSwitchBlock' and adding 'newSwitchBlock'.
1376  */
1377
1378 void Compiler::fgChangeSwitchBlock(BasicBlock* oldSwitchBlock, BasicBlock* newSwitchBlock)
1379 {
1380     noway_assert(oldSwitchBlock != nullptr);
1381     noway_assert(newSwitchBlock != nullptr);
1382     noway_assert(oldSwitchBlock->bbJumpKind == BBJ_SWITCH);
1383
1384     unsigned     jumpCnt = oldSwitchBlock->bbJumpSwt->bbsCount;
1385     BasicBlock** jumpTab = oldSwitchBlock->bbJumpSwt->bbsDstTab;
1386
1387     unsigned i;
1388
1389     // Walk the switch's jump table, updating the predecessor for each branch.
1390     for (i = 0; i < jumpCnt; i++)
1391     {
1392         BasicBlock* bJump = jumpTab[i];
1393         noway_assert(bJump != nullptr);
1394
1395         // Note that if there are duplicate branch targets in the switch jump table,
1396         // fgRemoveRefPred()/fgAddRefPred() will do the right thing: the second and
1397         // subsequent duplicates will simply subtract from and add to the duplicate
1398         // count (respectively).
1399
1400         //
1401         // Remove the old edge [oldSwitchBlock => bJump]
1402         //
1403         fgRemoveRefPred(bJump, oldSwitchBlock);
1404
1405         //
1406         // Create the new edge [newSwitchBlock => bJump]
1407         //
1408         fgAddRefPred(bJump, newSwitchBlock);
1409     }
1410
1411     if (m_switchDescMap != nullptr)
1412     {
1413         SwitchUniqueSuccSet uniqueSuccSet;
1414
1415         // If already computed and cached the unique descriptors for the old block, let's
1416         // update those for the new block.
1417         if (m_switchDescMap->Lookup(oldSwitchBlock, &uniqueSuccSet))
1418         {
1419             m_switchDescMap->Set(newSwitchBlock, uniqueSuccSet);
1420         }
1421         else
1422         {
1423             fgInvalidateSwitchDescMapEntry(newSwitchBlock);
1424         }
1425         fgInvalidateSwitchDescMapEntry(oldSwitchBlock);
1426     }
1427 }
1428
1429 /*****************************************************************************
1430  * fgReplaceSwitchJumpTarget:
1431  *
1432  * We have a BBJ_SWITCH at 'blockSwitch' and we want to replace all entries
1433  * in the jumpTab[] such that so that jumps that previously went to
1434  * 'oldTarget' now go to 'newTarget'.
1435  * We also must update the predecessor lists for 'oldTarget' and 'newPred'.
1436  */
1437
1438 void Compiler::fgReplaceSwitchJumpTarget(BasicBlock* blockSwitch, BasicBlock* newTarget, BasicBlock* oldTarget)
1439 {
1440     noway_assert(blockSwitch != nullptr);
1441     noway_assert(newTarget != nullptr);
1442     noway_assert(oldTarget != nullptr);
1443     noway_assert(blockSwitch->bbJumpKind == BBJ_SWITCH);
1444
1445     // For the jump targets values that match oldTarget of our BBJ_SWITCH
1446     // replace predecessor 'blockSwitch' with 'newTarget'
1447     //
1448
1449     unsigned     jumpCnt = blockSwitch->bbJumpSwt->bbsCount;
1450     BasicBlock** jumpTab = blockSwitch->bbJumpSwt->bbsDstTab;
1451
1452     unsigned i = 0;
1453
1454     // Walk the switch's jump table looking for blocks to update the preds for
1455     while (i < jumpCnt)
1456     {
1457         if (jumpTab[i] == oldTarget) // We will update when jumpTab[i] matches
1458         {
1459             // Remove the old edge [oldTarget from blockSwitch]
1460             //
1461             fgRemoveAllRefPreds(oldTarget, blockSwitch);
1462
1463             //
1464             // Change the jumpTab entry to branch to the new location
1465             //
1466             jumpTab[i] = newTarget;
1467
1468             //
1469             // Create the new edge [newTarget from blockSwitch]
1470             //
1471             flowList* newEdge = fgAddRefPred(newTarget, blockSwitch);
1472
1473             // Now set the correct value of newEdge->flDupCount
1474             // and replace any other jumps in jumpTab[] that go to oldTarget.
1475             //
1476             i++;
1477             while (i < jumpCnt)
1478             {
1479                 if (jumpTab[i] == oldTarget)
1480                 {
1481                     //
1482                     // We also must update this entry in the jumpTab
1483                     //
1484                     jumpTab[i] = newTarget;
1485                     newTarget->bbRefs++;
1486
1487                     //
1488                     // Increment the flDupCount
1489                     //
1490                     newEdge->flDupCount++;
1491                 }
1492                 i++; // Check the next entry in jumpTab[]
1493             }
1494
1495             // Maintain, if necessary, the set of unique targets of "block."
1496             UpdateSwitchTableTarget(blockSwitch, oldTarget, newTarget);
1497
1498             // Make sure the new target has the proper bits set for being a branch target.
1499             newTarget->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
1500
1501             return; // We have replaced the jumps to oldTarget with newTarget
1502         }
1503         i++; // Check the next entry in jumpTab[] for a match
1504     }
1505     noway_assert(!"Did not find oldTarget in jumpTab[]");
1506 }
1507
1508 //------------------------------------------------------------------------
1509 // Compiler::fgReplaceJumpTarget: For a given block, replace the target 'oldTarget' with 'newTarget'.
1510 //
1511 // Arguments:
1512 //    block     - the block in which a jump target will be replaced.
1513 //    newTarget - the new branch target of the block.
1514 //    oldTarget - the old branch target of the block.
1515 //
1516 // Notes:
1517 // 1. Only branches are changed: BBJ_ALWAYS, the non-fallthrough path of BBJ_COND, BBJ_SWITCH, etc.
1518 //    We ignore other block types.
1519 // 2. Only the first target found is updated. If there are multiple ways for a block
1520 //    to reach 'oldTarget' (e.g., multiple arms of a switch), only the first one found is changed.
1521 // 3. The predecessor lists are not changed.
1522 // 4. The switch table "unique successor" cache is invalidated.
1523 //
1524 // This function is most useful early, before the full predecessor lists have been computed.
1525 //
1526 void Compiler::fgReplaceJumpTarget(BasicBlock* block, BasicBlock* newTarget, BasicBlock* oldTarget)
1527 {
1528     assert(block != nullptr);
1529
1530     switch (block->bbJumpKind)
1531     {
1532         case BBJ_CALLFINALLY:
1533         case BBJ_COND:
1534         case BBJ_ALWAYS:
1535         case BBJ_EHCATCHRET:
1536         case BBJ_EHFILTERRET:
1537         case BBJ_LEAVE: // This function will be called before import, so we still have BBJ_LEAVE
1538
1539             if (block->bbJumpDest == oldTarget)
1540             {
1541                 block->bbJumpDest = newTarget;
1542             }
1543             break;
1544
1545         case BBJ_NONE:
1546         case BBJ_EHFINALLYRET:
1547         case BBJ_THROW:
1548         case BBJ_RETURN:
1549             break;
1550
1551         case BBJ_SWITCH:
1552             unsigned jumpCnt;
1553             jumpCnt = block->bbJumpSwt->bbsCount;
1554             BasicBlock** jumpTab;
1555             jumpTab = block->bbJumpSwt->bbsDstTab;
1556
1557             for (unsigned i = 0; i < jumpCnt; i++)
1558             {
1559                 if (jumpTab[i] == oldTarget)
1560                 {
1561                     jumpTab[i] = newTarget;
1562                     break;
1563                 }
1564             }
1565             break;
1566
1567         default:
1568             assert(!"Block doesn't have a valid bbJumpKind!!!!");
1569             unreached();
1570             break;
1571     }
1572 }
1573
1574 /*****************************************************************************
1575  * Updates the predecessor list for 'block' by replacing 'oldPred' with 'newPred'.
1576  * Note that a block can only appear once in the preds list (for normal preds, not
1577  * cheap preds): if a predecessor has multiple ways to get to this block, then
1578  * flDupCount will be >1, but the block will still appear exactly once. Thus, this
1579  * function assumes that all branches from the predecessor (practically, that all
1580  * switch cases that target this block) are changed to branch from the new predecessor,
1581  * with the same dup count.
1582  *
1583  * Note that the block bbRefs is not changed, since 'block' has the same number of
1584  * references as before, just from a different predecessor block.
1585  */
1586
1587 void Compiler::fgReplacePred(BasicBlock* block, BasicBlock* oldPred, BasicBlock* newPred)
1588 {
1589     noway_assert(block != nullptr);
1590     noway_assert(oldPred != nullptr);
1591     noway_assert(newPred != nullptr);
1592     assert(!fgCheapPredsValid);
1593
1594     flowList* pred;
1595
1596     for (pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
1597     {
1598         if (oldPred == pred->flBlock)
1599         {
1600             pred->flBlock = newPred;
1601             break;
1602         }
1603     }
1604 }
1605
1606 /*****************************************************************************
1607  *
1608  *  Returns true if block b1 dominates block b2.
1609  */
1610
1611 bool Compiler::fgDominate(BasicBlock* b1, BasicBlock* b2)
1612 {
1613     noway_assert(fgDomsComputed);
1614     assert(!fgCheapPredsValid);
1615
1616     //
1617     // If the fgModified flag is false then we made some modifications to
1618     // the flow graph, like adding a new block or changing a conditional branch
1619     // into an unconditional branch.
1620     //
1621     // We can continue to use the dominator and reachable information to
1622     // unmark loops as long as we haven't renumbered the blocks or we aren't
1623     // asking for information about a new block
1624     //
1625
1626     if (b2->bbNum > fgDomBBcount)
1627     {
1628         if (b1 == b2)
1629         {
1630             return true;
1631         }
1632
1633         for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext)
1634         {
1635             if (!fgDominate(b1, pred->flBlock))
1636             {
1637                 return false;
1638             }
1639         }
1640
1641         return b2->bbPreds != nullptr;
1642     }
1643
1644     if (b1->bbNum > fgDomBBcount)
1645     {
1646         // if b1 is a loop preheader and Succ is its only successor, then all predecessors of
1647         // Succ either are b1 itself or are dominated by Succ. Under these conditions, b1
1648         // dominates b2 if and only if Succ dominates b2 (or if b2 == b1, but we already tested
1649         // for this case)
1650         if (b1->bbFlags & BBF_LOOP_PREHEADER)
1651         {
1652             noway_assert(b1->bbFlags & BBF_INTERNAL);
1653             noway_assert(b1->bbJumpKind == BBJ_NONE);
1654             return fgDominate(b1->bbNext, b2);
1655         }
1656
1657         // unknown dominators; err on the safe side and return false
1658         return false;
1659     }
1660
1661     /* Check if b1 dominates b2 */
1662     unsigned numA = b1->bbNum;
1663     noway_assert(numA <= fgDomBBcount);
1664     unsigned numB = b2->bbNum;
1665     noway_assert(numB <= fgDomBBcount);
1666
1667     // What we want to ask here is basically if A is in the middle of the path from B to the root (the entry node)
1668     // in the dominator tree. Turns out that can be translated as:
1669     //
1670     //   A dom B <-> preorder(A) <= preorder(B) && postorder(A) >= postorder(B)
1671     //
1672     // where the equality holds when you ask if A dominates itself.
1673     bool treeDom =
1674         fgDomTreePreOrder[numA] <= fgDomTreePreOrder[numB] && fgDomTreePostOrder[numA] >= fgDomTreePostOrder[numB];
1675
1676     return treeDom;
1677 }
1678
1679 /*****************************************************************************
1680  *
1681  *  Returns true if block b1 can reach block b2.
1682  */
1683
1684 bool Compiler::fgReachable(BasicBlock* b1, BasicBlock* b2)
1685 {
1686     noway_assert(fgDomsComputed);
1687     assert(!fgCheapPredsValid);
1688
1689     //
1690     // If the fgModified flag is false then we made some modifications to
1691     // the flow graph, like adding a new block or changing a conditional branch
1692     // into an unconditional branch.
1693     //
1694     // We can continue to use the dominator and reachable information to
1695     // unmark loops as long as we haven't renumbered the blocks or we aren't
1696     // asking for information about a new block
1697     //
1698
1699     if (b2->bbNum > fgDomBBcount)
1700     {
1701         if (b1 == b2)
1702         {
1703             return true;
1704         }
1705
1706         for (flowList* pred = b2->bbPreds; pred != nullptr; pred = pred->flNext)
1707         {
1708             if (fgReachable(b1, pred->flBlock))
1709             {
1710                 return true;
1711             }
1712         }
1713
1714         return false;
1715     }
1716
1717     if (b1->bbNum > fgDomBBcount)
1718     {
1719         noway_assert(b1->bbJumpKind == BBJ_NONE || b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND);
1720
1721         if (b1->bbFallsThrough() && fgReachable(b1->bbNext, b2))
1722         {
1723             return true;
1724         }
1725
1726         if (b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND)
1727         {
1728             return fgReachable(b1->bbJumpDest, b2);
1729         }
1730
1731         return false;
1732     }
1733
1734     /* Check if b1 can reach b2 */
1735     assert(fgReachabilitySetsValid);
1736     assert(BasicBlockBitSetTraits::GetSize(this) == fgDomBBcount + 1);
1737     return BlockSetOps::IsMember(this, b2->bbReach, b1->bbNum);
1738 }
1739
1740 /*****************************************************************************
1741  *  Update changed flow graph information.
1742  *
1743  *  If the flow graph has changed, we need to recompute various information if we want to use
1744  *  it again.
1745  */
1746
1747 void Compiler::fgUpdateChangedFlowGraph()
1748 {
1749     // We need to clear this so we don't hit an assert calling fgRenumberBlocks().
1750     fgDomsComputed = false;
1751
1752     JITDUMP("\nRenumbering the basic blocks for fgUpdateChangeFlowGraph\n");
1753     fgRenumberBlocks();
1754
1755     fgComputePreds();
1756     fgComputeEnterBlocksSet();
1757     fgComputeReachabilitySets();
1758     fgComputeDoms();
1759 }
1760
1761 /*****************************************************************************
1762  *  Compute the bbReach sets.
1763  *
1764  *  This can be called to recompute the bbReach sets after the flow graph changes, such as when the
1765  *  number of BasicBlocks change (and thus, the BlockSet epoch changes).
1766  *
1767  *  Finally, this also sets the BBF_GC_SAFE_POINT flag on blocks.
1768  *
1769  *  Assumes the predecessor lists are correct.
1770  *
1771  *  TODO-Throughput: This algorithm consumes O(n^2) because we're using dense bitsets to
1772  *  represent reachability. While this yields O(1) time queries, it bloats the memory usage
1773  *  for large code.  We can do better if we try to approach reachability by
1774  *  computing the strongly connected components of the flow graph.  That way we only need
1775  *  linear memory to label every block with its SCC.
1776  */
1777
1778 void Compiler::fgComputeReachabilitySets()
1779 {
1780     assert(fgComputePredsDone);
1781     assert(!fgCheapPredsValid);
1782
1783 #ifdef DEBUG
1784     fgReachabilitySetsValid = false;
1785 #endif // DEBUG
1786
1787     BasicBlock* block;
1788
1789     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1790     {
1791         // Initialize the per-block bbReach sets. (Note that we can't just call BlockSetOps::ClearD()
1792         // when re-running this computation, because if the epoch changes, the size and representation of the
1793         // sets might change).
1794         block->bbReach = BlockSetOps::MakeEmpty(this);
1795
1796         /* Mark block as reaching itself */
1797         BlockSetOps::AddElemD(this, block->bbReach, block->bbNum);
1798     }
1799
1800     /* Find the reachable blocks */
1801     // Also, set BBF_GC_SAFE_POINT.
1802
1803     bool     change;
1804     BlockSet BLOCKSET_INIT_NOCOPY(newReach, BlockSetOps::MakeEmpty(this));
1805     do
1806     {
1807         change = false;
1808
1809         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1810         {
1811             BlockSetOps::Assign(this, newReach, block->bbReach);
1812
1813             bool predGcSafe = (block->bbPreds != nullptr); // Do all of our predecessor blocks have a GC safe bit?
1814
1815             for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
1816             {
1817                 BasicBlock* predBlock = pred->flBlock;
1818
1819                 /* Union the predecessor's reachability set into newReach */
1820                 BlockSetOps::UnionD(this, newReach, predBlock->bbReach);
1821
1822                 if (!(predBlock->bbFlags & BBF_GC_SAFE_POINT))
1823                 {
1824                     predGcSafe = false;
1825                 }
1826             }
1827
1828             if (predGcSafe)
1829             {
1830                 block->bbFlags |= BBF_GC_SAFE_POINT;
1831             }
1832
1833             if (!BlockSetOps::Equal(this, newReach, block->bbReach))
1834             {
1835                 BlockSetOps::Assign(this, block->bbReach, newReach);
1836                 change = true;
1837             }
1838         }
1839     } while (change);
1840
1841 #ifdef DEBUG
1842     if (verbose)
1843     {
1844         printf("\nAfter computing reachability sets:\n");
1845         fgDispReach();
1846     }
1847
1848     fgReachabilitySetsValid = true;
1849 #endif // DEBUG
1850 }
1851
1852 /*****************************************************************************
1853  *  Compute the entry blocks set.
1854  *
1855  *  Initialize fgEnterBlks to the set of blocks for which we don't have explicit control
1856  *  flow edges. These are the entry basic block and each of the EH handler blocks.
1857  *  For ARM, also include the BBJ_ALWAYS block of a BBJ_CALLFINALLY/BBJ_ALWAYS pair,
1858  *  to avoid creating "retless" calls, since we need the BBJ_ALWAYS for the purpose
1859  *  of unwinding, even if the call doesn't return (due to an explicit throw, for example).
1860  */
1861
1862 void Compiler::fgComputeEnterBlocksSet()
1863 {
1864 #ifdef DEBUG
1865     fgEnterBlksSetValid = false;
1866 #endif // DEBUG
1867
1868     fgEnterBlks = BlockSetOps::MakeEmpty(this);
1869
1870     /* Now set the entry basic block */
1871     BlockSetOps::AddElemD(this, fgEnterBlks, fgFirstBB->bbNum);
1872     assert(fgFirstBB->bbNum == 1);
1873
1874     if (compHndBBtabCount > 0)
1875     {
1876         /* Also 'or' in the handler basic blocks */
1877         EHblkDsc* HBtab;
1878         EHblkDsc* HBtabEnd;
1879         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
1880         {
1881             if (HBtab->HasFilter())
1882             {
1883                 BlockSetOps::AddElemD(this, fgEnterBlks, HBtab->ebdFilter->bbNum);
1884             }
1885             BlockSetOps::AddElemD(this, fgEnterBlks, HBtab->ebdHndBeg->bbNum);
1886         }
1887     }
1888
1889 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1890     // TODO-ARM-Cleanup: The ARM code here to prevent creating retless calls by adding the BBJ_ALWAYS
1891     // to the enter blocks is a bit of a compromise, because sometimes the blocks are already reachable,
1892     // and it messes up DFS ordering to have them marked as enter block. We should prevent the
1893     // creation of retless calls some other way.
1894     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
1895     {
1896         if (block->bbJumpKind == BBJ_CALLFINALLY)
1897         {
1898             assert(block->isBBCallAlwaysPair());
1899
1900             // Don't remove the BBJ_ALWAYS block that is only here for the unwinder. It might be dead
1901             // if the finally is no-return, so mark it as an entry point.
1902             BlockSetOps::AddElemD(this, fgEnterBlks, block->bbNext->bbNum);
1903         }
1904     }
1905 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1906
1907 #ifdef DEBUG
1908     if (verbose)
1909     {
1910         printf("Enter blocks: ");
1911         BLOCKSET_ITER_INIT(this, iter, fgEnterBlks, bbNum);
1912         while (iter.NextElem(this, &bbNum))
1913         {
1914             printf("BB%02u ", bbNum);
1915         }
1916         printf("\n");
1917     }
1918 #endif // DEBUG
1919
1920 #ifdef DEBUG
1921     fgEnterBlksSetValid = true;
1922 #endif // DEBUG
1923 }
1924
1925 /*****************************************************************************
1926  *  Remove unreachable blocks.
1927  *
1928  *  Return true if any unreachable blocks were removed.
1929  */
1930
1931 bool Compiler::fgRemoveUnreachableBlocks()
1932 {
1933     assert(!fgCheapPredsValid);
1934     assert(fgReachabilitySetsValid);
1935
1936     bool        hasLoops             = false;
1937     bool        hasUnreachableBlocks = false;
1938     BasicBlock* block;
1939
1940     /* Record unreachable blocks */
1941     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
1942     {
1943         /* Internal throw blocks are also reachable */
1944         if (fgIsThrowHlpBlk(block))
1945         {
1946             goto SKIP_BLOCK;
1947         }
1948         else if (block == genReturnBB)
1949         {
1950             // Don't remove statements for the genReturnBB block, as we might have special hookups there.
1951             // For example, <BUGNUM> in VSW 364383, </BUGNUM>
1952             // the profiler hookup needs to have the "void GT_RETURN" statement
1953             // to properly set the info.compProfilerCallback flag.
1954             goto SKIP_BLOCK;
1955         }
1956         else
1957         {
1958             // If any of the entry blocks can reach this block, then we skip it.
1959             if (!BlockSetOps::IsEmptyIntersection(this, fgEnterBlks, block->bbReach))
1960             {
1961                 goto SKIP_BLOCK;
1962             }
1963         }
1964
1965         // Remove all the code for the block
1966         fgUnreachableBlock(block);
1967
1968         // Make sure that the block was marked as removed */
1969         noway_assert(block->bbFlags & BBF_REMOVED);
1970
1971         // Some blocks mark the end of trys and catches
1972         // and can't be removed. We convert these into
1973         // empty blocks of type BBJ_THROW
1974
1975         if (block->bbFlags & BBF_DONT_REMOVE)
1976         {
1977             bool bIsBBCallAlwaysPair = block->isBBCallAlwaysPair();
1978
1979             /* Unmark the block as removed, */
1980             /* clear BBF_INTERNAL as well and set BBJ_IMPORTED */
1981
1982             block->bbFlags &= ~(BBF_REMOVED | BBF_INTERNAL | BBF_NEEDS_GCPOLL);
1983             block->bbFlags |= BBF_IMPORTED;
1984             block->bbJumpKind = BBJ_THROW;
1985             block->bbSetRunRarely();
1986
1987 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1988             // If this is a <BBJ_CALLFINALLY, BBJ_ALWAYS> pair, we have to clear BBF_FINALLY_TARGET flag on
1989             // the target node (of BBJ_ALWAYS) since BBJ_CALLFINALLY node is getting converted to a BBJ_THROW.
1990             if (bIsBBCallAlwaysPair)
1991             {
1992                 noway_assert(block->bbNext->bbJumpKind == BBJ_ALWAYS);
1993                 fgClearFinallyTargetBit(block->bbNext->bbJumpDest);
1994             }
1995 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
1996         }
1997         else
1998         {
1999             /* We have to call fgRemoveBlock next */
2000             hasUnreachableBlocks = true;
2001         }
2002         continue;
2003
2004     SKIP_BLOCK:;
2005
2006         // if (block->isRunRarely())
2007         //    continue;
2008         if (block->bbJumpKind == BBJ_RETURN)
2009         {
2010             continue;
2011         }
2012
2013         /* Set BBF_LOOP_HEAD if we have backwards branches to this block */
2014
2015         unsigned blockNum = block->bbNum;
2016         for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
2017         {
2018             BasicBlock* predBlock = pred->flBlock;
2019             if (blockNum <= predBlock->bbNum)
2020             {
2021                 if (predBlock->bbJumpKind == BBJ_CALLFINALLY)
2022                 {
2023                     continue;
2024                 }
2025
2026                 /* If block can reach predBlock then we have a loop head */
2027                 if (BlockSetOps::IsMember(this, predBlock->bbReach, blockNum))
2028                 {
2029                     hasLoops = true;
2030
2031                     /* Set the BBF_LOOP_HEAD flag */
2032                     block->bbFlags |= BBF_LOOP_HEAD;
2033                     break;
2034                 }
2035             }
2036         }
2037     }
2038
2039     fgHasLoops = hasLoops;
2040
2041     if (hasUnreachableBlocks)
2042     {
2043         // Now remove the unreachable blocks
2044         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2045         {
2046             //  If we mark the block with BBF_REMOVED then
2047             //  we need to call fgRemovedBlock() on it
2048
2049             if (block->bbFlags & BBF_REMOVED)
2050             {
2051                 fgRemoveBlock(block, true);
2052
2053                 // When we have a BBJ_CALLFINALLY, BBJ_ALWAYS pair; fgRemoveBlock will remove
2054                 // both blocks, so we must advance 1 extra place in the block list
2055                 //
2056                 if (block->isBBCallAlwaysPair())
2057                 {
2058                     block = block->bbNext;
2059                 }
2060             }
2061         }
2062     }
2063
2064     return hasUnreachableBlocks;
2065 }
2066
2067 /*****************************************************************************
2068  *
2069  *  Function called to compute the dominator and reachable sets.
2070  *
2071  *  Assumes the predecessor lists are computed and correct.
2072  */
2073
2074 void Compiler::fgComputeReachability()
2075 {
2076 #ifdef DEBUG
2077     if (verbose)
2078     {
2079         printf("*************** In fgComputeReachability\n");
2080     }
2081
2082     fgVerifyHandlerTab();
2083
2084     // Make sure that the predecessor lists are accurate
2085     assert(fgComputePredsDone);
2086     fgDebugCheckBBlist();
2087 #endif // DEBUG
2088
2089     /* Create a list of all BBJ_RETURN blocks. The head of the list is 'fgReturnBlocks'. */
2090     fgReturnBlocks = nullptr;
2091
2092     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
2093     {
2094         // If this is a BBJ_RETURN block, add it to our list of all BBJ_RETURN blocks. This list is only
2095         // used to find return blocks.
2096         if (block->bbJumpKind == BBJ_RETURN)
2097         {
2098             fgReturnBlocks = new (this, CMK_Reachability) BasicBlockList(block, fgReturnBlocks);
2099         }
2100     }
2101
2102     // Compute reachability and then delete blocks determined to be unreachable. If we delete blocks, we
2103     // need to loop, as that might have caused more blocks to become unreachable. This can happen in the
2104     // case where a call to a finally is unreachable and deleted (maybe the call to the finally is
2105     // preceded by a throw or an infinite loop), making the blocks following the finally unreachable.
2106     // However, all EH entry blocks are considered global entry blocks, causing the blocks following the
2107     // call to the finally to stay rooted, until a second round of reachability is done.
2108     // The dominator algorithm expects that all blocks can be reached from the fgEnterBlks set.
2109     unsigned passNum = 1;
2110     bool     changed;
2111     do
2112     {
2113         // Just to be paranoid, avoid infinite loops; fall back to minopts.
2114         if (passNum > 10)
2115         {
2116             noway_assert(!"Too many unreachable block removal loops");
2117         }
2118
2119         /* Walk the flow graph, reassign block numbers to keep them in ascending order */
2120         JITDUMP("\nRenumbering the basic blocks for fgComputeReachability pass #%u\n", passNum);
2121         passNum++;
2122         fgRenumberBlocks();
2123
2124         //
2125         // Compute fgEnterBlks
2126         //
2127
2128         fgComputeEnterBlocksSet();
2129
2130         //
2131         // Compute bbReach
2132         //
2133
2134         fgComputeReachabilitySets();
2135
2136         //
2137         // Use reachability information to delete unreachable blocks.
2138         // Also, determine if the flow graph has loops and set 'fgHasLoops' accordingly.
2139         // Set the BBF_LOOP_HEAD flag on the block target of backwards branches.
2140         //
2141
2142         changed = fgRemoveUnreachableBlocks();
2143
2144     } while (changed);
2145
2146 #ifdef DEBUG
2147     if (verbose)
2148     {
2149         printf("\nAfter computing reachability:\n");
2150         fgDispBasicBlocks(verboseTrees);
2151         printf("\n");
2152     }
2153
2154     fgVerifyHandlerTab();
2155     fgDebugCheckBBlist(true);
2156 #endif // DEBUG
2157
2158     //
2159     // Now, compute the dominators
2160     //
2161
2162     fgComputeDoms();
2163 }
2164
2165 /** In order to be able to compute dominance, we need to first get a DFS reverse post order sort on the basic flow graph
2166   * for the dominance algorithm to operate correctly.  The reason why we need the DFS sort is because
2167   * we will build the dominance sets using the partial order induced by the DFS sorting.  With this
2168   * precondition not holding true, the algorithm doesn't work properly.
2169   */
2170 void Compiler::fgDfsInvPostOrder()
2171 {
2172     // NOTE: This algorithm only pays attention to the actual blocks. It ignores the imaginary entry block.
2173
2174     // visited   :  Once we run the DFS post order sort recursive algorithm, we mark the nodes we visited to avoid
2175     //              backtracking.
2176     BlockSet BLOCKSET_INIT_NOCOPY(visited, BlockSetOps::MakeEmpty(this));
2177
2178     // We begin by figuring out which basic blocks don't have incoming edges and mark them as
2179     // start nodes.  Later on we run the recursive algorithm for each node that we
2180     // mark in this step.
2181     BlockSet_ValRet_T startNodes = fgDomFindStartNodes();
2182
2183     // Make sure fgEnterBlks are still there in startNodes, even if they participate in a loop (i.e., there is
2184     // an incoming edge into the block).
2185     assert(fgEnterBlksSetValid);
2186
2187 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2188     //
2189     //    BlockSetOps::UnionD(this, startNodes, fgEnterBlks);
2190     //
2191     // This causes problems on ARM, because we for BBJ_CALLFINALLY/BBJ_ALWAYS pairs, we add the BBJ_ALWAYS
2192     // to the enter blocks set to prevent flow graph optimizations from removing it and creating retless call finallies
2193     // (BBF_RETLESS_CALL). This leads to an incorrect DFS ordering in some cases, because we start the recursive walk
2194     // from the BBJ_ALWAYS, which is reachable from other blocks. A better solution would be to change ARM to avoid
2195     // creating retless calls in a different way, not by adding BBJ_ALWAYS to fgEnterBlks.
2196     //
2197     // So, let us make sure at least fgFirstBB is still there, even if it participates in a loop.
2198     BlockSetOps::AddElemD(this, startNodes, 1);
2199     assert(fgFirstBB->bbNum == 1);
2200 #else
2201     BlockSetOps::UnionD(this, startNodes, fgEnterBlks);
2202 #endif
2203
2204     assert(BlockSetOps::IsMember(this, startNodes, fgFirstBB->bbNum));
2205
2206     // Call the flowgraph DFS traversal helper.
2207     unsigned postIndex = 1;
2208     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
2209     {
2210         // If the block has no predecessors, and we haven't already visited it (because it's in fgEnterBlks but also
2211         // reachable from the first block), go ahead and traverse starting from this block.
2212         if (BlockSetOps::IsMember(this, startNodes, block->bbNum) &&
2213             !BlockSetOps::IsMember(this, visited, block->bbNum))
2214         {
2215             fgDfsInvPostOrderHelper(block, visited, &postIndex);
2216         }
2217     }
2218
2219     // After the DFS reverse postorder is completed, we must have visited all the basic blocks.
2220     noway_assert(postIndex == fgBBcount + 1);
2221     noway_assert(fgBBNumMax == fgBBcount);
2222
2223 #ifdef DEBUG
2224     if (0 && verbose)
2225     {
2226         printf("\nAfter doing a post order traversal of the BB graph, this is the ordering:\n");
2227         for (unsigned i = 1; i <= fgBBNumMax; ++i)
2228         {
2229             printf("%02u -> BB%02u\n", i, fgBBInvPostOrder[i]->bbNum);
2230         }
2231         printf("\n");
2232     }
2233 #endif // DEBUG
2234 }
2235
2236 BlockSet_ValRet_T Compiler::fgDomFindStartNodes()
2237 {
2238     unsigned    j;
2239     BasicBlock* block;
2240
2241     // startNodes ::  A set that represents which basic blocks in the flow graph don't have incoming edges.
2242     // We begin assuming everything is a start block and remove any block that is being referenced by another in its
2243     // successor list.
2244
2245     BlockSet BLOCKSET_INIT_NOCOPY(startNodes, BlockSetOps::MakeFull(this));
2246
2247     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2248     {
2249         unsigned cSucc = block->NumSucc(this);
2250         for (j = 0; j < cSucc; ++j)
2251         {
2252             BasicBlock* succ = block->GetSucc(j, this);
2253             BlockSetOps::RemoveElemD(this, startNodes, succ->bbNum);
2254         }
2255     }
2256
2257 #ifdef DEBUG
2258     if (verbose)
2259     {
2260         printf("\nDominator computation start blocks (those blocks with no incoming edges):\n");
2261         BLOCKSET_ITER_INIT(this, iter, startNodes, bbNum);
2262         while (iter.NextElem(this, &bbNum))
2263         {
2264             printf("BB%02u ", bbNum);
2265         }
2266         printf("\n");
2267     }
2268 #endif // DEBUG
2269
2270     return startNodes;
2271 }
2272
2273 //------------------------------------------------------------------------
2274 // fgDfsInvPostOrderHelper: Helper to assign post-order numbers to blocks.
2275 //
2276 // Arguments:
2277 //    block   - The starting entry block
2278 //    visited - The set of visited blocks
2279 //    count   - Pointer to the Dfs counter
2280 //
2281 // Notes:
2282 //    Compute a non-recursive DFS traversal of the flow graph using an
2283 //    evaluation stack to assign post-order numbers.
2284
2285 void Compiler::fgDfsInvPostOrderHelper(BasicBlock* block, BlockSet& visited, unsigned* count)
2286 {
2287     // Assume we haven't visited this node yet (callers ensure this).
2288     assert(!BlockSetOps::IsMember(this, visited, block->bbNum));
2289
2290     // Allocate a local stack to hold the DFS traversal actions necessary
2291     // to compute pre/post-ordering of the control flowgraph.
2292     ArrayStack<DfsBlockEntry> stack(this);
2293
2294     // Push the first block on the stack to seed the traversal.
2295     stack.Push(DfsBlockEntry(DSS_Pre, block));
2296     // Flag the node we just visited to avoid backtracking.
2297     BlockSetOps::AddElemD(this, visited, block->bbNum);
2298
2299     // The search is terminated once all the actions have been processed.
2300     while (stack.Height() != 0)
2301     {
2302         DfsBlockEntry current      = stack.Pop();
2303         BasicBlock*   currentBlock = current.dfsBlock;
2304
2305         if (current.dfsStackState == DSS_Pre)
2306         {
2307             // This is a pre-visit that corresponds to the first time the
2308             // node is encountered in the spanning tree and receives pre-order
2309             // numberings. By pushing the post-action on the stack here we
2310             // are guaranteed to only process it after all of its successors
2311             // pre and post actions are processed.
2312             stack.Push(DfsBlockEntry(DSS_Post, currentBlock));
2313
2314             unsigned cSucc = currentBlock->NumSucc(this);
2315             for (unsigned j = 0; j < cSucc; ++j)
2316             {
2317                 BasicBlock* succ = currentBlock->GetSucc(j, this);
2318
2319                 // If this is a node we haven't seen before, go ahead and process
2320                 if (!BlockSetOps::IsMember(this, visited, succ->bbNum))
2321                 {
2322                     // Push a pre-visit action for this successor onto the stack and
2323                     // mark it as visited in case this block has multiple successors
2324                     // to the same node (multi-graph).
2325                     stack.Push(DfsBlockEntry(DSS_Pre, succ));
2326                     BlockSetOps::AddElemD(this, visited, succ->bbNum);
2327                 }
2328             }
2329         }
2330         else
2331         {
2332             // This is a post-visit that corresponds to the last time the
2333             // node is visited in the spanning tree and only happens after
2334             // all descendents in the spanning tree have had pre and post
2335             // actions applied.
2336
2337             assert(current.dfsStackState == DSS_Post);
2338
2339             unsigned invCount = fgBBcount - *count + 1;
2340             assert(1 <= invCount && invCount <= fgBBNumMax);
2341             fgBBInvPostOrder[invCount] = currentBlock;
2342             currentBlock->bbDfsNum     = invCount;
2343             ++(*count);
2344         }
2345     }
2346 }
2347
2348 void Compiler::fgComputeDoms()
2349 {
2350     assert(!fgCheapPredsValid);
2351
2352 #ifdef DEBUG
2353     if (verbose)
2354     {
2355         printf("*************** In fgComputeDoms\n");
2356     }
2357
2358     fgVerifyHandlerTab();
2359
2360     // Make sure that the predecessor lists are accurate.
2361     // Also check that the blocks are properly, densely numbered (so calling fgRenumberBlocks is not necessary).
2362     fgDebugCheckBBlist(true);
2363
2364     // Assert things related to the BlockSet epoch.
2365     assert(fgBBcount == fgBBNumMax);
2366     assert(BasicBlockBitSetTraits::GetSize(this) == fgBBNumMax + 1);
2367 #endif // DEBUG
2368
2369     BlockSet BLOCKSET_INIT_NOCOPY(processedBlks, BlockSetOps::MakeEmpty(this));
2370
2371     fgBBInvPostOrder = new (this, CMK_DominatorMemory) BasicBlock*[fgBBNumMax + 1];
2372     memset(fgBBInvPostOrder, 0, sizeof(BasicBlock*) * (fgBBNumMax + 1));
2373
2374     fgDfsInvPostOrder();
2375     noway_assert(fgBBInvPostOrder[0] == nullptr);
2376
2377     // flRoot and bbRoot represent an imaginary unique entry point in the flow graph.
2378     // All the orphaned EH blocks and fgFirstBB will temporarily have its predecessors list
2379     // (with bbRoot as the only basic block in it) set as flRoot.
2380     // Later on, we clear their predecessors and let them to be nullptr again.
2381     // Since we number basic blocks starting at one, the imaginary entry block is conveniently numbered as zero.
2382     flowList   flRoot;
2383     BasicBlock bbRoot;
2384
2385     bbRoot.bbPreds  = nullptr;
2386     bbRoot.bbNum    = 0;
2387     bbRoot.bbIDom   = &bbRoot;
2388     bbRoot.bbDfsNum = 0;
2389     flRoot.flNext   = nullptr;
2390     flRoot.flBlock  = &bbRoot;
2391
2392     fgBBInvPostOrder[0] = &bbRoot;
2393
2394     // Mark both bbRoot and fgFirstBB processed
2395     BlockSetOps::AddElemD(this, processedBlks, 0); // bbRoot    == block #0
2396     BlockSetOps::AddElemD(this, processedBlks, 1); // fgFirstBB == block #1
2397     assert(fgFirstBB->bbNum == 1);
2398
2399     // Special case fgFirstBB to say its IDom is bbRoot.
2400     fgFirstBB->bbIDom = &bbRoot;
2401
2402     BasicBlock* block = nullptr;
2403
2404     for (block = fgFirstBB->bbNext; block != nullptr; block = block->bbNext)
2405     {
2406         // If any basic block has no predecessors then we flag it as processed and temporarily
2407         // mark its precedessor list to be flRoot.  This makes the flowgraph connected,
2408         // a precondition that is needed by the dominance algorithm to operate properly.
2409         if (block->bbPreds == nullptr)
2410         {
2411             block->bbPreds = &flRoot;
2412             block->bbIDom  = &bbRoot;
2413             BlockSetOps::AddElemD(this, processedBlks, block->bbNum);
2414         }
2415         else
2416         {
2417             block->bbIDom = nullptr;
2418         }
2419     }
2420
2421     // Mark the EH blocks as entry blocks and also flag them as processed.
2422     if (compHndBBtabCount > 0)
2423     {
2424         EHblkDsc* HBtab;
2425         EHblkDsc* HBtabEnd;
2426         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
2427         {
2428             if (HBtab->HasFilter())
2429             {
2430                 HBtab->ebdFilter->bbIDom = &bbRoot;
2431                 BlockSetOps::AddElemD(this, processedBlks, HBtab->ebdFilter->bbNum);
2432             }
2433             HBtab->ebdHndBeg->bbIDom = &bbRoot;
2434             BlockSetOps::AddElemD(this, processedBlks, HBtab->ebdHndBeg->bbNum);
2435         }
2436     }
2437
2438     // Now proceed to compute the immediate dominators for each basic block.
2439     bool changed = true;
2440     while (changed)
2441     {
2442         changed = false;
2443         for (unsigned i = 1; i <= fgBBNumMax;
2444              ++i) // Process each actual block; don't process the imaginary predecessor block.
2445         {
2446             flowList*   first   = nullptr;
2447             BasicBlock* newidom = nullptr;
2448             block               = fgBBInvPostOrder[i];
2449
2450             // If we have a block that has bbRoot as its bbIDom
2451             // it means we flag it as processed and as an entry block so
2452             // in this case we're all set.
2453             if (block->bbIDom == &bbRoot)
2454             {
2455                 continue;
2456             }
2457
2458             // Pick up the first processed predecesor of the current block.
2459             for (first = block->bbPreds; first != nullptr; first = first->flNext)
2460             {
2461                 if (BlockSetOps::IsMember(this, processedBlks, first->flBlock->bbNum))
2462                 {
2463                     break;
2464                 }
2465             }
2466             noway_assert(first != nullptr);
2467
2468             // We assume the first processed predecessor will be the
2469             // immediate dominator and then compute the forward flow analysis.
2470             newidom = first->flBlock;
2471             for (flowList* p = block->bbPreds; p != nullptr; p = p->flNext)
2472             {
2473                 if (p->flBlock == first->flBlock)
2474                 {
2475                     continue;
2476                 }
2477                 if (p->flBlock->bbIDom != nullptr)
2478                 {
2479                     // fgIntersectDom is basically the set intersection between
2480                     // the dominance sets of the new IDom and the current predecessor
2481                     // Since the nodes are ordered in DFS inverse post order and
2482                     // IDom induces a tree, fgIntersectDom actually computes
2483                     // the lowest common ancestor in the dominator tree.
2484                     newidom = fgIntersectDom(p->flBlock, newidom);
2485                 }
2486             }
2487
2488             // If the Immediate dominator changed, assign the new one
2489             // to the current working basic block.
2490             if (block->bbIDom != newidom)
2491             {
2492                 noway_assert(newidom != nullptr);
2493                 block->bbIDom = newidom;
2494                 changed       = true;
2495             }
2496             BlockSetOps::AddElemD(this, processedBlks, block->bbNum);
2497         }
2498     }
2499
2500     // As stated before, once we have computed immediate dominance we need to clear
2501     // all the basic blocks whose predecessor list was set to flRoot.  This
2502     // reverts that and leaves the blocks the same as before.
2503     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2504     {
2505         if (block->bbPreds == &flRoot)
2506         {
2507             block->bbPreds = nullptr;
2508         }
2509     }
2510
2511 #ifdef DEBUG
2512     if (verbose)
2513     {
2514         fgDispDoms();
2515     }
2516 #endif
2517
2518     fgBuildDomTree();
2519
2520     fgModified   = false;
2521     fgDomBBcount = fgBBcount;
2522     assert(fgBBcount == fgBBNumMax);
2523     assert(BasicBlockBitSetTraits::GetSize(this) == fgDomBBcount + 1);
2524
2525     fgDomsComputed = true;
2526 }
2527
2528 void Compiler::fgBuildDomTree()
2529 {
2530     unsigned    i;
2531     BasicBlock* block;
2532
2533 #ifdef DEBUG
2534     if (verbose)
2535     {
2536         printf("\nInside fgBuildDomTree\n");
2537     }
2538 #endif // DEBUG
2539
2540     // domTree :: The dominance tree represented using adjacency lists. We use BasicBlockList to represent edges.
2541     // Indexed by basic block number.
2542     unsigned         bbArraySize = fgBBNumMax + 1;
2543     BasicBlockList** domTree     = new (this, CMK_DominatorMemory) BasicBlockList*[bbArraySize];
2544
2545     fgDomTreePreOrder  = new (this, CMK_DominatorMemory) unsigned[bbArraySize];
2546     fgDomTreePostOrder = new (this, CMK_DominatorMemory) unsigned[bbArraySize];
2547
2548     // Initialize all the data structures.
2549     for (i = 0; i < bbArraySize; ++i)
2550     {
2551         domTree[i]           = nullptr;
2552         fgDomTreePreOrder[i] = fgDomTreePostOrder[i] = 0;
2553     }
2554
2555     // Build the dominance tree.
2556     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2557     {
2558         // If the immediate dominator is not the imaginary root (bbRoot)
2559         // we proceed to append this block to the children of the dominator node.
2560         if (block->bbIDom->bbNum != 0)
2561         {
2562             int bbNum      = block->bbIDom->bbNum;
2563             domTree[bbNum] = new (this, CMK_DominatorMemory) BasicBlockList(block, domTree[bbNum]);
2564         }
2565         else
2566         {
2567             // This means this block had bbRoot set as its IDom.  We clear it out
2568             // and convert the tree back to a forest.
2569             block->bbIDom = nullptr;
2570         }
2571     }
2572
2573 #ifdef DEBUG
2574     if (verbose)
2575     {
2576         printf("\nAfter computing the Dominance Tree:\n");
2577         fgDispDomTree(domTree);
2578     }
2579 #endif // DEBUG
2580
2581     // Get the bitset that represents the roots of the dominance tree.
2582     // Something to note here is that the dominance tree has been converted from a forest to a tree
2583     // by using the bbRoot trick on fgComputeDoms. The reason we have a forest instead of a real tree
2584     // is because we treat the EH blocks as entry nodes so the real dominance tree is not necessarily connected.
2585     BlockSet_ValRet_T domTreeEntryNodes = fgDomTreeEntryNodes(domTree);
2586
2587     // The preorder and postorder numbers.
2588     // We start from 1 to match the bbNum ordering.
2589     unsigned preNum  = 1;
2590     unsigned postNum = 1;
2591
2592     // There will be nodes in the dominance tree that will not be reachable:
2593     // the catch blocks that return since they don't have any predecessor.
2594     // For that matter we'll keep track of how many nodes we can
2595     // reach and assert at the end that we visited all of them.
2596     unsigned domTreeReachable = fgBBcount;
2597
2598     // Once we have the dominance tree computed, we need to traverse it
2599     // to get the preorder and postorder numbers for each node.  The purpose of
2600     // this is to achieve O(1) queries for of the form A dominates B.
2601     for (i = 1; i <= fgBBNumMax; ++i)
2602     {
2603         if (BlockSetOps::IsMember(this, domTreeEntryNodes, i))
2604         {
2605             if (domTree[i] == nullptr)
2606             {
2607                 // If this is an entry node but there's no children on this
2608                 // node, it means it's unreachable so we decrement the reachable
2609                 // counter.
2610                 --domTreeReachable;
2611             }
2612             else
2613             {
2614                 // Otherwise, we do a DFS traversal of the dominator tree.
2615                 fgTraverseDomTree(i, domTree, &preNum, &postNum);
2616             }
2617         }
2618     }
2619
2620     noway_assert(preNum == domTreeReachable + 1);
2621     noway_assert(postNum == domTreeReachable + 1);
2622
2623     // Once we have all the reachable nodes numbered, we proceed to
2624     // assign numbers to the non-reachable ones, just assign incrementing
2625     // values.  We must reach fgBBcount at the end.
2626
2627     for (i = 1; i <= fgBBNumMax; ++i)
2628     {
2629         if (BlockSetOps::IsMember(this, domTreeEntryNodes, i))
2630         {
2631             if (domTree[i] == nullptr)
2632             {
2633                 fgDomTreePreOrder[i]  = preNum++;
2634                 fgDomTreePostOrder[i] = postNum++;
2635             }
2636         }
2637     }
2638
2639     noway_assert(preNum == fgBBNumMax + 1);
2640     noway_assert(postNum == fgBBNumMax + 1);
2641     noway_assert(fgDomTreePreOrder[0] == 0);  // Unused first element
2642     noway_assert(fgDomTreePostOrder[0] == 0); // Unused first element
2643
2644 #ifdef DEBUG
2645     if (0 && verbose)
2646     {
2647         printf("\nAfter traversing the dominance tree:\n");
2648         printf("PreOrder:\n");
2649         for (i = 1; i <= fgBBNumMax; ++i)
2650         {
2651             printf("BB%02u : %02u\n", i, fgDomTreePreOrder[i]);
2652         }
2653         printf("PostOrder:\n");
2654         for (i = 1; i <= fgBBNumMax; ++i)
2655         {
2656             printf("BB%02u : %02u\n", i, fgDomTreePostOrder[i]);
2657         }
2658     }
2659 #endif // DEBUG
2660 }
2661
2662 BlockSet_ValRet_T Compiler::fgDomTreeEntryNodes(BasicBlockList** domTree)
2663 {
2664     // domTreeEntryNodes ::  Set that represents which basic blocks are roots of the dominator forest.
2665
2666     BlockSet BLOCKSET_INIT_NOCOPY(domTreeEntryNodes, BlockSetOps::MakeFull(this));
2667
2668     // First of all we need to find all the roots of the dominance forest.
2669
2670     for (unsigned i = 1; i <= fgBBNumMax; ++i)
2671     {
2672         for (BasicBlockList* current = domTree[i]; current != nullptr; current = current->next)
2673         {
2674             BlockSetOps::RemoveElemD(this, domTreeEntryNodes, current->block->bbNum);
2675         }
2676     }
2677
2678     return domTreeEntryNodes;
2679 }
2680
2681 #ifdef DEBUG
2682 void Compiler::fgDispDomTree(BasicBlockList** domTree)
2683 {
2684     for (unsigned i = 1; i <= fgBBNumMax; ++i)
2685     {
2686         if (domTree[i] != nullptr)
2687         {
2688             printf("BB%02u : ", i);
2689             for (BasicBlockList* current = domTree[i]; current != nullptr; current = current->next)
2690             {
2691                 assert(current->block);
2692                 printf("BB%02u ", current->block->bbNum);
2693             }
2694             printf("\n");
2695         }
2696     }
2697     printf("\n");
2698 }
2699 #endif // DEBUG
2700
2701 //------------------------------------------------------------------------
2702 // fgTraverseDomTree: Assign pre/post-order numbers to the dominator tree.
2703 //
2704 // Arguments:
2705 //    bbNum   - The basic block number of the starting block
2706 //    domTree - The dominator tree (as child block lists)
2707 //    preNum  - Pointer to the pre-number counter
2708 //    postNum - Pointer to the post-number counter
2709 //
2710 // Notes:
2711 //    Runs a non-recursive DFS traversal of the dominator tree using an
2712 //    evaluation stack to assign pre-order and post-order numbers.
2713 //    These numberings are used to provide constant time lookup for
2714 //    ancestor/descendent tests between pairs of nodes in the tree.
2715
2716 void Compiler::fgTraverseDomTree(unsigned bbNum, BasicBlockList** domTree, unsigned* preNum, unsigned* postNum)
2717 {
2718     noway_assert(bbNum <= fgBBNumMax);
2719
2720     // If the block preorder number is not zero it means we already visited
2721     // that node, so we skip it.
2722     if (fgDomTreePreOrder[bbNum] == 0)
2723     {
2724         // If this is the first time we visit this node, both preorder and postnumber
2725         // values must be zero.
2726         noway_assert(fgDomTreePostOrder[bbNum] == 0);
2727
2728         // Allocate a local stack to hold the Dfs traversal actions necessary
2729         // to compute pre/post-ordering of the dominator tree.
2730         ArrayStack<DfsNumEntry> stack(this);
2731
2732         // Push the first entry number on the stack to seed the traversal.
2733         stack.Push(DfsNumEntry(DSS_Pre, bbNum));
2734
2735         // The search is terminated once all the actions have been processed.
2736         while (stack.Height() != 0)
2737         {
2738             DfsNumEntry current    = stack.Pop();
2739             unsigned    currentNum = current.dfsNum;
2740
2741             if (current.dfsStackState == DSS_Pre)
2742             {
2743                 // This pre-visit action corresponds to the first time the
2744                 // node is encountered during the spanning traversal.
2745                 noway_assert(fgDomTreePreOrder[currentNum] == 0);
2746                 noway_assert(fgDomTreePostOrder[currentNum] == 0);
2747
2748                 // Assign the preorder number on the first visit.
2749                 fgDomTreePreOrder[currentNum] = (*preNum)++;
2750
2751                 // Push this nodes post-action on the stack such that all successors
2752                 // pre-order visits occur before this nodes post-action. We will assign
2753                 // its post-order numbers when we pop off the stack.
2754                 stack.Push(DfsNumEntry(DSS_Post, currentNum));
2755
2756                 // For each child in the dominator tree process its pre-actions.
2757                 for (BasicBlockList* child = domTree[currentNum]; child != nullptr; child = child->next)
2758                 {
2759                     unsigned childNum = child->block->bbNum;
2760
2761                     // This is a tree so never could have been visited
2762                     assert(fgDomTreePreOrder[childNum] == 0);
2763
2764                     // Push the successor in the dominator tree for pre-actions.
2765                     stack.Push(DfsNumEntry(DSS_Pre, childNum));
2766                 }
2767             }
2768             else
2769             {
2770                 // This post-visit action corresponds to the last time the node
2771                 // is encountered and only after all descendents in the spanning
2772                 // tree have had pre and post-order numbers assigned.
2773
2774                 assert(current.dfsStackState == DSS_Post);
2775                 assert(fgDomTreePreOrder[currentNum] != 0);
2776                 assert(fgDomTreePostOrder[currentNum] == 0);
2777
2778                 // Now assign this nodes post-order number.
2779                 fgDomTreePostOrder[currentNum] = (*postNum)++;
2780             }
2781         }
2782     }
2783 }
2784
2785 // This code finds the lowest common ancestor in the
2786 // dominator tree between two basic blocks. The LCA in the Dominance tree
2787 // represents the closest dominator between the two basic blocks. Used to
2788 // adjust the IDom value in fgComputDoms.
2789 BasicBlock* Compiler::fgIntersectDom(BasicBlock* a, BasicBlock* b)
2790 {
2791     BasicBlock* finger1 = a;
2792     BasicBlock* finger2 = b;
2793     while (finger1 != finger2)
2794     {
2795         while (finger1->bbDfsNum > finger2->bbDfsNum)
2796         {
2797             finger1 = finger1->bbIDom;
2798         }
2799         while (finger2->bbDfsNum > finger1->bbDfsNum)
2800         {
2801             finger2 = finger2->bbIDom;
2802         }
2803     }
2804     return finger1;
2805 }
2806
2807 // Return a BlockSet containing all the blocks that dominate 'block'.
2808 BlockSet_ValRet_T Compiler::fgGetDominatorSet(BasicBlock* block)
2809 {
2810     assert(block != nullptr);
2811
2812     BlockSet BLOCKSET_INIT_NOCOPY(domSet, BlockSetOps::MakeEmpty(this));
2813
2814     do
2815     {
2816         BlockSetOps::AddElemD(this, domSet, block->bbNum);
2817         if (block == block->bbIDom)
2818         {
2819             break; // We found a cycle in the IDom list, so we're done.
2820         }
2821         block = block->bbIDom;
2822     } while (block != nullptr);
2823
2824     return domSet;
2825 }
2826
2827 /*****************************************************************************
2828  *
2829  *  fgComputeCheapPreds: Function called to compute the BasicBlock::bbCheapPreds lists.
2830  *
2831  *  No other block data is changed (e.g., bbRefs, bbFlags).
2832  *
2833  *  The cheap preds lists are similar to the normal (bbPreds) predecessor lists, but are cheaper to
2834  *  compute and store, as follows:
2835  *  1. A flow edge is typed BasicBlockList, which only has a block pointer and 'next' pointer. It doesn't
2836  *     have weights or a dup count.
2837  *  2. The preds list for a block is not sorted by block number.
2838  *  3. The predecessors of the block following a BBJ_CALLFINALLY (the corresponding BBJ_ALWAYS,
2839  *     for normal, non-retless calls to the finally) are not computed.
2840  *  4. The cheap preds lists will contain duplicates if a single switch table has multiple branches
2841  *     to the same block. Thus, we don't spend the time looking for duplicates for every edge we insert.
2842  */
2843 void Compiler::fgComputeCheapPreds()
2844 {
2845     noway_assert(!fgComputePredsDone); // We can't do this if we've got the full preds.
2846     noway_assert(fgFirstBB != nullptr);
2847
2848     BasicBlock* block;
2849
2850 #ifdef DEBUG
2851     if (verbose)
2852     {
2853         printf("\n*************** In fgComputeCheapPreds()\n");
2854         fgDispBasicBlocks();
2855         printf("\n");
2856     }
2857 #endif // DEBUG
2858
2859     // Clear out the cheap preds lists.
2860     fgRemovePreds();
2861
2862     for (block = fgFirstBB; block != nullptr; block = block->bbNext)
2863     {
2864         switch (block->bbJumpKind)
2865         {
2866             case BBJ_COND:
2867                 fgAddCheapPred(block->bbJumpDest, block);
2868                 fgAddCheapPred(block->bbNext, block);
2869                 break;
2870
2871             case BBJ_CALLFINALLY:
2872             case BBJ_LEAVE: // If fgComputeCheapPreds is called before all blocks are imported, BBJ_LEAVE blocks are
2873                             // still in the BB list.
2874             case BBJ_ALWAYS:
2875             case BBJ_EHCATCHRET:
2876                 fgAddCheapPred(block->bbJumpDest, block);
2877                 break;
2878
2879             case BBJ_NONE:
2880                 fgAddCheapPred(block->bbNext, block);
2881                 break;
2882
2883             case BBJ_EHFILTERRET:
2884                 // Connect end of filter to catch handler.
2885                 // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
2886                 // fgComputeCheapPreds before fgImport on an ill-formed program; the problem will be detected in
2887                 // fgImport.
2888                 if (block->bbJumpDest != nullptr)
2889                 {
2890                     fgAddCheapPred(block->bbJumpDest, block);
2891                 }
2892                 break;
2893
2894             case BBJ_SWITCH:
2895                 unsigned jumpCnt;
2896                 jumpCnt = block->bbJumpSwt->bbsCount;
2897                 BasicBlock** jumpTab;
2898                 jumpTab = block->bbJumpSwt->bbsDstTab;
2899
2900                 do
2901                 {
2902                     fgAddCheapPred(*jumpTab, block);
2903                 } while (++jumpTab, --jumpCnt);
2904
2905                 break;
2906
2907             case BBJ_EHFINALLYRET: // It's expensive to compute the preds for this case, so we don't for the cheap
2908                                    // preds.
2909             case BBJ_THROW:
2910             case BBJ_RETURN:
2911                 break;
2912
2913             default:
2914                 noway_assert(!"Unexpected bbJumpKind");
2915                 break;
2916         }
2917     }
2918
2919     fgCheapPredsValid = true;
2920
2921 #ifdef DEBUG
2922     if (verbose)
2923     {
2924         printf("\n*************** After fgComputeCheapPreds()\n");
2925         fgDispBasicBlocks();
2926         printf("\n");
2927     }
2928 #endif
2929 }
2930
2931 /*****************************************************************************
2932  * Add 'blockPred' to the cheap predecessor list of 'block'.
2933  */
2934
2935 void Compiler::fgAddCheapPred(BasicBlock* block, BasicBlock* blockPred)
2936 {
2937     assert(!fgComputePredsDone);
2938     assert(block != nullptr);
2939     assert(blockPred != nullptr);
2940
2941     block->bbCheapPreds = new (this, CMK_FlowList) BasicBlockList(blockPred, block->bbCheapPreds);
2942
2943 #if MEASURE_BLOCK_SIZE
2944     genFlowNodeCnt += 1;
2945     genFlowNodeSize += sizeof(BasicBlockList);
2946 #endif // MEASURE_BLOCK_SIZE
2947 }
2948
2949 /*****************************************************************************
2950  * Remove 'blockPred' from the cheap predecessor list of 'block'.
2951  * If there are duplicate edges, only remove one of them.
2952  */
2953 void Compiler::fgRemoveCheapPred(BasicBlock* block, BasicBlock* blockPred)
2954 {
2955     assert(!fgComputePredsDone);
2956     assert(fgCheapPredsValid);
2957
2958     flowList* oldEdge = nullptr;
2959
2960     assert(block != nullptr);
2961     assert(blockPred != nullptr);
2962     assert(block->bbCheapPreds != nullptr);
2963
2964     /* Is this the first block in the pred list? */
2965     if (blockPred == block->bbCheapPreds->block)
2966     {
2967         block->bbCheapPreds = block->bbCheapPreds->next;
2968     }
2969     else
2970     {
2971         BasicBlockList* pred;
2972         for (pred = block->bbCheapPreds; pred->next != nullptr; pred = pred->next)
2973         {
2974             if (blockPred == pred->next->block)
2975             {
2976                 break;
2977             }
2978         }
2979         noway_assert(pred->next != nullptr); // we better have found it!
2980         pred->next = pred->next->next;       // splice it out
2981     }
2982 }
2983
2984 void Compiler::fgRemovePreds()
2985 {
2986     C_ASSERT(offsetof(BasicBlock, bbPreds) ==
2987              offsetof(BasicBlock, bbCheapPreds)); // bbPreds and bbCheapPreds are at the same place in a union,
2988     C_ASSERT(sizeof(((BasicBlock*)0)->bbPreds) ==
2989              sizeof(((BasicBlock*)0)->bbCheapPreds)); // and are the same size. So, this function removes both.
2990
2991     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
2992     {
2993         block->bbPreds = nullptr;
2994     }
2995     fgComputePredsDone = false;
2996     fgCheapPredsValid  = false;
2997 }
2998
2999 /*****************************************************************************
3000  *
3001  *  Function called to compute the bbPreds lists.
3002  */
3003 void Compiler::fgComputePreds()
3004 {
3005     noway_assert(fgFirstBB);
3006
3007     BasicBlock* block;
3008
3009 #ifdef DEBUG
3010     if (verbose)
3011     {
3012         printf("\n*************** In fgComputePreds()\n");
3013         fgDispBasicBlocks();
3014         printf("\n");
3015     }
3016 #endif // DEBUG
3017
3018     // reset the refs count for each basic block
3019
3020     for (block = fgFirstBB; block; block = block->bbNext)
3021     {
3022         block->bbRefs = 0;
3023     }
3024
3025     /* the first block is always reachable! */
3026     fgFirstBB->bbRefs = 1;
3027
3028     /* Treat the initial block as a jump target */
3029     fgFirstBB->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3030
3031     fgRemovePreds();
3032
3033     for (block = fgFirstBB; block; block = block->bbNext)
3034     {
3035         switch (block->bbJumpKind)
3036         {
3037             case BBJ_CALLFINALLY:
3038                 if (!(block->bbFlags & BBF_RETLESS_CALL))
3039                 {
3040                     assert(block->isBBCallAlwaysPair());
3041
3042                     /* Mark the next block as being a jump target,
3043                        since the call target will return there */
3044                     PREFIX_ASSUME(block->bbNext != nullptr);
3045                     block->bbNext->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
3046                 }
3047
3048                 __fallthrough;
3049
3050             case BBJ_LEAVE: // Sometimes fgComputePreds is called before all blocks are imported, so BBJ_LEAVE
3051                             // blocks are still in the BB list.
3052             case BBJ_COND:
3053             case BBJ_ALWAYS:
3054             case BBJ_EHCATCHRET:
3055
3056                 /* Mark the jump dest block as being a jump target */
3057                 block->bbJumpDest->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3058
3059                 fgAddRefPred(block->bbJumpDest, block, nullptr, true);
3060
3061                 /* Is the next block reachable? */
3062
3063                 if (block->bbJumpKind != BBJ_COND)
3064                 {
3065                     break;
3066                 }
3067
3068                 noway_assert(block->bbNext);
3069
3070                 /* Fall through, the next block is also reachable */
3071                 __fallthrough;
3072
3073             case BBJ_NONE:
3074
3075                 fgAddRefPred(block->bbNext, block, nullptr, true);
3076                 break;
3077
3078             case BBJ_EHFILTERRET:
3079
3080                 // Connect end of filter to catch handler.
3081                 // In a well-formed program, this cannot be null.  Tolerate here, so that we can call
3082                 // fgComputePreds before fgImport on an ill-formed program; the problem will be detected in fgImport.
3083                 if (block->bbJumpDest != nullptr)
3084                 {
3085                     fgAddRefPred(block->bbJumpDest, block, nullptr, true);
3086                 }
3087                 break;
3088
3089             case BBJ_EHFINALLYRET:
3090             {
3091                 /* Connect the end of the finally to the successor of
3092                   the call to this finally */
3093
3094                 if (!block->hasHndIndex())
3095                 {
3096                     NO_WAY("endfinally outside a finally/fault block.");
3097                 }
3098
3099                 unsigned  hndIndex = block->getHndIndex();
3100                 EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
3101
3102                 if (!ehDsc->HasFinallyOrFaultHandler())
3103                 {
3104                     NO_WAY("endfinally outside a finally/fault block.");
3105                 }
3106
3107                 if (ehDsc->HasFinallyHandler())
3108                 {
3109                     // Find all BBJ_CALLFINALLY that branched to this finally handler.
3110                     BasicBlock* begBlk;
3111                     BasicBlock* endBlk;
3112                     ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
3113
3114                     BasicBlock* finBeg = ehDsc->ebdHndBeg;
3115                     for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
3116                     {
3117                         if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
3118                         {
3119                             continue;
3120                         }
3121
3122                         noway_assert(bcall->isBBCallAlwaysPair());
3123                         fgAddRefPred(bcall->bbNext, block, nullptr, true);
3124                     }
3125                 }
3126             }
3127             break;
3128
3129             case BBJ_THROW:
3130             case BBJ_RETURN:
3131                 break;
3132
3133             case BBJ_SWITCH:
3134                 unsigned jumpCnt;
3135                 jumpCnt = block->bbJumpSwt->bbsCount;
3136                 BasicBlock** jumpTab;
3137                 jumpTab = block->bbJumpSwt->bbsDstTab;
3138
3139                 do
3140                 {
3141                     /* Mark the target block as being a jump target */
3142                     (*jumpTab)->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3143
3144                     fgAddRefPred(*jumpTab, block, nullptr, true);
3145                 } while (++jumpTab, --jumpCnt);
3146
3147                 break;
3148
3149             default:
3150                 noway_assert(!"Unexpected bbJumpKind");
3151                 break;
3152         }
3153     }
3154
3155     for (unsigned EHnum = 0; EHnum < compHndBBtabCount; EHnum++)
3156     {
3157         EHblkDsc* ehDsc = ehGetDsc(EHnum);
3158
3159         if (ehDsc->HasFilter())
3160         {
3161             ehDsc->ebdFilter->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3162         }
3163
3164         ehDsc->ebdHndBeg->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
3165     }
3166
3167     fgModified         = false;
3168     fgComputePredsDone = true;
3169
3170 #ifdef DEBUG
3171     if (verbose)
3172     {
3173         printf("\n*************** After fgComputePreds()\n");
3174         fgDispBasicBlocks();
3175         printf("\n");
3176     }
3177 #endif
3178 }
3179
3180 unsigned Compiler::fgNSuccsOfFinallyRet(BasicBlock* block)
3181 {
3182     BasicBlock* bb;
3183     unsigned    res;
3184     fgSuccOfFinallyRetWork(block, ~0, &bb, &res);
3185     return res;
3186 }
3187
3188 BasicBlock* Compiler::fgSuccOfFinallyRet(BasicBlock* block, unsigned i)
3189 {
3190     BasicBlock* bb;
3191     unsigned    res;
3192     fgSuccOfFinallyRetWork(block, i, &bb, &res);
3193     return bb;
3194 }
3195
3196 void Compiler::fgSuccOfFinallyRetWork(BasicBlock* block, unsigned i, BasicBlock** bres, unsigned* nres)
3197 {
3198     assert(block->hasHndIndex()); // Otherwise, endfinally outside a finally/fault block?
3199
3200     unsigned  hndIndex = block->getHndIndex();
3201     EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
3202
3203     assert(ehDsc->HasFinallyOrFaultHandler()); // Otherwise, endfinally outside a finally/fault block.
3204
3205     *bres            = nullptr;
3206     unsigned succNum = 0;
3207
3208     if (ehDsc->HasFinallyHandler())
3209     {
3210         BasicBlock* begBlk;
3211         BasicBlock* endBlk;
3212         ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
3213
3214         BasicBlock* finBeg = ehDsc->ebdHndBeg;
3215
3216         for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
3217         {
3218             if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
3219             {
3220                 continue;
3221             }
3222
3223             assert(bcall->isBBCallAlwaysPair());
3224
3225             if (succNum == i)
3226             {
3227                 *bres = bcall->bbNext;
3228                 return;
3229             }
3230             succNum++;
3231         }
3232     }
3233     assert(i == ~0u || ehDsc->HasFaultHandler()); // Should reach here only for fault blocks.
3234     if (i == ~0u)
3235     {
3236         *nres = succNum;
3237     }
3238 }
3239
3240 Compiler::SwitchUniqueSuccSet Compiler::GetDescriptorForSwitch(BasicBlock* switchBlk)
3241 {
3242     assert(switchBlk->bbJumpKind == BBJ_SWITCH);
3243     BlockToSwitchDescMap* switchMap = GetSwitchDescMap();
3244     SwitchUniqueSuccSet   res;
3245     if (switchMap->Lookup(switchBlk, &res))
3246     {
3247         return res;
3248     }
3249     else
3250     {
3251         // We must compute the descriptor. Find which are dups, by creating a bit set with the unique successors.
3252         // We create a temporary bitset of blocks to compute the unique set of successor blocks,
3253         // since adding a block's number twice leaves just one "copy" in the bitset. Note that
3254         // we specifically don't use the BlockSet type, because doing so would require making a
3255         // call to EnsureBasicBlockEpoch() to make sure the epoch is up-to-date. However, that
3256         // can create a new epoch, thus invalidating all existing BlockSet objects, such as
3257         // reachability information stored in the blocks. To avoid that, we just use a local BitVec.
3258
3259         BitVecTraits blockVecTraits(fgBBNumMax + 1, this);
3260         BitVec       BITVEC_INIT_NOCOPY(uniqueSuccBlocks, BitVecOps::MakeEmpty(&blockVecTraits));
3261         BasicBlock** jumpTable = switchBlk->bbJumpSwt->bbsDstTab;
3262         unsigned     jumpCount = switchBlk->bbJumpSwt->bbsCount;
3263         for (unsigned i = 0; i < jumpCount; i++)
3264         {
3265             BasicBlock* targ = jumpTable[i];
3266             BitVecOps::AddElemD(&blockVecTraits, uniqueSuccBlocks, targ->bbNum);
3267         }
3268         // Now we have a set of unique successors.
3269         unsigned numNonDups = BitVecOps::Count(&blockVecTraits, uniqueSuccBlocks);
3270
3271         typedef BasicBlock* BasicBlockPtr;
3272         BasicBlockPtr*      nonDups = new (getAllocator()) BasicBlockPtr[numNonDups];
3273
3274         unsigned nonDupInd = 0;
3275         // At this point, all unique targets are in "uniqueSuccBlocks".  As we encounter each,
3276         // add to nonDups, remove from "uniqueSuccBlocks".
3277         for (unsigned i = 0; i < jumpCount; i++)
3278         {
3279             BasicBlock* targ = jumpTable[i];
3280             if (BitVecOps::IsMember(&blockVecTraits, uniqueSuccBlocks, targ->bbNum))
3281             {
3282                 nonDups[nonDupInd] = targ;
3283                 nonDupInd++;
3284                 BitVecOps::RemoveElemD(&blockVecTraits, uniqueSuccBlocks, targ->bbNum);
3285             }
3286         }
3287
3288         assert(nonDupInd == numNonDups);
3289         assert(BitVecOps::Count(&blockVecTraits, uniqueSuccBlocks) == 0);
3290         res.numDistinctSuccs = numNonDups;
3291         res.nonDuplicates    = nonDups;
3292         switchMap->Set(switchBlk, res);
3293         return res;
3294     }
3295 }
3296
3297 void Compiler::SwitchUniqueSuccSet::UpdateTarget(IAllocator* alloc,
3298                                                  BasicBlock* switchBlk,
3299                                                  BasicBlock* from,
3300                                                  BasicBlock* to)
3301 {
3302     assert(switchBlk->bbJumpKind == BBJ_SWITCH); // Precondition.
3303     unsigned     jmpTabCnt = switchBlk->bbJumpSwt->bbsCount;
3304     BasicBlock** jmpTab    = switchBlk->bbJumpSwt->bbsDstTab;
3305
3306     // Is "from" still in the switch table (because it had more than one entry before?)
3307     bool fromStillPresent = false;
3308     for (unsigned i = 0; i < jmpTabCnt; i++)
3309     {
3310         if (jmpTab[i] == from)
3311         {
3312             fromStillPresent = true;
3313             break;
3314         }
3315     }
3316
3317     // Is "to" already in "this"?
3318     bool toAlreadyPresent = false;
3319     for (unsigned i = 0; i < numDistinctSuccs; i++)
3320     {
3321         if (nonDuplicates[i] == to)
3322         {
3323             toAlreadyPresent = true;
3324             break;
3325         }
3326     }
3327
3328     // Four cases:
3329     //   If "from" is still present, and "to" is already present, do nothing
3330     //   If "from" is still present, and "to" is not, must reallocate to add an entry.
3331     //   If "from" is not still present, and "to" is not present, write "to" where "from" was.
3332     //   If "from" is not still present, but "to" is present, remove "from".
3333     if (fromStillPresent && toAlreadyPresent)
3334     {
3335         return;
3336     }
3337     else if (fromStillPresent && !toAlreadyPresent)
3338     {
3339         // reallocate to add an entry
3340         typedef BasicBlock* BasicBlockPtr;
3341         BasicBlockPtr*      newNonDups = new (alloc) BasicBlockPtr[numDistinctSuccs + 1];
3342         memcpy(newNonDups, nonDuplicates, numDistinctSuccs * sizeof(BasicBlock*));
3343         newNonDups[numDistinctSuccs] = to;
3344         numDistinctSuccs++;
3345         nonDuplicates = newNonDups;
3346     }
3347     else if (!fromStillPresent && !toAlreadyPresent)
3348     {
3349 #ifdef DEBUG
3350         // write "to" where "from" was
3351         bool foundFrom = false;
3352 #endif // DEBUG
3353         for (unsigned i = 0; i < numDistinctSuccs; i++)
3354         {
3355             if (nonDuplicates[i] == from)
3356             {
3357                 nonDuplicates[i] = to;
3358 #ifdef DEBUG
3359                 foundFrom = true;
3360 #endif // DEBUG
3361                 break;
3362             }
3363         }
3364         assert(foundFrom);
3365     }
3366     else
3367     {
3368         assert(!fromStillPresent && toAlreadyPresent);
3369 #ifdef DEBUG
3370         // remove "from".
3371         bool foundFrom = false;
3372 #endif // DEBUG
3373         for (unsigned i = 0; i < numDistinctSuccs; i++)
3374         {
3375             if (nonDuplicates[i] == from)
3376             {
3377                 nonDuplicates[i] = nonDuplicates[numDistinctSuccs - 1];
3378                 numDistinctSuccs--;
3379 #ifdef DEBUG
3380                 foundFrom = true;
3381 #endif // DEBUG
3382                 break;
3383             }
3384         }
3385         assert(foundFrom);
3386     }
3387 }
3388
3389 /*****************************************************************************
3390  *
3391  *  Simple utility function to remove an entry for a block in the switch desc
3392  *  map. So it can be called from other phases.
3393  *
3394  */
3395 void Compiler::fgInvalidateSwitchDescMapEntry(BasicBlock* block)
3396 {
3397     // Check if map has no entries yet.
3398     if (m_switchDescMap != nullptr)
3399     {
3400         m_switchDescMap->Remove(block);
3401     }
3402 }
3403
3404 void Compiler::UpdateSwitchTableTarget(BasicBlock* switchBlk, BasicBlock* from, BasicBlock* to)
3405 {
3406     if (m_switchDescMap == nullptr)
3407     {
3408         return; // No mappings, nothing to do.
3409     }
3410
3411     // Otherwise...
3412     BlockToSwitchDescMap* switchMap = GetSwitchDescMap();
3413     SwitchUniqueSuccSet*  res       = switchMap->LookupPointer(switchBlk);
3414     if (res != nullptr)
3415     {
3416         // If no result, nothing to do. Otherwise, update it.
3417         res->UpdateTarget(getAllocator(), switchBlk, from, to);
3418     }
3419 }
3420
3421 /*****************************************************************************
3422  *  For a block that is in a handler region, find the first block of the most-nested
3423  *  handler containing the block.
3424  */
3425 BasicBlock* Compiler::fgFirstBlockOfHandler(BasicBlock* block)
3426 {
3427     assert(block->hasHndIndex());
3428     return ehGetDsc(block->getHndIndex())->ebdHndBeg;
3429 }
3430
3431 /*****************************************************************************
3432  *
3433  *  Function called to find back edges and return blocks and mark them as needing GC Polls.  This marks all
3434  *  blocks.
3435  */
3436 void Compiler::fgMarkGCPollBlocks()
3437 {
3438     if (GCPOLL_NONE == opts.compGCPollType)
3439     {
3440         return;
3441     }
3442
3443 #ifdef DEBUG
3444     /* Check that the flowgraph data (bbNum, bbRefs, bbPreds) is up-to-date */
3445     fgDebugCheckBBlist();
3446 #endif
3447
3448     BasicBlock* block;
3449
3450     // Return blocks always need GC polls.  In addition, all back edges (including those from switch
3451     // statements) need GC polls.  The poll is on the block with the outgoing back edge (or ret), rather than
3452     // on the destination or on the edge itself.
3453     for (block = fgFirstBB; block; block = block->bbNext)
3454     {
3455         bool blockNeedsPoll = false;
3456         switch (block->bbJumpKind)
3457         {
3458             case BBJ_COND:
3459             case BBJ_ALWAYS:
3460                 blockNeedsPoll = (block->bbJumpDest->bbNum <= block->bbNum);
3461                 break;
3462
3463             case BBJ_RETURN:
3464                 blockNeedsPoll = true;
3465                 break;
3466
3467             case BBJ_SWITCH:
3468                 unsigned jumpCnt;
3469                 jumpCnt = block->bbJumpSwt->bbsCount;
3470                 BasicBlock** jumpTab;
3471                 jumpTab = block->bbJumpSwt->bbsDstTab;
3472
3473                 do
3474                 {
3475                     if ((*jumpTab)->bbNum <= block->bbNum)
3476                     {
3477                         blockNeedsPoll = true;
3478                         break;
3479                     }
3480                 } while (++jumpTab, --jumpCnt);
3481                 break;
3482
3483             default:
3484                 break;
3485         }
3486
3487         if (blockNeedsPoll)
3488         {
3489             block->bbFlags |= BBF_NEEDS_GCPOLL;
3490         }
3491     }
3492 }
3493
3494 void Compiler::fgInitBlockVarSets()
3495 {
3496     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
3497     {
3498         block->InitVarSets(this);
3499     }
3500
3501     // QMarks are much like blocks, and need their VarSets initialized.
3502     assert(!compIsForInlining());
3503     for (unsigned i = 0; i < compQMarks->Size(); i++)
3504     {
3505         GenTreePtr qmark = compQMarks->Get(i);
3506         // Perhaps the gtOper of a QMark node was changed to something else since it was created and put on this list.
3507         // So can't hurt to check.
3508         if (qmark->OperGet() == GT_QMARK)
3509         {
3510             VarSetOps::AssignAllowUninitRhs(this, qmark->gtQmark.gtThenLiveSet, VarSetOps::UninitVal());
3511             VarSetOps::AssignAllowUninitRhs(this, qmark->gtQmark.gtElseLiveSet, VarSetOps::UninitVal());
3512         }
3513     }
3514     fgBBVarSetsInited = true;
3515 }
3516
3517 /*****************************************************************************
3518  *
3519  *  The following does the final pass on BBF_NEEDS_GCPOLL and then actually creates the GC Polls.
3520  */
3521 void Compiler::fgCreateGCPolls()
3522 {
3523     if (GCPOLL_NONE == opts.compGCPollType)
3524     {
3525         return;
3526     }
3527
3528     bool createdPollBlocks = false;
3529
3530 #ifdef DEBUG
3531     if (verbose)
3532     {
3533         printf("*************** In fgCreateGCPolls() for %s\n", info.compFullName);
3534     }
3535 #endif // DEBUG
3536
3537     if (!(opts.MinOpts() || opts.compDbgCode))
3538     {
3539         // Remove polls from well formed loops with a constant upper bound.
3540         for (unsigned lnum = 0; lnum < optLoopCount; ++lnum)
3541         {
3542             // Look for constant counted loops that run for a short duration.  This logic is very similar to
3543             // what's in code:Compiler::optUnrollLoops, since they have similar constraints.  However, this
3544             // logic is much more permissive since we're not doing a complex transformation.
3545
3546             /* TODO-Cleanup:
3547              * I feel bad cloning so much logic from optUnrollLoops
3548              */
3549
3550             // Filter out loops not meeting the obvious preconditions.
3551             //
3552             if (optLoopTable[lnum].lpFlags & LPFLG_REMOVED)
3553             {
3554                 continue;
3555             }
3556
3557             if (!(optLoopTable[lnum].lpFlags & LPFLG_CONST))
3558             {
3559                 continue;
3560             }
3561
3562             BasicBlock* head   = optLoopTable[lnum].lpHead;
3563             BasicBlock* bottom = optLoopTable[lnum].lpBottom;
3564
3565             // Loops dominated by GC_SAFE_POINT won't have this set.
3566             if (!(bottom->bbFlags & BBF_NEEDS_GCPOLL))
3567             {
3568                 continue;
3569             }
3570
3571             /* Get the loop data:
3572                 - initial constant
3573                 - limit constant
3574                 - iterator
3575                 - iterator increment
3576                 - increment operation type (i.e. ASG_ADD, ASG_SUB, etc...)
3577                 - loop test type (i.e. GT_GE, GT_LT, etc...)
3578              */
3579
3580             int        lbeg     = optLoopTable[lnum].lpConstInit;
3581             int        llim     = optLoopTable[lnum].lpConstLimit();
3582             genTreeOps testOper = optLoopTable[lnum].lpTestOper();
3583
3584             int        lvar     = optLoopTable[lnum].lpIterVar();
3585             int        iterInc  = optLoopTable[lnum].lpIterConst();
3586             genTreeOps iterOper = optLoopTable[lnum].lpIterOper();
3587
3588             var_types iterOperType = optLoopTable[lnum].lpIterOperType();
3589             bool      unsTest      = (optLoopTable[lnum].lpTestTree->gtFlags & GTF_UNSIGNED) != 0;
3590             if (lvaTable[lvar].lvAddrExposed)
3591             { // Can't reason about the value of the iteration variable.
3592                 continue;
3593             }
3594
3595             unsigned totalIter;
3596
3597             /* Find the number of iterations - the function returns false if not a constant number */
3598
3599             if (!optComputeLoopRep(lbeg, llim, iterInc, iterOper, iterOperType, testOper, unsTest,
3600                                    // The value here doesn't matter for this variation of the optimization
3601                                    true, &totalIter))
3602             {
3603 #ifdef DEBUG
3604                 if (verbose)
3605                 {
3606                     printf("Could not compute loop iterations for loop from BB%02u to BB%02u", head->bbNum,
3607                            bottom->bbNum);
3608                 }
3609 #endif                      // DEBUG
3610                 (void)head; // suppress gcc error.
3611
3612                 continue;
3613             }
3614
3615             /* Forget it if there are too many repetitions or not a constant loop */
3616
3617             static const unsigned ITER_LIMIT = 256;
3618             if (totalIter > ITER_LIMIT)
3619             {
3620                 continue;
3621             }
3622
3623             // It is safe to elminate the poll from this loop.
3624             bottom->bbFlags &= ~BBF_NEEDS_GCPOLL;
3625
3626 #ifdef DEBUG
3627             if (verbose)
3628             {
3629                 printf("Removing poll in block BB%02u because it forms a bounded counted loop\n", bottom->bbNum);
3630             }
3631 #endif // DEBUG
3632         }
3633     }
3634
3635     // Final chance to optimize the polls.  Move all polls in loops from the bottom of the loop up to the
3636     // loop head.  Also eliminate all epilog polls in non-leaf methods.  This only works if we have dominator
3637     // information.
3638     if (fgDomsComputed)
3639     {
3640         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
3641         {
3642             if (!(block->bbFlags & BBF_NEEDS_GCPOLL))
3643             {
3644                 continue;
3645             }
3646
3647             if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS)
3648             {
3649                 // make sure that this is loop-like
3650                 if (!fgReachable(block->bbJumpDest, block))
3651                 {
3652                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3653 #ifdef DEBUG
3654                     if (verbose)
3655                     {
3656                         printf("Removing poll in block BB%02u because it is not loop\n", block->bbNum);
3657                     }
3658 #endif // DEBUG
3659                     continue;
3660                 }
3661             }
3662             else if (!(block->bbJumpKind == BBJ_RETURN || block->bbJumpKind == BBJ_SWITCH))
3663             {
3664                 noway_assert(!"GC Poll on a block that has no control transfer.");
3665 #ifdef DEBUG
3666                 if (verbose)
3667                 {
3668                     printf("Removing poll in block BB%02u because it is not a jump\n", block->bbNum);
3669                 }
3670 #endif // DEBUG
3671                 block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3672                 continue;
3673             }
3674
3675             // Because of block compaction, it's possible to end up with a block that is both poll and safe.
3676             // Clean those up now.
3677
3678             if (block->bbFlags & BBF_GC_SAFE_POINT)
3679             {
3680 #ifdef DEBUG
3681                 if (verbose)
3682                 {
3683                     printf("Removing poll in return block BB%02u because it is GC Safe\n", block->bbNum);
3684                 }
3685 #endif // DEBUG
3686                 block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3687                 continue;
3688             }
3689
3690             if (block->bbJumpKind == BBJ_RETURN)
3691             {
3692                 if (!optReachWithoutCall(fgFirstBB, block))
3693                 {
3694                     // check to see if there is a call along the path between the first block and the return
3695                     // block.
3696                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
3697 #ifdef DEBUG
3698                     if (verbose)
3699                     {
3700                         printf("Removing poll in return block BB%02u because it dominated by a call\n", block->bbNum);
3701                     }
3702 #endif // DEBUG
3703                     continue;
3704                 }
3705             }
3706         }
3707     }
3708
3709     noway_assert(!fgGCPollsCreated);
3710     BasicBlock* block;
3711     fgGCPollsCreated = true;
3712
3713     // Walk through the blocks and hunt for a block that has BBF_NEEDS_GCPOLL
3714     for (block = fgFirstBB; block; block = block->bbNext)
3715     {
3716         // Because of block compaction, it's possible to end up with a block that is both poll and safe.
3717         // And if !fgDomsComputed, we won't have cleared them, so skip them now
3718         if (!(block->bbFlags & BBF_NEEDS_GCPOLL) || (block->bbFlags & BBF_GC_SAFE_POINT))
3719         {
3720             continue;
3721         }
3722
3723         // This block needs a poll.  We either just insert a callout or we split the block and inline part of
3724         // the test.  This depends on the value of opts.compGCPollType.
3725
3726         // If we're doing GCPOLL_CALL, just insert a GT_CALL node before the last node in the block.
3727         CLANG_FORMAT_COMMENT_ANCHOR;
3728
3729 #ifdef DEBUG
3730         switch (block->bbJumpKind)
3731         {
3732             case BBJ_RETURN:
3733             case BBJ_ALWAYS:
3734             case BBJ_COND:
3735             case BBJ_SWITCH:
3736                 break;
3737             default:
3738                 noway_assert(!"Unknown block type for BBF_NEEDS_GCPOLL");
3739         }
3740 #endif // DEBUG
3741
3742         noway_assert(opts.compGCPollType);
3743
3744         GCPollType pollType = opts.compGCPollType;
3745         // pollType is set to either CALL or INLINE at this point.  Below is the list of places where we
3746         // can't or don't want to emit an inline check.  Check all of those.  If after all of that we still
3747         // have INLINE, then emit an inline check.
3748
3749         if (opts.MinOpts() || opts.compDbgCode)
3750         {
3751 #ifdef DEBUG
3752             if (verbose)
3753             {
3754                 printf("Selecting CALL poll in block BB%02u because of debug/minopts\n", block->bbNum);
3755             }
3756 #endif // DEBUG
3757
3758             // Don't split blocks and create inlined polls unless we're optimizing.
3759             pollType = GCPOLL_CALL;
3760         }
3761         else if (genReturnBB == block)
3762         {
3763 #ifdef DEBUG
3764             if (verbose)
3765             {
3766                 printf("Selecting CALL poll in block BB%02u because it is the single return block\n", block->bbNum);
3767             }
3768 #endif // DEBUG
3769
3770             // we don't want to split the single return block
3771             pollType = GCPOLL_CALL;
3772         }
3773         else if (BBJ_SWITCH == block->bbJumpKind)
3774         {
3775 #ifdef DEBUG
3776             if (verbose)
3777             {
3778                 printf("Selecting CALL poll in block BB%02u because it is a loop formed by a SWITCH\n", block->bbNum);
3779             }
3780 #endif // DEBUG
3781
3782             // I don't want to deal with all the outgoing edges of a switch block.
3783             pollType = GCPOLL_CALL;
3784         }
3785
3786         // TODO-Cleanup: potentially don't split if we're in an EH region.
3787
3788         createdPollBlocks |= fgCreateGCPoll(pollType, block);
3789     }
3790
3791     // If we split a block to create a GC Poll, then rerun fgReorderBlocks to push the rarely run blocks out
3792     // past the epilog.  We should never split blocks unless we're optimizing.
3793     if (createdPollBlocks)
3794     {
3795         noway_assert(!opts.MinOpts() && !opts.compDbgCode);
3796         fgReorderBlocks();
3797     }
3798 }
3799
3800 /*****************************************************************************
3801  *
3802  *  Actually create a GCPoll in the given block. Returns true if it created
3803  *  a basic block.
3804  */
3805
3806 bool Compiler::fgCreateGCPoll(GCPollType pollType, BasicBlock* block)
3807 {
3808     assert(!(block->bbFlags & BBF_GC_SAFE_POINT));
3809     bool createdPollBlocks;
3810
3811     void* addrTrap;
3812     void* pAddrOfCaptureThreadGlobal;
3813
3814     addrTrap = info.compCompHnd->getAddrOfCaptureThreadGlobal(&pAddrOfCaptureThreadGlobal);
3815
3816 #ifdef ENABLE_FAST_GCPOLL_HELPER
3817     // I never want to split blocks if we've got two indirections here.
3818     // This is a size trade-off assuming the VM has ENABLE_FAST_GCPOLL_HELPER.
3819     // So don't do it when that is off
3820     if (pAddrOfCaptureThreadGlobal != NULL)
3821     {
3822         pollType = GCPOLL_CALL;
3823     }
3824 #endif // ENABLE_FAST_GCPOLL_HELPER
3825
3826     if (GCPOLL_CALL == pollType)
3827     {
3828         createdPollBlocks = false;
3829         GenTreePtr tree   = gtNewHelperCallNode(CORINFO_HELP_POLL_GC, TYP_VOID);
3830 #if GTF_CALL_REG_SAVE
3831         tree->gtCall.gtCallMoreFlags |= GTF_CALL_REG_SAVE;
3832 #endif // GTF_CALL_REG_SAVE
3833
3834         // for BBJ_ALWAYS I don't need to insert it before the condition.  Just append it.
3835         if (block->bbJumpKind == BBJ_ALWAYS)
3836         {
3837             fgInsertStmtAtEnd(block, tree);
3838         }
3839         else
3840         {
3841             GenTreeStmt* newStmt = fgInsertStmtNearEnd(block, tree);
3842             // For DDB156656, we need to associate the GC Poll with the IL offset (and therefore sequence
3843             // point) of the tree before which we inserted the poll.  One example of when this is a
3844             // problem:
3845             //  if (...) {  //1
3846             //      ...
3847             //  } //2
3848             //  else { //3
3849             //      ...
3850             //  }
3851             //  (gcpoll) //4
3852             //  return. //5
3853             //
3854             //  If we take the if statement at 1, we encounter a jump at 2.  This jumps over the else
3855             //  and lands at 4.  4 is where we inserted the gcpoll.  However, that is associated with
3856             //  the sequence point a 3.  Therefore, the debugger displays the wrong source line at the
3857             //  gc poll location.
3858             //
3859             //  More formally, if control flow targets an instruction, that instruction must be the
3860             //  start of a new sequence point.
3861             if (newStmt->gtNext)
3862             {
3863                 // Is it possible for gtNext to be NULL?
3864                 noway_assert(newStmt->gtNext->gtOper == GT_STMT);
3865                 newStmt->gtStmtILoffsx = newStmt->gtNextStmt->gtStmtILoffsx;
3866             }
3867         }
3868
3869         block->bbFlags |= BBF_GC_SAFE_POINT;
3870 #ifdef DEBUG
3871         if (verbose)
3872         {
3873             printf("*** creating GC Poll in block BB%02u\n", block->bbNum);
3874             gtDispTreeList(block->bbTreeList);
3875         }
3876 #endif // DEBUG
3877     }
3878     else
3879     {
3880         createdPollBlocks = true;
3881         // if we're doing GCPOLL_INLINE, then:
3882         //  1) Create two new blocks: Poll and Bottom.  The original block is called Top.
3883
3884         // I want to create:
3885         // top -> poll -> bottom (lexically)
3886         // so that we jump over poll to get to bottom.
3887         BasicBlock* top         = block;
3888         BasicBlock* poll        = fgNewBBafter(BBJ_NONE, top, true);
3889         BasicBlock* bottom      = fgNewBBafter(top->bbJumpKind, poll, true);
3890         BBjumpKinds oldJumpKind = top->bbJumpKind;
3891
3892         // Update block flags
3893         unsigned originalFlags;
3894         originalFlags = top->bbFlags | BBF_GC_SAFE_POINT;
3895
3896         // Unlike Fei's inliner from puclr, I'm allowed to split loops.
3897         // And we keep a few other flags...
3898         noway_assert((originalFlags & (BBF_SPLIT_NONEXIST & ~(BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1))) == 0);
3899         top->bbFlags = originalFlags & (~BBF_SPLIT_LOST | BBF_GC_SAFE_POINT);
3900         bottom->bbFlags |= originalFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_GC_SAFE_POINT);
3901         bottom->inheritWeight(top);
3902         poll->bbFlags |= originalFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_GC_SAFE_POINT);
3903
3904         //  9) Mark Poll as rarely run.
3905         poll->bbSetRunRarely();
3906
3907         //  5) Bottom gets all the outgoing edges and inherited flags of Original.
3908         bottom->bbJumpDest = top->bbJumpDest;
3909
3910         //  2) Add a GC_CALL node to Poll.
3911         GenTreePtr tree = gtNewHelperCallNode(CORINFO_HELP_POLL_GC, TYP_VOID);
3912 #if GTF_CALL_REG_SAVE
3913         tree->gtCall.gtCallMoreFlags |= GTF_CALL_REG_SAVE;
3914 #endif // GTF_CALL_REG_SAVE
3915         fgInsertStmtAtEnd(poll, tree);
3916
3917         //  3) Remove the last statement from Top and add it to Bottom.
3918         if (oldJumpKind != BBJ_ALWAYS)
3919         {
3920             // if I'm always jumping to the target, then this is not a condition that needs moving.
3921             GenTreeStmt* stmt = top->firstStmt();
3922             while (stmt->gtNext)
3923             {
3924                 stmt = stmt->gtNextStmt;
3925             }
3926             fgRemoveStmt(top, stmt);
3927             fgInsertStmtAtEnd(bottom, stmt);
3928         }
3929
3930         // for BBJ_ALWAYS blocks, bottom is an empty block.
3931
3932         //  4) Create a GT_EQ node that checks against g_TrapReturningThreads.  True jumps to Bottom,
3933         //  false falls through to poll.  Add this to the end of Top.  Top is now BBJ_COND.  Bottom is
3934         //  now a jump target
3935         CLANG_FORMAT_COMMENT_ANCHOR;
3936
3937 #ifdef ENABLE_FAST_GCPOLL_HELPER
3938         // Prefer the fast gc poll helepr over the double indirection
3939         noway_assert(pAddrOfCaptureThreadGlobal == nullptr);
3940 #endif
3941
3942         GenTreePtr trap;
3943         if (pAddrOfCaptureThreadGlobal != nullptr)
3944         {
3945             trap = gtNewOperNode(GT_IND, TYP_I_IMPL,
3946                                  gtNewIconHandleNode((size_t)pAddrOfCaptureThreadGlobal, GTF_ICON_PTR_HDL));
3947         }
3948         else
3949         {
3950             trap = gtNewIconHandleNode((size_t)addrTrap, GTF_ICON_PTR_HDL);
3951         }
3952
3953         GenTreePtr trapRelop = gtNewOperNode(GT_EQ, TYP_INT,
3954                                              // lhs [g_TrapReturningThreads]
3955                                              gtNewOperNode(GT_IND, TYP_INT, trap),
3956                                              // rhs 0
3957                                              gtNewIconNode(0, TYP_INT));
3958         trapRelop->gtFlags |= GTF_RELOP_JMP_USED | GTF_DONT_CSE; // Treat reading g_TrapReturningThreads as volatile.
3959         GenTreePtr trapCheck = gtNewOperNode(GT_JTRUE, TYP_VOID, trapRelop);
3960         fgInsertStmtAtEnd(top, trapCheck);
3961         top->bbJumpDest = bottom;
3962         top->bbJumpKind = BBJ_COND;
3963         bottom->bbFlags |= BBF_JMP_TARGET;
3964
3965         //  7) Bottom has Top and Poll as its predecessors.  Poll has just Top as a predecessor.
3966         fgAddRefPred(bottom, poll);
3967         fgAddRefPred(bottom, top);
3968         fgAddRefPred(poll, top);
3969
3970         //  8) Replace Top with Bottom in the predecessor list of all outgoing edges from Bottom (1 for
3971         //      jumps, 2 for conditional branches, N for switches).
3972         switch (oldJumpKind)
3973         {
3974             case BBJ_RETURN:
3975                 // no successors
3976                 break;
3977             case BBJ_COND:
3978                 // replace predecessor in the fall through block.
3979                 noway_assert(bottom->bbNext);
3980                 fgReplacePred(bottom->bbNext, top, bottom);
3981
3982                 // fall through for the jump target
3983                 __fallthrough;
3984
3985             case BBJ_ALWAYS:
3986                 fgReplacePred(bottom->bbJumpDest, top, bottom);
3987                 break;
3988             case BBJ_SWITCH:
3989                 NO_WAY("SWITCH should be a call rather than an inlined poll.");
3990                 break;
3991             default:
3992                 NO_WAY("Unknown block type for updating predecessor lists.");
3993         }
3994
3995         top->bbFlags &= ~BBF_NEEDS_GCPOLL;
3996         noway_assert(!(poll->bbFlags & BBF_NEEDS_GCPOLL));
3997         noway_assert(!(bottom->bbFlags & BBF_NEEDS_GCPOLL));
3998
3999         if (compCurBB == top)
4000         {
4001             compCurBB = bottom;
4002         }
4003
4004 #ifdef DEBUG
4005         if (verbose)
4006         {
4007             printf("*** creating inlined GC Poll in top block BB%02u\n", top->bbNum);
4008             gtDispTreeList(top->bbTreeList);
4009             printf(" poll block is BB%02u\n", poll->bbNum);
4010             gtDispTreeList(poll->bbTreeList);
4011             printf(" bottom block is BB%02u\n", bottom->bbNum);
4012             gtDispTreeList(bottom->bbTreeList);
4013         }
4014 #endif // DEBUG
4015     }
4016
4017     return createdPollBlocks;
4018 }
4019
4020 /*****************************************************************************
4021  *
4022  *  The following helps find a basic block given its PC offset.
4023  */
4024
4025 void Compiler::fgInitBBLookup()
4026 {
4027     BasicBlock** dscBBptr;
4028     BasicBlock*  tmpBBdesc;
4029
4030     /* Allocate the basic block table */
4031
4032     dscBBptr = fgBBs = new (this, CMK_BasicBlock) BasicBlock*[fgBBcount];
4033
4034     /* Walk all the basic blocks, filling in the table */
4035
4036     for (tmpBBdesc = fgFirstBB; tmpBBdesc; tmpBBdesc = tmpBBdesc->bbNext)
4037     {
4038         *dscBBptr++ = tmpBBdesc;
4039     }
4040
4041     noway_assert(dscBBptr == fgBBs + fgBBcount);
4042 }
4043
4044 BasicBlock* Compiler::fgLookupBB(unsigned addr)
4045 {
4046     unsigned lo;
4047     unsigned hi;
4048
4049     /* Do a binary search */
4050
4051     for (lo = 0, hi = fgBBcount - 1;;)
4052     {
4053
4054     AGAIN:;
4055
4056         if (lo > hi)
4057         {
4058             break;
4059         }
4060
4061         unsigned    mid = (lo + hi) / 2;
4062         BasicBlock* dsc = fgBBs[mid];
4063
4064         // We introduce internal blocks for BBJ_CALLFINALLY. Skip over these.
4065
4066         while (dsc->bbFlags & BBF_INTERNAL)
4067         {
4068             dsc = dsc->bbNext;
4069             mid++;
4070
4071             // We skipped over too many, Set hi back to the original mid - 1
4072
4073             if (mid > hi)
4074             {
4075                 mid = (lo + hi) / 2;
4076                 hi  = mid - 1;
4077                 goto AGAIN;
4078             }
4079         }
4080
4081         unsigned pos = dsc->bbCodeOffs;
4082
4083         if (pos < addr)
4084         {
4085             if ((lo == hi) && (lo == (fgBBcount - 1)))
4086             {
4087                 noway_assert(addr == dsc->bbCodeOffsEnd);
4088                 return nullptr; // NULL means the end of method
4089             }
4090             lo = mid + 1;
4091             continue;
4092         }
4093
4094         if (pos > addr)
4095         {
4096             hi = mid - 1;
4097             continue;
4098         }
4099
4100         return dsc;
4101     }
4102 #ifdef DEBUG
4103     printf("ERROR: Couldn't find basic block at offset %04X\n", addr);
4104 #endif // DEBUG
4105     NO_WAY("fgLookupBB failed.");
4106 }
4107
4108 /*****************************************************************************
4109  *
4110  *  The 'jump target' array uses the following flags to indicate what kind
4111  *  of label is present.
4112  */
4113
4114 #define JT_NONE 0x00  // This IL offset is never used
4115 #define JT_ADDR 0x01  // merely make sure this is an OK address
4116 #define JT_JUMP 0x02  // 'normal' jump target
4117 #define JT_MULTI 0x04 // target of multiple jumps
4118
4119 inline void Compiler::fgMarkJumpTarget(BYTE* jumpTarget, unsigned offs)
4120 {
4121     /* Make sure we set JT_MULTI if target of multiple jumps */
4122
4123     noway_assert(JT_MULTI == JT_JUMP << 1);
4124
4125     jumpTarget[offs] |= (jumpTarget[offs] & JT_JUMP) << 1 | JT_JUMP;
4126 }
4127
4128 //------------------------------------------------------------------------
4129 // FgStack: simple stack model for the inlinee's evaluation stack.
4130 //
4131 // Model the inputs available to various operations in the inline body.
4132 // Tracks constants, arguments, array lengths.
4133
4134 class FgStack
4135 {
4136 public:
4137     FgStack() : slot0(SLOT_INVALID), slot1(SLOT_INVALID), depth(0)
4138     {
4139         // Empty
4140     }
4141
4142     void Clear()
4143     {
4144         depth = 0;
4145     }
4146     void PushUnknown()
4147     {
4148         Push(SLOT_UNKNOWN);
4149     }
4150     void PushConstant()
4151     {
4152         Push(SLOT_CONSTANT);
4153     }
4154     void PushArrayLen()
4155     {
4156         Push(SLOT_ARRAYLEN);
4157     }
4158     void PushArgument(unsigned arg)
4159     {
4160         Push(SLOT_ARGUMENT + arg);
4161     }
4162     unsigned GetSlot0() const
4163     {
4164         assert(depth >= 1);
4165         return slot0;
4166     }
4167     unsigned GetSlot1() const
4168     {
4169         assert(depth >= 2);
4170         return slot1;
4171     }
4172     static bool IsConstant(unsigned value)
4173     {
4174         return value == SLOT_CONSTANT;
4175     }
4176     static bool IsArrayLen(unsigned value)
4177     {
4178         return value == SLOT_ARRAYLEN;
4179     }
4180     static bool IsArgument(unsigned value)
4181     {
4182         return value >= SLOT_ARGUMENT;
4183     }
4184     static unsigned SlotTypeToArgNum(unsigned value)
4185     {
4186         assert(IsArgument(value));
4187         return value - SLOT_ARGUMENT;
4188     }
4189     bool IsStackTwoDeep() const
4190     {
4191         return depth == 2;
4192     }
4193     bool IsStackOneDeep() const
4194     {
4195         return depth == 1;
4196     }
4197     bool IsStackAtLeastOneDeep() const
4198     {
4199         return depth >= 1;
4200     }
4201
4202 private:
4203     enum
4204     {
4205         SLOT_INVALID  = UINT_MAX,
4206         SLOT_UNKNOWN  = 0,
4207         SLOT_CONSTANT = 1,
4208         SLOT_ARRAYLEN = 2,
4209         SLOT_ARGUMENT = 3
4210     };
4211
4212     void Push(int type)
4213     {
4214         switch (depth)
4215         {
4216             case 0:
4217                 ++depth;
4218                 slot0 = type;
4219                 break;
4220             case 1:
4221                 ++depth;
4222                 __fallthrough;
4223             case 2:
4224                 slot1 = slot0;
4225                 slot0 = type;
4226         }
4227     }
4228
4229     unsigned slot0;
4230     unsigned slot1;
4231     unsigned depth;
4232 };
4233
4234 //------------------------------------------------------------------------
4235 // fgFindJumpTargets: walk the IL stream, determining jump target offsets
4236 //
4237 // Arguments:
4238 //    codeAddr   - base address of the IL code buffer
4239 //    codeSize   - number of bytes in the IL code buffer
4240 //    jumpTarget - [OUT] byte array for flagging jump targets
4241 //
4242 // Notes:
4243 //    If inlining or prejitting the root, this method also makes
4244 //    various observations about the method that factor into inline
4245 //    decisions.
4246 //
4247 //    May throw an exception if the IL is malformed.
4248 //
4249 //    jumpTarget[N] is set to a JT_* value if IL offset N is a
4250 //    jump target in the method.
4251 //
4252 //    Also sets lvAddrExposed and lvArgWrite in lvaTable[].
4253
4254 #ifdef _PREFAST_
4255 #pragma warning(push)
4256 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
4257 #endif
4258
4259 void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget)
4260 {
4261     const BYTE* codeBegp = codeAddr;
4262     const BYTE* codeEndp = codeAddr + codeSize;
4263     unsigned    varNum;
4264     bool        seenJump = false;
4265     var_types   varType  = DUMMY_INIT(TYP_UNDEF); // TYP_ type
4266     typeInfo    ti;                               // Verifier type.
4267     bool        typeIsNormed = false;
4268     FgStack     pushedStack;
4269     const bool  isForceInline          = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0;
4270     const bool  makeInlineObservations = (compInlineResult != nullptr);
4271     const bool  isInlining             = compIsForInlining();
4272
4273     if (makeInlineObservations)
4274     {
4275         // Observe force inline state and code size.
4276         compInlineResult->NoteBool(InlineObservation::CALLEE_IS_FORCE_INLINE, isForceInline);
4277         compInlineResult->NoteInt(InlineObservation::CALLEE_IL_CODE_SIZE, codeSize);
4278
4279 #ifdef DEBUG
4280
4281         // If inlining, this method should still be a candidate.
4282         if (isInlining)
4283         {
4284             assert(compInlineResult->IsCandidate());
4285         }
4286
4287 #endif // DEBUG
4288
4289         // note that we're starting to look at the opcodes.
4290         compInlineResult->Note(InlineObservation::CALLEE_BEGIN_OPCODE_SCAN);
4291     }
4292
4293     while (codeAddr < codeEndp)
4294     {
4295         OPCODE opcode = (OPCODE)getU1LittleEndian(codeAddr);
4296         codeAddr += sizeof(__int8);
4297         opts.instrCount++;
4298         typeIsNormed = false;
4299
4300     DECODE_OPCODE:
4301
4302         if (opcode >= CEE_COUNT)
4303         {
4304             BADCODE3("Illegal opcode", ": %02X", (int)opcode);
4305         }
4306
4307         if ((opcode >= CEE_LDARG_0 && opcode <= CEE_STLOC_S) || (opcode >= CEE_LDARG && opcode <= CEE_STLOC))
4308         {
4309             opts.lvRefCount++;
4310         }
4311
4312         if (makeInlineObservations && (opcode >= CEE_LDNULL) && (opcode <= CEE_LDC_R8))
4313         {
4314             pushedStack.PushConstant();
4315         }
4316
4317         unsigned sz = opcodeSizes[opcode];
4318
4319         switch (opcode)
4320         {
4321             case CEE_PREFIX1:
4322             {
4323                 if (codeAddr >= codeEndp)
4324                 {
4325                     goto TOO_FAR;
4326                 }
4327                 opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr));
4328                 codeAddr += sizeof(__int8);
4329                 goto DECODE_OPCODE;
4330             }
4331
4332             case CEE_PREFIX2:
4333             case CEE_PREFIX3:
4334             case CEE_PREFIX4:
4335             case CEE_PREFIX5:
4336             case CEE_PREFIX6:
4337             case CEE_PREFIX7:
4338             case CEE_PREFIXREF:
4339             {
4340                 BADCODE3("Illegal opcode", ": %02X", (int)opcode);
4341             }
4342
4343             case CEE_CALL:
4344             case CEE_CALLVIRT:
4345             {
4346                 // There has to be code after the call, otherwise the inlinee is unverifiable.
4347                 if (isInlining)
4348                 {
4349
4350                     noway_assert(codeAddr < codeEndp - sz);
4351                 }
4352
4353                 // If the method has a call followed by a ret, assume that
4354                 // it is a wrapper method.
4355                 if (makeInlineObservations)
4356                 {
4357                     if ((OPCODE)getU1LittleEndian(codeAddr + sz) == CEE_RET)
4358                     {
4359                         compInlineResult->Note(InlineObservation::CALLEE_LOOKS_LIKE_WRAPPER);
4360                     }
4361                 }
4362             }
4363             break;
4364
4365             case CEE_LEAVE:
4366             case CEE_LEAVE_S:
4367             case CEE_BR:
4368             case CEE_BR_S:
4369             case CEE_BRFALSE:
4370             case CEE_BRFALSE_S:
4371             case CEE_BRTRUE:
4372             case CEE_BRTRUE_S:
4373             case CEE_BEQ:
4374             case CEE_BEQ_S:
4375             case CEE_BGE:
4376             case CEE_BGE_S:
4377             case CEE_BGE_UN:
4378             case CEE_BGE_UN_S:
4379             case CEE_BGT:
4380             case CEE_BGT_S:
4381             case CEE_BGT_UN:
4382             case CEE_BGT_UN_S:
4383             case CEE_BLE:
4384             case CEE_BLE_S:
4385             case CEE_BLE_UN:
4386             case CEE_BLE_UN_S:
4387             case CEE_BLT:
4388             case CEE_BLT_S:
4389             case CEE_BLT_UN:
4390             case CEE_BLT_UN_S:
4391             case CEE_BNE_UN:
4392             case CEE_BNE_UN_S:
4393             {
4394                 seenJump = true;
4395
4396                 if (codeAddr > codeEndp - sz)
4397                 {
4398                     goto TOO_FAR;
4399                 }
4400
4401                 // Compute jump target address
4402                 signed jmpDist = (sz == 1) ? getI1LittleEndian(codeAddr) : getI4LittleEndian(codeAddr);
4403
4404                 if (compIsForInlining() && jmpDist == 0 &&
4405                     (opcode == CEE_LEAVE || opcode == CEE_LEAVE_S || opcode == CEE_BR || opcode == CEE_BR_S))
4406                 {
4407                     break; /* NOP */
4408                 }
4409
4410                 unsigned jmpAddr = (IL_OFFSET)(codeAddr - codeBegp) + sz + jmpDist;
4411
4412                 // Make sure target is reasonable
4413                 if (jmpAddr >= codeSize)
4414                 {
4415                     BADCODE3("code jumps to outer space", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4416                 }
4417
4418                 // Mark the jump target
4419                 fgMarkJumpTarget(jumpTarget, jmpAddr);
4420
4421                 // See if jump might be sensitive to inlining
4422                 if (makeInlineObservations && (opcode != CEE_BR_S) && (opcode != CEE_BR))
4423                 {
4424                     fgObserveInlineConstants(opcode, pushedStack, isInlining);
4425                 }
4426             }
4427             break;
4428
4429             case CEE_SWITCH:
4430             {
4431                 seenJump = true;
4432
4433                 if (makeInlineObservations)
4434                 {
4435                     compInlineResult->Note(InlineObservation::CALLEE_HAS_SWITCH);
4436
4437                     // Fail fast, if we're inlining and can't handle this.
4438                     if (isInlining && compInlineResult->IsFailure())
4439                     {
4440                         return;
4441                     }
4442                 }
4443
4444                 // Make sure we don't go past the end reading the number of cases
4445                 if (codeAddr > codeEndp - sizeof(DWORD))
4446                 {
4447                     goto TOO_FAR;
4448                 }
4449
4450                 // Read the number of cases
4451                 unsigned jmpCnt = getU4LittleEndian(codeAddr);
4452                 codeAddr += sizeof(DWORD);
4453
4454                 if (jmpCnt > codeSize / sizeof(DWORD))
4455                 {
4456                     goto TOO_FAR;
4457                 }
4458
4459                 // Find the end of the switch table
4460                 unsigned jmpBase = (unsigned)((codeAddr - codeBegp) + jmpCnt * sizeof(DWORD));
4461
4462                 // Make sure there is more code after the switch
4463                 if (jmpBase >= codeSize)
4464                 {
4465                     goto TOO_FAR;
4466                 }
4467
4468                 // jmpBase is also the target of the default case, so mark it
4469                 fgMarkJumpTarget(jumpTarget, jmpBase);
4470
4471                 // Process table entries
4472                 while (jmpCnt > 0)
4473                 {
4474                     unsigned jmpAddr = jmpBase + getI4LittleEndian(codeAddr);
4475                     codeAddr += 4;
4476
4477                     if (jmpAddr >= codeSize)
4478                     {
4479                         BADCODE3("jump target out of range", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4480                     }
4481
4482                     fgMarkJumpTarget(jumpTarget, jmpAddr);
4483                     jmpCnt--;
4484                 }
4485
4486                 // We've advanced past all the bytes in this instruction
4487                 sz = 0;
4488             }
4489             break;
4490
4491             case CEE_UNALIGNED:
4492             case CEE_CONSTRAINED:
4493             case CEE_READONLY:
4494             case CEE_VOLATILE:
4495             case CEE_TAILCALL:
4496             {
4497                 if (codeAddr >= codeEndp)
4498                 {
4499                     goto TOO_FAR;
4500                 }
4501             }
4502             break;
4503
4504             case CEE_STARG:
4505             case CEE_STARG_S:
4506             {
4507                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4508
4509                 if (codeAddr > codeEndp - sz)
4510                 {
4511                     goto TOO_FAR;
4512                 }
4513
4514                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4515                 varNum = compMapILargNum(varNum); // account for possible hidden param
4516
4517                 // This check is only intended to prevent an AV.  Bad varNum values will later
4518                 // be handled properly by the verifier.
4519                 if (varNum < lvaTableCnt)
4520                 {
4521                     if (isInlining)
4522                     {
4523                         impInlineInfo->inlArgInfo[varNum].argHasStargOp = true;
4524                     }
4525                     else
4526                     {
4527                         // In non-inline cases, note written-to locals.
4528                         lvaTable[varNum].lvArgWrite = 1;
4529                     }
4530                 }
4531             }
4532             break;
4533
4534             case CEE_LDARGA:
4535             case CEE_LDARGA_S:
4536             case CEE_LDLOCA:
4537             case CEE_LDLOCA_S:
4538             {
4539                 // Handle address-taken args or locals
4540                 noway_assert(sz == sizeof(BYTE) || sz == sizeof(WORD));
4541
4542                 if (codeAddr > codeEndp - sz)
4543                 {
4544                     goto TOO_FAR;
4545                 }
4546
4547                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4548
4549                 if (isInlining)
4550                 {
4551                     if (opcode == CEE_LDLOCA || opcode == CEE_LDLOCA_S)
4552                     {
4553                         varType = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclTypeInfo;
4554                         ti      = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclVerTypeInfo;
4555
4556                         impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclHasLdlocaOp = true;
4557                     }
4558                     else
4559                     {
4560                         noway_assert(opcode == CEE_LDARGA || opcode == CEE_LDARGA_S);
4561
4562                         varType = impInlineInfo->lclVarInfo[varNum].lclTypeInfo;
4563                         ti      = impInlineInfo->lclVarInfo[varNum].lclVerTypeInfo;
4564
4565                         impInlineInfo->inlArgInfo[varNum].argHasLdargaOp = true;
4566
4567                         pushedStack.PushArgument(varNum);
4568                     }
4569                 }
4570                 else
4571                 {
4572                     if (opcode == CEE_LDLOCA || opcode == CEE_LDLOCA_S)
4573                     {
4574                         if (varNum >= info.compMethodInfo->locals.numArgs)
4575                         {
4576                             BADCODE("bad local number");
4577                         }
4578
4579                         varNum += info.compArgsCount;
4580                     }
4581                     else
4582                     {
4583                         noway_assert(opcode == CEE_LDARGA || opcode == CEE_LDARGA_S);
4584
4585                         if (varNum >= info.compILargsCount)
4586                         {
4587                             BADCODE("bad argument number");
4588                         }
4589
4590                         varNum = compMapILargNum(varNum); // account for possible hidden param
4591                     }
4592
4593                     varType = (var_types)lvaTable[varNum].lvType;
4594                     ti      = lvaTable[varNum].lvVerTypeInfo;
4595
4596                     // Determine if the next instruction will consume
4597                     // the address. If so we won't mark this var as
4598                     // address taken.
4599                     //
4600                     // We will put structs on the stack and changing
4601                     // the addrTaken of a local requires an extra pass
4602                     // in the morpher so we won't apply this
4603                     // optimization to structs.
4604                     //
4605                     // Debug code spills for every IL instruction, and
4606                     // therefore it will split statements, so we will
4607                     // need the address.  Note that this optimization
4608                     // is based in that we know what trees we will
4609                     // generate for this ldfld, and we require that we
4610                     // won't need the address of this local at all
4611                     noway_assert(varNum < lvaTableCnt);
4612
4613                     const bool notStruct    = !varTypeIsStruct(&lvaTable[varNum]);
4614                     const bool notLastInstr = (codeAddr < codeEndp - sz);
4615                     const bool notDebugCode = !opts.compDbgCode;
4616
4617                     if (notStruct && notLastInstr && notDebugCode &&
4618                         impILConsumesAddr(codeAddr + sz, impTokenLookupContextHandle, info.compScopeHnd))
4619                     {
4620                         // We can skip the addrtaken, as next IL instruction consumes
4621                         // the address.
4622                     }
4623                     else
4624                     {
4625                         lvaTable[varNum].lvHasLdAddrOp = 1;
4626                         if (!info.compIsStatic && (varNum == 0))
4627                         {
4628                             // Addr taken on "this" pointer is significant,
4629                             // go ahead to mark it as permanently addr-exposed here.
4630                             lvaSetVarAddrExposed(0);
4631                             // This may be conservative, but probably not very.
4632                         }
4633                     }
4634                 } // isInlining
4635
4636                 typeIsNormed = ti.IsValueClass() && !varTypeIsStruct(varType);
4637             }
4638             break;
4639
4640             case CEE_JMP:
4641
4642 #if !defined(_TARGET_X86_) && !defined(_TARGET_ARM_)
4643                 if (!isInlining)
4644                 {
4645                     // We transform this into a set of ldarg's + tail call and
4646                     // thus may push more onto the stack than originally thought.
4647                     // This doesn't interfere with verification because CEE_JMP
4648                     // is never verifiable, and there's nothing unsafe you can
4649                     // do with a an IL stack overflow if the JIT is expecting it.
4650                     info.compMaxStack = max(info.compMaxStack, info.compILargsCount);
4651                     break;
4652                 }
4653 #endif // !_TARGET_X86_ && !_TARGET_ARM_
4654
4655                 // If we are inlining, we need to fail for a CEE_JMP opcode, just like
4656                 // the list of other opcodes (for all platforms).
4657
4658                 __fallthrough;
4659
4660             case CEE_CALLI:
4661             case CEE_LOCALLOC:
4662             case CEE_MKREFANY:
4663             case CEE_RETHROW:
4664                 // CEE_CALLI should not be inlined because the JIT cannot generate an inlined call frame. If the call
4665                 // target
4666                 // is a no-marshal CALLI P/Invoke we end up calling the IL stub. We don't NGEN these stubs, so we'll
4667                 // have to
4668                 // JIT an IL stub for a trivial func. It's almost certainly a better choice to leave out the inline
4669                 // candidate so we can generate an inlined call frame. It might be nice to call getCallInfo to figure
4670                 // out
4671                 // what kind of call we have here.
4672
4673                 // Consider making this only for not force inline.
4674                 if (makeInlineObservations)
4675                 {
4676                     // Arguably this should be NoteFatal, but the legacy behavior is
4677                     // to ignore this for the prejit root.
4678                     compInlineResult->Note(InlineObservation::CALLEE_UNSUPPORTED_OPCODE);
4679
4680                     // Fail fast if we're inlining...
4681                     if (isInlining)
4682                     {
4683                         assert(compInlineResult->IsFailure());
4684                         return;
4685                     }
4686                 }
4687                 break;
4688
4689             case CEE_LDARG_0:
4690             case CEE_LDARG_1:
4691             case CEE_LDARG_2:
4692             case CEE_LDARG_3:
4693                 if (makeInlineObservations)
4694                 {
4695                     pushedStack.PushArgument(opcode - CEE_LDARG_0);
4696                 }
4697                 break;
4698
4699             case CEE_LDARG_S:
4700             case CEE_LDARG:
4701             {
4702                 if (codeAddr > codeEndp - sz)
4703                 {
4704                     goto TOO_FAR;
4705                 }
4706
4707                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
4708
4709                 if (makeInlineObservations)
4710                 {
4711                     pushedStack.PushArgument(varNum);
4712                 }
4713             }
4714             break;
4715
4716             case CEE_LDLEN:
4717                 if (makeInlineObservations)
4718                 {
4719                     pushedStack.PushArrayLen();
4720                 }
4721                 break;
4722
4723             case CEE_CEQ:
4724             case CEE_CGT:
4725             case CEE_CGT_UN:
4726             case CEE_CLT:
4727             case CEE_CLT_UN:
4728                 if (makeInlineObservations)
4729                 {
4730                     fgObserveInlineConstants(opcode, pushedStack, isInlining);
4731                 }
4732                 break;
4733
4734             default:
4735                 break;
4736         }
4737
4738         // Skip any remaining operands this opcode may have
4739         codeAddr += sz;
4740
4741         // Note the opcode we just saw
4742         if (makeInlineObservations)
4743         {
4744             InlineObservation obs =
4745                 typeIsNormed ? InlineObservation::CALLEE_OPCODE_NORMED : InlineObservation::CALLEE_OPCODE;
4746             compInlineResult->NoteInt(obs, opcode);
4747         }
4748     }
4749
4750     if (codeAddr != codeEndp)
4751     {
4752     TOO_FAR:
4753         BADCODE3("Code ends in the middle of an opcode, or there is a branch past the end of the method",
4754                  " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
4755     }
4756
4757     if (makeInlineObservations)
4758     {
4759         compInlineResult->Note(InlineObservation::CALLEE_END_OPCODE_SCAN);
4760
4761         // If the inline is viable and discretionary, do the
4762         // profitability screening.
4763         if (compInlineResult->IsDiscretionaryCandidate())
4764         {
4765             // Make some callsite specific observations that will feed
4766             // into the profitability model.
4767             impMakeDiscretionaryInlineObservations(impInlineInfo, compInlineResult);
4768
4769             // None of those observations should have changed the
4770             // inline's viability.
4771             assert(compInlineResult->IsCandidate());
4772
4773             if (isInlining)
4774             {
4775                 // Assess profitability...
4776                 CORINFO_METHOD_INFO* methodInfo = &impInlineInfo->inlineCandidateInfo->methInfo;
4777                 compInlineResult->DetermineProfitability(methodInfo);
4778
4779                 if (compInlineResult->IsFailure())
4780                 {
4781                     impInlineRoot()->m_inlineStrategy->NoteUnprofitable();
4782                     JITDUMP("\n\nInline expansion aborted, inline not profitable\n");
4783                     return;
4784                 }
4785                 else
4786                 {
4787                     // The inline is still viable.
4788                     assert(compInlineResult->IsCandidate());
4789                 }
4790             }
4791             else
4792             {
4793                 // Prejit root case. Profitability assessment for this
4794                 // is done over in compCompileHelper.
4795             }
4796         }
4797     }
4798
4799     // None of the local vars in the inlinee should have address taken or been written to.
4800     // Therefore we should NOT need to enter this "if" statement.
4801     if (!isInlining && !info.compIsStatic)
4802     {
4803         fgAdjustForAddressExposedOrWrittenThis();
4804     }
4805 }
4806
4807 #ifdef _PREFAST_
4808 #pragma warning(pop)
4809 #endif
4810
4811 //------------------------------------------------------------------------
4812 // fgAdjustForAddressExposedOrWrittenThis: update var table for cases
4813 //   where the this pointer value can change.
4814 //
4815 // Notes:
4816 //    Modifies lvaArg0Var to refer to a temp if the value of 'this' can
4817 //    change. The original this (info.compThisArg) then remains
4818 //    unmodified in the method.  fgAddInternal is reponsible for
4819 //    adding the code to copy the initial this into the temp.
4820
4821 void Compiler::fgAdjustForAddressExposedOrWrittenThis()
4822 {
4823     // Optionally enable adjustment during stress.
4824     if (!tiVerificationNeeded && compStressCompile(STRESS_GENERIC_VARN, 15))
4825     {
4826         lvaTable[info.compThisArg].lvArgWrite = true;
4827     }
4828
4829     // If this is exposed or written to, create a temp for the modifiable this
4830     if (lvaTable[info.compThisArg].lvAddrExposed || lvaTable[info.compThisArg].lvArgWrite)
4831     {
4832         // If there is a "ldarga 0" or "starg 0", grab and use the temp.
4833         lvaArg0Var = lvaGrabTemp(false DEBUGARG("Address-exposed, or written this pointer"));
4834         noway_assert(lvaArg0Var > (unsigned)info.compThisArg);
4835         lvaTable[lvaArg0Var].lvType            = lvaTable[info.compThisArg].TypeGet();
4836         lvaTable[lvaArg0Var].lvAddrExposed     = lvaTable[info.compThisArg].lvAddrExposed;
4837         lvaTable[lvaArg0Var].lvDoNotEnregister = lvaTable[info.compThisArg].lvDoNotEnregister;
4838 #ifdef DEBUG
4839         lvaTable[lvaArg0Var].lvVMNeedsStackAddr = lvaTable[info.compThisArg].lvVMNeedsStackAddr;
4840         lvaTable[lvaArg0Var].lvLiveInOutOfHndlr = lvaTable[info.compThisArg].lvLiveInOutOfHndlr;
4841         lvaTable[lvaArg0Var].lvLclFieldExpr     = lvaTable[info.compThisArg].lvLclFieldExpr;
4842         lvaTable[lvaArg0Var].lvLiveAcrossUCall  = lvaTable[info.compThisArg].lvLiveAcrossUCall;
4843 #endif
4844         lvaTable[lvaArg0Var].lvArgWrite    = lvaTable[info.compThisArg].lvArgWrite;
4845         lvaTable[lvaArg0Var].lvVerTypeInfo = lvaTable[info.compThisArg].lvVerTypeInfo;
4846
4847         // Clear the TI_FLAG_THIS_PTR in the original 'this' pointer.
4848         noway_assert(lvaTable[lvaArg0Var].lvVerTypeInfo.IsThisPtr());
4849         lvaTable[info.compThisArg].lvVerTypeInfo.ClearThisPtr();
4850         lvaTable[info.compThisArg].lvAddrExposed = false;
4851         lvaTable[info.compThisArg].lvArgWrite    = false;
4852     }
4853 }
4854
4855 //------------------------------------------------------------------------
4856 // fgObserveInlineConstants: look for operations that might get optimized
4857 //   if this method were to be inlined, and report these to the inliner.
4858 //
4859 // Arguments:
4860 //    opcode     -- MSIL opcode under consideration
4861 //    stack      -- abstract stack model at this point in the IL
4862 //    isInlining -- true if we're inlining (vs compiling a prejit root)
4863 //
4864 // Notes:
4865 //    Currently only invoked on compare and branch opcodes.
4866 //
4867 //    If we're inlining we also look at the argument values supplied by
4868 //    the caller at this call site.
4869 //
4870 //    The crude stack model may overestimate stack depth.
4871
4872 void Compiler::fgObserveInlineConstants(OPCODE opcode, const FgStack& stack, bool isInlining)
4873 {
4874     // We should be able to record inline observations.
4875     assert(compInlineResult != nullptr);
4876
4877     // The stack only has to be 1 deep for BRTRUE/FALSE
4878     bool lookForBranchCases = stack.IsStackAtLeastOneDeep();
4879
4880     if (compInlineResult->UsesLegacyPolicy())
4881     {
4882         // LegacyPolicy misses cases where the stack is really one
4883         // deep but the model says it's two deep. We need to do
4884         // likewise to preseve old behavior.
4885         lookForBranchCases &= !stack.IsStackTwoDeep();
4886     }
4887
4888     if (lookForBranchCases)
4889     {
4890         if (opcode == CEE_BRFALSE || opcode == CEE_BRFALSE_S || opcode == CEE_BRTRUE || opcode == CEE_BRTRUE_S)
4891         {
4892             unsigned slot0 = stack.GetSlot0();
4893             if (FgStack::IsArgument(slot0))
4894             {
4895                 compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_CONSTANT_TEST);
4896
4897                 if (isInlining)
4898                 {
4899                     // Check for the double whammy of an incoming constant argument
4900                     // feeding a constant test.
4901                     unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
4902                     if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
4903                     {
4904                         compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
4905                     }
4906                 }
4907             }
4908
4909             return;
4910         }
4911     }
4912
4913     // Remaining cases require at least two things on the stack.
4914     if (!stack.IsStackTwoDeep())
4915     {
4916         return;
4917     }
4918
4919     unsigned slot0 = stack.GetSlot0();
4920     unsigned slot1 = stack.GetSlot1();
4921
4922     // Arg feeds constant test
4923     if ((FgStack::IsConstant(slot0) && FgStack::IsArgument(slot1)) ||
4924         (FgStack::IsConstant(slot1) && FgStack::IsArgument(slot0)))
4925     {
4926         compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_CONSTANT_TEST);
4927     }
4928
4929     // Arg feeds range check
4930     if ((FgStack::IsArrayLen(slot0) && FgStack::IsArgument(slot1)) ||
4931         (FgStack::IsArrayLen(slot1) && FgStack::IsArgument(slot0)))
4932     {
4933         compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_RANGE_CHECK);
4934     }
4935
4936     // Check for an incoming arg that's a constant
4937     if (isInlining)
4938     {
4939         if (FgStack::IsArgument(slot0))
4940         {
4941             unsigned varNum = FgStack::SlotTypeToArgNum(slot0);
4942             if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
4943             {
4944                 compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
4945             }
4946         }
4947
4948         if (FgStack::IsArgument(slot1))
4949         {
4950             unsigned varNum = FgStack::SlotTypeToArgNum(slot1);
4951             if (impInlineInfo->inlArgInfo[varNum].argNode->OperIsConst())
4952             {
4953                 compInlineResult->Note(InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST);
4954             }
4955         }
4956     }
4957 }
4958
4959 /*****************************************************************************
4960  *
4961  *  Finally link up the bbJumpDest of the blocks together
4962  */
4963
4964 void Compiler::fgMarkBackwardJump(BasicBlock* startBlock, BasicBlock* endBlock)
4965 {
4966     noway_assert(startBlock->bbNum <= endBlock->bbNum);
4967
4968     for (BasicBlock* block = startBlock; block != endBlock->bbNext; block = block->bbNext)
4969     {
4970         if ((block->bbFlags & BBF_BACKWARD_JUMP) == 0)
4971         {
4972             block->bbFlags |= BBF_BACKWARD_JUMP;
4973         }
4974     }
4975 }
4976
4977 /*****************************************************************************
4978  *
4979  *  Finally link up the bbJumpDest of the blocks together
4980  */
4981
4982 void Compiler::fgLinkBasicBlocks()
4983 {
4984     /* Create the basic block lookup tables */
4985
4986     fgInitBBLookup();
4987
4988     /* First block is always reachable */
4989
4990     fgFirstBB->bbRefs = 1;
4991
4992     /* Walk all the basic blocks, filling in the target addresses */
4993
4994     for (BasicBlock* curBBdesc = fgFirstBB; curBBdesc; curBBdesc = curBBdesc->bbNext)
4995     {
4996         switch (curBBdesc->bbJumpKind)
4997         {
4998             case BBJ_COND:
4999             case BBJ_ALWAYS:
5000             case BBJ_LEAVE:
5001                 curBBdesc->bbJumpDest = fgLookupBB(curBBdesc->bbJumpOffs);
5002                 curBBdesc->bbJumpDest->bbRefs++;
5003                 if (curBBdesc->bbJumpDest->bbNum <= curBBdesc->bbNum)
5004                 {
5005                     fgMarkBackwardJump(curBBdesc->bbJumpDest, curBBdesc);
5006                 }
5007
5008                 /* Is the next block reachable? */
5009
5010                 if (curBBdesc->bbJumpKind == BBJ_ALWAYS || curBBdesc->bbJumpKind == BBJ_LEAVE)
5011                 {
5012                     break;
5013                 }
5014
5015                 if (!curBBdesc->bbNext)
5016                 {
5017                     BADCODE("Fall thru the end of a method");
5018                 }
5019
5020             // Fall through, the next block is also reachable
5021
5022             case BBJ_NONE:
5023                 curBBdesc->bbNext->bbRefs++;
5024                 break;
5025
5026             case BBJ_EHFINALLYRET:
5027             case BBJ_EHFILTERRET:
5028             case BBJ_THROW:
5029             case BBJ_RETURN:
5030                 break;
5031
5032             case BBJ_SWITCH:
5033
5034                 unsigned jumpCnt;
5035                 jumpCnt = curBBdesc->bbJumpSwt->bbsCount;
5036                 BasicBlock** jumpPtr;
5037                 jumpPtr = curBBdesc->bbJumpSwt->bbsDstTab;
5038
5039                 do
5040                 {
5041                     *jumpPtr = fgLookupBB((unsigned)*(size_t*)jumpPtr);
5042                     (*jumpPtr)->bbRefs++;
5043                     if ((*jumpPtr)->bbNum <= curBBdesc->bbNum)
5044                     {
5045                         fgMarkBackwardJump(*jumpPtr, curBBdesc);
5046                     }
5047                 } while (++jumpPtr, --jumpCnt);
5048
5049                 /* Default case of CEE_SWITCH (next block), is at end of jumpTab[] */
5050
5051                 noway_assert(*(jumpPtr - 1) == curBBdesc->bbNext);
5052                 break;
5053
5054             case BBJ_CALLFINALLY: // BBJ_CALLFINALLY and BBJ_EHCATCHRET don't appear until later
5055             case BBJ_EHCATCHRET:
5056             default:
5057                 noway_assert(!"Unexpected bbJumpKind");
5058                 break;
5059         }
5060     }
5061 }
5062
5063 /*****************************************************************************
5064  *
5065  *  Walk the instrs to create the basic blocks.
5066  */
5067
5068 void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget)
5069 {
5070     const BYTE* codeBegp = codeAddr;
5071     const BYTE* codeEndp = codeAddr + codeSize;
5072     bool        tailCall = false;
5073     unsigned    curBBoffs;
5074     BasicBlock* curBBdesc;
5075
5076     /* Clear the beginning offset for the first BB */
5077
5078     curBBoffs = 0;
5079
5080 #ifdef DEBUGGING_SUPPORT
5081     if (opts.compDbgCode && (info.compVarScopesCount > 0))
5082     {
5083         compResetScopeLists();
5084
5085         // Ignore scopes beginning at offset 0
5086         while (compGetNextEnterScope(0))
5087         { /* do nothing */
5088         }
5089         while (compGetNextExitScope(0))
5090         { /* do nothing */
5091         }
5092     }
5093 #endif
5094
5095     BBjumpKinds jmpKind;
5096
5097     do
5098     {
5099         OPCODE     opcode;
5100         unsigned   sz;
5101         unsigned   jmpAddr = DUMMY_INIT(BAD_IL_OFFSET);
5102         unsigned   bbFlags = 0;
5103         BBswtDesc* swtDsc  = nullptr;
5104         unsigned   nxtBBoffs;
5105
5106         opcode = (OPCODE)getU1LittleEndian(codeAddr);
5107         codeAddr += sizeof(__int8);
5108         jmpKind = BBJ_NONE;
5109
5110     DECODE_OPCODE:
5111
5112         /* Get the size of additional parameters */
5113
5114         noway_assert(opcode < CEE_COUNT);
5115
5116         sz = opcodeSizes[opcode];
5117
5118         switch (opcode)
5119         {
5120             signed jmpDist;
5121
5122             case CEE_PREFIX1:
5123                 if (jumpTarget[codeAddr - codeBegp] != JT_NONE)
5124                 {
5125                     BADCODE3("jump target between prefix 0xFE and opcode", " at offset %04X",
5126                              (IL_OFFSET)(codeAddr - codeBegp));
5127                 }
5128
5129                 opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr));
5130                 codeAddr += sizeof(__int8);
5131                 goto DECODE_OPCODE;
5132
5133             /* Check to see if we have a jump/return opcode */
5134
5135             case CEE_BRFALSE:
5136             case CEE_BRFALSE_S:
5137             case CEE_BRTRUE:
5138             case CEE_BRTRUE_S:
5139
5140             case CEE_BEQ:
5141             case CEE_BEQ_S:
5142             case CEE_BGE:
5143             case CEE_BGE_S:
5144             case CEE_BGE_UN:
5145             case CEE_BGE_UN_S:
5146             case CEE_BGT:
5147             case CEE_BGT_S:
5148             case CEE_BGT_UN:
5149             case CEE_BGT_UN_S:
5150             case CEE_BLE:
5151             case CEE_BLE_S:
5152             case CEE_BLE_UN:
5153             case CEE_BLE_UN_S:
5154             case CEE_BLT:
5155             case CEE_BLT_S:
5156             case CEE_BLT_UN:
5157             case CEE_BLT_UN_S:
5158             case CEE_BNE_UN:
5159             case CEE_BNE_UN_S:
5160
5161                 jmpKind = BBJ_COND;
5162                 goto JMP;
5163
5164             case CEE_LEAVE:
5165             case CEE_LEAVE_S:
5166
5167                 // We need to check if we are jumping out of a finally-protected try.
5168                 jmpKind = BBJ_LEAVE;
5169                 goto JMP;
5170
5171             case CEE_BR:
5172             case CEE_BR_S:
5173                 jmpKind = BBJ_ALWAYS;
5174                 goto JMP;
5175
5176             JMP:
5177
5178                 /* Compute the target address of the jump */
5179
5180                 jmpDist = (sz == 1) ? getI1LittleEndian(codeAddr) : getI4LittleEndian(codeAddr);
5181
5182                 if (compIsForInlining() && jmpDist == 0 && (opcode == CEE_BR || opcode == CEE_BR_S))
5183                 {
5184                     continue; /* NOP */
5185                 }
5186
5187                 jmpAddr = (IL_OFFSET)(codeAddr - codeBegp) + sz + jmpDist;
5188                 break;
5189
5190             case CEE_SWITCH:
5191             {
5192                 unsigned jmpBase;
5193                 unsigned jmpCnt; // # of switch cases (excluding defualt)
5194
5195                 BasicBlock** jmpTab;
5196                 BasicBlock** jmpPtr;
5197
5198                 /* Allocate the switch descriptor */
5199
5200                 swtDsc = new (this, CMK_BasicBlock) BBswtDesc;
5201
5202                 /* Read the number of entries in the table */
5203
5204                 jmpCnt = getU4LittleEndian(codeAddr);
5205                 codeAddr += 4;
5206
5207                 /* Compute  the base offset for the opcode */
5208
5209                 jmpBase = (IL_OFFSET)((codeAddr - codeBegp) + jmpCnt * sizeof(DWORD));
5210
5211                 /* Allocate the jump table */
5212
5213                 jmpPtr = jmpTab = new (this, CMK_BasicBlock) BasicBlock*[jmpCnt + 1];
5214
5215                 /* Fill in the jump table */
5216
5217                 for (unsigned count = jmpCnt; count; count--)
5218                 {
5219                     jmpDist = getI4LittleEndian(codeAddr);
5220                     codeAddr += 4;
5221
5222                     // store the offset in the pointer.  We change these in fgLinkBasicBlocks().
5223                     *jmpPtr++ = (BasicBlock*)(size_t)(jmpBase + jmpDist);
5224                 }
5225
5226                 /* Append the default label to the target table */
5227
5228                 *jmpPtr++ = (BasicBlock*)(size_t)jmpBase;
5229
5230                 /* Make sure we found the right number of labels */
5231
5232                 noway_assert(jmpPtr == jmpTab + jmpCnt + 1);
5233
5234                 /* Compute the size of the switch opcode operands */
5235
5236                 sz = sizeof(DWORD) + jmpCnt * sizeof(DWORD);
5237
5238                 /* Fill in the remaining fields of the switch descriptor */
5239
5240                 swtDsc->bbsCount  = jmpCnt + 1;
5241                 swtDsc->bbsDstTab = jmpTab;
5242
5243                 /* This is definitely a jump */
5244
5245                 jmpKind     = BBJ_SWITCH;
5246                 fgHasSwitch = true;
5247
5248 #ifndef LEGACY_BACKEND
5249                 if (opts.compProcedureSplitting)
5250                 {
5251                     // TODO-CQ: We might need to create a switch table; we won't know for sure until much later.
5252                     // However, switch tables don't work with hot/cold splitting, currently. The switch table data needs
5253                     // a relocation such that if the base (the first block after the prolog) and target of the switch
5254                     // branch are put in different sections, the difference stored in the table is updated. However, our
5255                     // relocation implementation doesn't support three different pointers (relocation address, base, and
5256                     // target). So, we need to change our switch table implementation to be more like
5257                     // JIT64: put the table in the code section, in the same hot/cold section as the switch jump itself
5258                     // (maybe immediately after the switch jump), and make the "base" address be also in that section,
5259                     // probably the address after the switch jump.
5260                     opts.compProcedureSplitting = false;
5261                     JITDUMP("Turning off procedure splitting for this method, as it might need switch tables; "
5262                             "implementation limitation.\n");
5263                 }
5264 #endif // !LEGACY_BACKEND
5265             }
5266                 goto GOT_ENDP;
5267
5268             case CEE_ENDFILTER:
5269                 bbFlags |= BBF_DONT_REMOVE;
5270                 jmpKind = BBJ_EHFILTERRET;
5271                 break;
5272
5273             case CEE_ENDFINALLY:
5274                 jmpKind = BBJ_EHFINALLYRET;
5275                 break;
5276
5277             case CEE_TAILCALL:
5278                 if (compIsForInlining())
5279                 {
5280                     // TODO-CQ: We can inline some callees with explicit tail calls if we can guarantee that the calls
5281                     // can be dispatched as tail calls from the caller.
5282                     compInlineResult->NoteFatal(InlineObservation::CALLEE_EXPLICIT_TAIL_PREFIX);
5283                     return;
5284                 }
5285
5286                 __fallthrough;
5287
5288             case CEE_READONLY:
5289             case CEE_CONSTRAINED:
5290             case CEE_VOLATILE:
5291             case CEE_UNALIGNED:
5292                 // fgFindJumpTargets should have ruled out this possibility
5293                 //   (i.e. a prefix opcodes as last intruction in a block)
5294                 noway_assert(codeAddr < codeEndp);
5295
5296                 if (jumpTarget[codeAddr - codeBegp] != JT_NONE)
5297                 {
5298                     BADCODE3("jump target between prefix and an opcode", " at offset %04X",
5299                              (IL_OFFSET)(codeAddr - codeBegp));
5300                 }
5301                 break;
5302
5303             case CEE_CALL:
5304             case CEE_CALLVIRT:
5305             case CEE_CALLI:
5306             {
5307                 if (compIsForInlining() ||               // Ignore tail call in the inlinee. Period.
5308                     (!tailCall && !compTailCallStress()) // A new BB with BBJ_RETURN would have been created
5309
5310                     // after a tailcall statement.
5311                     // We need to keep this invariant if we want to stress the tailcall.
5312                     // That way, the potential (tail)call statement is always the last
5313                     // statement in the block.
5314                     // Otherwise, we will assert at the following line in fgMorphCall()
5315                     //     noway_assert(fgMorphStmt->gtNext == NULL);
5316                     )
5317                 {
5318                     // Neither .tailcall prefix, no tailcall stress. So move on.
5319                     break;
5320                 }
5321
5322                 // Make sure the code sequence is legal for the tail call.
5323                 // If so, mark this BB as having a BBJ_RETURN.
5324
5325                 if (codeAddr >= codeEndp - sz)
5326                 {
5327                     BADCODE3("No code found after the call instruction", " at offset %04X",
5328                              (IL_OFFSET)(codeAddr - codeBegp));
5329                 }
5330
5331                 if (tailCall)
5332                 {
5333                     bool isCallPopAndRet = false;
5334
5335                     // impIsTailCallILPattern uses isRecursive flag to determine whether ret in a fallthrough block is
5336                     // allowed. We don't know at this point whether the call is recursive so we conservatively pass
5337                     // false. This will only affect explicit tail calls when IL verification is not needed for the
5338                     // method.
5339                     bool isRecursive = false;
5340                     if (!impIsTailCallILPattern(tailCall, opcode, codeAddr + sz, codeEndp, isRecursive,
5341                                                 &isCallPopAndRet))
5342                     {
5343 #ifdef _TARGET_AMD64_
5344                         BADCODE3("tail call not followed by ret or pop+ret", " at offset %04X",
5345                                  (IL_OFFSET)(codeAddr - codeBegp));
5346 #else
5347                         BADCODE3("tail call not followed by ret", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5348 #endif //_TARGET_AMD64_
5349                     }
5350
5351 #ifdef _TARGET_AMD64_
5352                     if (isCallPopAndRet)
5353                     {
5354                         // By breaking here, we let pop and ret opcodes to be
5355                         // imported after tail call.  If tail prefix is honored,
5356                         // stmts corresponding to pop and ret will be removed
5357                         // in fgMorphCall().
5358                         break;
5359                     }
5360 #endif //_TARGET_AMD64_
5361                 }
5362                 else
5363                 {
5364                     OPCODE nextOpcode = (OPCODE)getU1LittleEndian(codeAddr + sz);
5365
5366                     if (nextOpcode != CEE_RET)
5367                     {
5368                         noway_assert(compTailCallStress());
5369                         // Next OPCODE is not a CEE_RET, bail the attempt to stress the tailcall.
5370                         // (I.e. We will not make a new BB after the "call" statement.)
5371                         break;
5372                     }
5373                 }
5374             }
5375
5376             /* For tail call, we just call CORINFO_HELP_TAILCALL, and it jumps to the
5377                target. So we don't need an epilog - just like CORINFO_HELP_THROW.
5378                Make the block BBJ_RETURN, but we will change it to BBJ_THROW
5379                if the tailness of the call is satisfied.
5380                NOTE : The next instruction is guaranteed to be a CEE_RET
5381                and it will create another BasicBlock. But there may be an
5382                jump directly to that CEE_RET. If we want to avoid creating
5383                an unnecessary block, we need to check if the CEE_RETURN is
5384                the target of a jump.
5385              */
5386
5387             // fall-through
5388
5389             case CEE_JMP:
5390             /* These are equivalent to a return from the current method
5391                But instead of directly returning to the caller we jump and
5392                execute something else in between */
5393             case CEE_RET:
5394                 jmpKind = BBJ_RETURN;
5395                 break;
5396
5397             case CEE_THROW:
5398             case CEE_RETHROW:
5399                 jmpKind = BBJ_THROW;
5400                 break;
5401
5402 #ifdef DEBUG
5403 // make certain we did not forget any flow of control instructions
5404 // by checking the 'ctrl' field in opcode.def. First filter out all
5405 // non-ctrl instructions
5406 #define BREAK(name)                                                                                                    \
5407     case name:                                                                                                         \
5408         break;
5409 #define NEXT(name)                                                                                                     \
5410     case name:                                                                                                         \
5411         break;
5412 #define CALL(name)
5413 #define THROW(name)
5414 #undef RETURN // undef contract RETURN macro
5415 #define RETURN(name)
5416 #define META(name)
5417 #define BRANCH(name)
5418 #define COND_BRANCH(name)
5419 #define PHI(name)
5420
5421 #define OPDEF(name, string, pop, push, oprType, opcType, l, s1, s2, ctrl) ctrl(name)
5422 #include "opcode.def"
5423 #undef OPDEF
5424
5425 #undef PHI
5426 #undef BREAK
5427 #undef CALL
5428 #undef NEXT
5429 #undef THROW
5430 #undef RETURN
5431 #undef META
5432 #undef BRANCH
5433 #undef COND_BRANCH
5434
5435             // These ctrl-flow opcodes don't need any special handling
5436             case CEE_NEWOBJ: // CTRL_CALL
5437                 break;
5438
5439             // what's left are forgotten instructions
5440             default:
5441                 BADCODE("Unrecognized control Opcode");
5442                 break;
5443 #else  // !DEBUG
5444             default:
5445                 break;
5446 #endif // !DEBUG
5447         }
5448
5449         /* Jump over the operand */
5450
5451         codeAddr += sz;
5452
5453     GOT_ENDP:
5454
5455         tailCall = (opcode == CEE_TAILCALL);
5456
5457         /* Make sure a jump target isn't in the middle of our opcode */
5458
5459         if (sz)
5460         {
5461             IL_OFFSET offs = (IL_OFFSET)(codeAddr - codeBegp) - sz; // offset of the operand
5462
5463             for (unsigned i = 0; i < sz; i++, offs++)
5464             {
5465                 if (jumpTarget[offs] != JT_NONE)
5466                 {
5467                     BADCODE3("jump into the middle of an opcode", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5468                 }
5469             }
5470         }
5471
5472         /* Compute the offset of the next opcode */
5473
5474         nxtBBoffs = (IL_OFFSET)(codeAddr - codeBegp);
5475
5476 #ifdef DEBUGGING_SUPPORT
5477
5478         bool foundScope = false;
5479
5480         if (opts.compDbgCode && (info.compVarScopesCount > 0))
5481         {
5482             while (compGetNextEnterScope(nxtBBoffs))
5483             {
5484                 foundScope = true;
5485             }
5486             while (compGetNextExitScope(nxtBBoffs))
5487             {
5488                 foundScope = true;
5489             }
5490         }
5491 #endif
5492
5493         /* Do we have a jump? */
5494
5495         if (jmpKind == BBJ_NONE)
5496         {
5497             /* No jump; make sure we don't fall off the end of the function */
5498
5499             if (codeAddr == codeEndp)
5500             {
5501                 BADCODE3("missing return opcode", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp));
5502             }
5503
5504             /* If a label follows this opcode, we'll have to make a new BB */
5505
5506             bool makeBlock = (jumpTarget[nxtBBoffs] != JT_NONE);
5507
5508 #ifdef DEBUGGING_SUPPORT
5509             if (!makeBlock && foundScope)
5510             {
5511                 makeBlock = true;
5512 #ifdef DEBUG
5513                 if (verbose)
5514                 {
5515                     printf("Splitting at BBoffs = %04u\n", nxtBBoffs);
5516                 }
5517 #endif // DEBUG
5518             }
5519 #endif // DEBUGGING_SUPPORT
5520
5521             if (!makeBlock)
5522             {
5523                 continue;
5524             }
5525         }
5526
5527         /* We need to create a new basic block */
5528
5529         curBBdesc = fgNewBasicBlock(jmpKind);
5530
5531         curBBdesc->bbFlags |= bbFlags;
5532         curBBdesc->bbRefs = 0;
5533
5534         curBBdesc->bbCodeOffs    = curBBoffs;
5535         curBBdesc->bbCodeOffsEnd = nxtBBoffs;
5536
5537         unsigned profileWeight;
5538         if (fgGetProfileWeightForBasicBlock(curBBoffs, &profileWeight))
5539         {
5540             curBBdesc->setBBProfileWeight(profileWeight);
5541             if (profileWeight == 0)
5542             {
5543                 curBBdesc->bbSetRunRarely();
5544             }
5545             else
5546             {
5547                 // Note that bbNewBasicBlock (called from fgNewBasicBlock) may have
5548                 // already marked the block as rarely run.  In that case (and when we know
5549                 // that the block profile weight is non-zero) we want to unmark that.
5550
5551                 curBBdesc->bbFlags &= ~BBF_RUN_RARELY;
5552             }
5553         }
5554
5555         switch (jmpKind)
5556         {
5557             case BBJ_SWITCH:
5558                 curBBdesc->bbJumpSwt = swtDsc;
5559                 break;
5560
5561             case BBJ_COND:
5562             case BBJ_ALWAYS:
5563             case BBJ_LEAVE:
5564                 noway_assert(jmpAddr != DUMMY_INIT(BAD_IL_OFFSET));
5565                 curBBdesc->bbJumpOffs = jmpAddr;
5566                 break;
5567
5568             default:
5569                 break;
5570         }
5571
5572         DBEXEC(verbose, curBBdesc->dspBlockHeader(this, false, false, false));
5573
5574         /* Remember where the next BB will start */
5575
5576         curBBoffs = nxtBBoffs;
5577     } while (codeAddr < codeEndp);
5578
5579     noway_assert(codeAddr == codeEndp);
5580
5581     /* Finally link up the bbJumpDest of the blocks together */
5582
5583     fgLinkBasicBlocks();
5584 }
5585
5586 /*****************************************************************************
5587  *
5588  *  Main entry point to discover the basic blocks for the current function.
5589  */
5590
5591 void Compiler::fgFindBasicBlocks()
5592 {
5593 #ifdef DEBUG
5594     if (verbose)
5595     {
5596         printf("*************** In fgFindBasicBlocks() for %s\n", info.compFullName);
5597     }
5598 #endif
5599
5600     /* Allocate the 'jump target' vector
5601      *
5602      *  We need one extra byte as we mark
5603      *  jumpTarget[info.compILCodeSize] with JT_ADDR
5604      *  when we need to add a dummy block
5605      *  to record the end of a try or handler region.
5606      */
5607     BYTE* jumpTarget = new (this, CMK_Unknown) BYTE[info.compILCodeSize + 1];
5608     memset(jumpTarget, JT_NONE, info.compILCodeSize + 1);
5609     noway_assert(JT_NONE == 0);
5610
5611     /* Walk the instrs to find all jump targets */
5612
5613     fgFindJumpTargets(info.compCode, info.compILCodeSize, jumpTarget);
5614     if (compDonotInline())
5615     {
5616         return;
5617     }
5618
5619     unsigned XTnum;
5620
5621     /* Are there any exception handlers? */
5622
5623     if (info.compXcptnsCount > 0)
5624     {
5625         noway_assert(!compIsForInlining());
5626
5627         /* Check and mark all the exception handlers */
5628
5629         for (XTnum = 0; XTnum < info.compXcptnsCount; XTnum++)
5630         {
5631             DWORD             tmpOffset;
5632             CORINFO_EH_CLAUSE clause;
5633             info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
5634             noway_assert(clause.HandlerLength != (unsigned)-1);
5635
5636             if (clause.TryLength <= 0)
5637             {
5638                 BADCODE("try block length <=0");
5639             }
5640
5641             /* Mark the 'try' block extent and the handler itself */
5642
5643             if (clause.TryOffset > info.compILCodeSize)
5644             {
5645                 BADCODE("try offset is > codesize");
5646             }
5647             if (jumpTarget[clause.TryOffset] == JT_NONE)
5648             {
5649                 jumpTarget[clause.TryOffset] = JT_ADDR;
5650             }
5651
5652             tmpOffset = clause.TryOffset + clause.TryLength;
5653             if (tmpOffset > info.compILCodeSize)
5654             {
5655                 BADCODE("try end is > codesize");
5656             }
5657             if (jumpTarget[tmpOffset] == JT_NONE)
5658             {
5659                 jumpTarget[tmpOffset] = JT_ADDR;
5660             }
5661
5662             if (clause.HandlerOffset > info.compILCodeSize)
5663             {
5664                 BADCODE("handler offset > codesize");
5665             }
5666             if (jumpTarget[clause.HandlerOffset] == JT_NONE)
5667             {
5668                 jumpTarget[clause.HandlerOffset] = JT_ADDR;
5669             }
5670
5671             tmpOffset = clause.HandlerOffset + clause.HandlerLength;
5672             if (tmpOffset > info.compILCodeSize)
5673             {
5674                 BADCODE("handler end > codesize");
5675             }
5676             if (jumpTarget[tmpOffset] == JT_NONE)
5677             {
5678                 jumpTarget[tmpOffset] = JT_ADDR;
5679             }
5680
5681             if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5682             {
5683                 if (clause.FilterOffset > info.compILCodeSize)
5684                 {
5685                     BADCODE("filter offset > codesize");
5686                 }
5687                 if (jumpTarget[clause.FilterOffset] == JT_NONE)
5688                 {
5689                     jumpTarget[clause.FilterOffset] = JT_ADDR;
5690                 }
5691             }
5692         }
5693     }
5694
5695 #ifdef DEBUG
5696     if (verbose)
5697     {
5698         bool anyJumpTargets = false;
5699         printf("Jump targets:\n");
5700         for (unsigned i = 0; i < info.compILCodeSize + 1; i++)
5701         {
5702             if (jumpTarget[i] == JT_NONE)
5703             {
5704                 continue;
5705             }
5706
5707             anyJumpTargets = true;
5708             printf("  IL_%04x", i);
5709
5710             if (jumpTarget[i] & JT_ADDR)
5711             {
5712                 printf(" addr");
5713             }
5714             if (jumpTarget[i] & JT_MULTI)
5715             {
5716                 printf(" multi");
5717             }
5718             printf("\n");
5719         }
5720         if (!anyJumpTargets)
5721         {
5722             printf("  none\n");
5723         }
5724     }
5725 #endif // DEBUG
5726
5727     /* Now create the basic blocks */
5728
5729     fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget);
5730
5731     if (compIsForInlining())
5732     {
5733         if (compInlineResult->IsFailure())
5734         {
5735             return;
5736         }
5737
5738         bool hasReturnBlocks           = false;
5739         bool hasMoreThanOneReturnBlock = false;
5740
5741         for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
5742         {
5743             if (block->bbJumpKind == BBJ_RETURN)
5744             {
5745                 if (hasReturnBlocks)
5746                 {
5747                     hasMoreThanOneReturnBlock = true;
5748                     break;
5749                 }
5750
5751                 hasReturnBlocks = true;
5752             }
5753         }
5754
5755         if (!hasReturnBlocks && !compInlineResult->UsesLegacyPolicy())
5756         {
5757             //
5758             // Mark the call node as "no return". The inliner might ignore CALLEE_DOES_NOT_RETURN and
5759             // fail inline for a different reasons. In that case we still want to make the "no return"
5760             // information available to the caller as it can impact caller's code quality.
5761             //
5762
5763             impInlineInfo->iciCall->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN;
5764         }
5765
5766         compInlineResult->NoteBool(InlineObservation::CALLEE_DOES_NOT_RETURN, !hasReturnBlocks);
5767
5768         if (compInlineResult->IsFailure())
5769         {
5770             return;
5771         }
5772
5773         noway_assert(info.compXcptnsCount == 0);
5774         compHndBBtab = impInlineInfo->InlinerCompiler->compHndBBtab;
5775         compHndBBtabAllocCount =
5776             impInlineInfo->InlinerCompiler->compHndBBtabAllocCount; // we probably only use the table, not add to it.
5777         compHndBBtabCount    = impInlineInfo->InlinerCompiler->compHndBBtabCount;
5778         info.compXcptnsCount = impInlineInfo->InlinerCompiler->info.compXcptnsCount;
5779
5780         if (info.compRetNativeType != TYP_VOID && hasMoreThanOneReturnBlock)
5781         {
5782             // The lifetime of this var might expand multiple BBs. So it is a long lifetime compiler temp.
5783             lvaInlineeReturnSpillTemp = lvaGrabTemp(false DEBUGARG("Inline candidate multiple BBJ_RETURN spill temp"));
5784             lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetNativeType;
5785         }
5786         return;
5787     }
5788
5789     /* Mark all blocks within 'try' blocks as such */
5790
5791     if (info.compXcptnsCount == 0)
5792     {
5793         return;
5794     }
5795
5796     if (info.compXcptnsCount > MAX_XCPTN_INDEX)
5797     {
5798         IMPL_LIMITATION("too many exception clauses");
5799     }
5800
5801     /* Allocate the exception handler table */
5802
5803     fgAllocEHTable();
5804
5805     /* Assume we don't need to sort the EH table (such that nested try/catch
5806      * appear before their try or handler parent). The EH verifier will notice
5807      * when we do need to sort it.
5808      */
5809
5810     fgNeedToSortEHTable = false;
5811
5812     verInitEHTree(info.compXcptnsCount);
5813     EHNodeDsc* initRoot = ehnNext; // remember the original root since
5814                                    // it may get modified during insertion
5815
5816     // Annotate BBs with exception handling information required for generating correct eh code
5817     // as well as checking for correct IL
5818
5819     EHblkDsc* HBtab;
5820
5821     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
5822     {
5823         CORINFO_EH_CLAUSE clause;
5824         info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
5825         noway_assert(clause.HandlerLength != (unsigned)-1); // @DEPRECATED
5826
5827 #ifdef DEBUG
5828         if (verbose)
5829         {
5830             dispIncomingEHClause(XTnum, clause);
5831         }
5832 #endif // DEBUG
5833
5834         IL_OFFSET tryBegOff    = clause.TryOffset;
5835         IL_OFFSET tryEndOff    = tryBegOff + clause.TryLength;
5836         IL_OFFSET filterBegOff = 0;
5837         IL_OFFSET hndBegOff    = clause.HandlerOffset;
5838         IL_OFFSET hndEndOff    = hndBegOff + clause.HandlerLength;
5839
5840         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5841         {
5842             filterBegOff = clause.FilterOffset;
5843         }
5844
5845         if (tryEndOff > info.compILCodeSize)
5846         {
5847             BADCODE3("end of try block beyond end of method for try", " at offset %04X", tryBegOff);
5848         }
5849         if (hndEndOff > info.compILCodeSize)
5850         {
5851             BADCODE3("end of hnd block beyond end of method for try", " at offset %04X", tryBegOff);
5852         }
5853
5854         HBtab->ebdTryBegOffset    = tryBegOff;
5855         HBtab->ebdTryEndOffset    = tryEndOff;
5856         HBtab->ebdFilterBegOffset = filterBegOff;
5857         HBtab->ebdHndBegOffset    = hndBegOff;
5858         HBtab->ebdHndEndOffset    = hndEndOff;
5859
5860         /* Convert the various addresses to basic blocks */
5861
5862         BasicBlock* tryBegBB = fgLookupBB(tryBegOff);
5863         BasicBlock* tryEndBB =
5864             fgLookupBB(tryEndOff); // note: this can be NULL if the try region is at the end of the function
5865         BasicBlock* hndBegBB = fgLookupBB(hndBegOff);
5866         BasicBlock* hndEndBB = nullptr;
5867         BasicBlock* filtBB   = nullptr;
5868         BasicBlock* block;
5869
5870         //
5871         // Assert that the try/hnd beginning blocks are set up correctly
5872         //
5873         if (tryBegBB == nullptr)
5874         {
5875             BADCODE("Try Clause is invalid");
5876         }
5877
5878         if (hndBegBB == nullptr)
5879         {
5880             BADCODE("Handler Clause is invalid");
5881         }
5882
5883         tryBegBB->bbFlags |= BBF_HAS_LABEL;
5884         hndBegBB->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
5885
5886 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
5887         // This will change the block weight from 0 to 1
5888         // and clear the rarely run flag
5889         hndBegBB->makeBlockHot();
5890 #else
5891         hndBegBB->bbSetRunRarely();   // handler entry points are rarely executed
5892 #endif
5893
5894         if (hndEndOff < info.compILCodeSize)
5895         {
5896             hndEndBB = fgLookupBB(hndEndOff);
5897         }
5898
5899         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5900         {
5901             filtBB = HBtab->ebdFilter = fgLookupBB(clause.FilterOffset);
5902
5903             filtBB->bbCatchTyp = BBCT_FILTER;
5904             filtBB->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
5905
5906             hndBegBB->bbCatchTyp = BBCT_FILTER_HANDLER;
5907
5908 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
5909             // This will change the block weight from 0 to 1
5910             // and clear the rarely run flag
5911             filtBB->makeBlockHot();
5912 #else
5913             filtBB->bbSetRunRarely(); // filter entry points are rarely executed
5914 #endif
5915
5916             // Mark all BBs that belong to the filter with the XTnum of the corresponding handler
5917             for (block = filtBB; /**/; block = block->bbNext)
5918             {
5919                 if (block == nullptr)
5920                 {
5921                     BADCODE3("Missing endfilter for filter", " at offset %04X", filtBB->bbCodeOffs);
5922                     return;
5923                 }
5924
5925                 // Still inside the filter
5926                 block->setHndIndex(XTnum);
5927
5928                 if (block->bbJumpKind == BBJ_EHFILTERRET)
5929                 {
5930                     // Mark catch handler as successor.
5931                     block->bbJumpDest = hndBegBB;
5932                     assert(block->bbJumpDest->bbCatchTyp == BBCT_FILTER_HANDLER);
5933                     break;
5934                 }
5935             }
5936
5937             if (!block->bbNext || block->bbNext != hndBegBB)
5938             {
5939                 BADCODE3("Filter does not immediately precede handler for filter", " at offset %04X",
5940                          filtBB->bbCodeOffs);
5941             }
5942         }
5943         else
5944         {
5945             HBtab->ebdTyp = clause.ClassToken;
5946
5947             /* Set bbCatchTyp as appropriate */
5948
5949             if (clause.Flags & CORINFO_EH_CLAUSE_FINALLY)
5950             {
5951                 hndBegBB->bbCatchTyp = BBCT_FINALLY;
5952             }
5953             else
5954             {
5955                 if (clause.Flags & CORINFO_EH_CLAUSE_FAULT)
5956                 {
5957                     hndBegBB->bbCatchTyp = BBCT_FAULT;
5958                 }
5959                 else
5960                 {
5961                     hndBegBB->bbCatchTyp = clause.ClassToken;
5962
5963                     // These values should be non-zero value that will
5964                     // not collide with real tokens for bbCatchTyp
5965                     if (clause.ClassToken == 0)
5966                     {
5967                         BADCODE("Exception catch type is Null");
5968                     }
5969
5970                     noway_assert(clause.ClassToken != BBCT_FAULT);
5971                     noway_assert(clause.ClassToken != BBCT_FINALLY);
5972                     noway_assert(clause.ClassToken != BBCT_FILTER);
5973                     noway_assert(clause.ClassToken != BBCT_FILTER_HANDLER);
5974                 }
5975             }
5976         }
5977
5978         /* Mark the initial block and last blocks in the 'try' region */
5979
5980         tryBegBB->bbFlags |= BBF_TRY_BEG | BBF_HAS_LABEL;
5981
5982         /*  Prevent future optimizations of removing the first block   */
5983         /*  of a TRY block and the first block of an exception handler */
5984
5985         tryBegBB->bbFlags |= BBF_DONT_REMOVE;
5986         hndBegBB->bbFlags |= BBF_DONT_REMOVE;
5987         hndBegBB->bbRefs++; // The first block of a handler gets an extra, "artificial" reference count.
5988
5989         if (clause.Flags & CORINFO_EH_CLAUSE_FILTER)
5990         {
5991             filtBB->bbFlags |= BBF_DONT_REMOVE;
5992             filtBB->bbRefs++; // The first block of a filter gets an extra, "artificial" reference count.
5993         }
5994
5995         tryBegBB->bbFlags |= BBF_DONT_REMOVE;
5996         hndBegBB->bbFlags |= BBF_DONT_REMOVE;
5997
5998         //
5999         // Store the info to the table of EH block handlers
6000         //
6001
6002         HBtab->ebdHandlerType = ToEHHandlerType(clause.Flags);
6003
6004         HBtab->ebdTryBeg  = tryBegBB;
6005         HBtab->ebdTryLast = (tryEndBB == nullptr) ? fgLastBB : tryEndBB->bbPrev;
6006
6007         HBtab->ebdHndBeg  = hndBegBB;
6008         HBtab->ebdHndLast = (hndEndBB == nullptr) ? fgLastBB : hndEndBB->bbPrev;
6009
6010         //
6011         // Assert that all of our try/hnd blocks are setup correctly.
6012         //
6013         if (HBtab->ebdTryLast == nullptr)
6014         {
6015             BADCODE("Try Clause is invalid");
6016         }
6017
6018         if (HBtab->ebdHndLast == nullptr)
6019         {
6020             BADCODE("Handler Clause is invalid");
6021         }
6022
6023         //
6024         // Verify that it's legal
6025         //
6026
6027         verInsertEhNode(&clause, HBtab);
6028
6029     } // end foreach handler table entry
6030
6031     fgSortEHTable();
6032
6033     // Next, set things related to nesting that depend on the sorting being complete.
6034
6035     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
6036     {
6037         /* Mark all blocks in the finally/fault or catch clause */
6038
6039         BasicBlock* tryBegBB = HBtab->ebdTryBeg;
6040         BasicBlock* hndBegBB = HBtab->ebdHndBeg;
6041
6042         IL_OFFSET tryBegOff = HBtab->ebdTryBegOffset;
6043         IL_OFFSET tryEndOff = HBtab->ebdTryEndOffset;
6044
6045         IL_OFFSET hndBegOff = HBtab->ebdHndBegOffset;
6046         IL_OFFSET hndEndOff = HBtab->ebdHndEndOffset;
6047
6048         BasicBlock* block;
6049
6050         for (block = hndBegBB; block && (block->bbCodeOffs < hndEndOff); block = block->bbNext)
6051         {
6052             if (!block->hasHndIndex())
6053             {
6054                 block->setHndIndex(XTnum);
6055             }
6056
6057             // All blocks in a catch handler or filter are rarely run, except the entry
6058             if ((block != hndBegBB) && (hndBegBB->bbCatchTyp != BBCT_FINALLY))
6059             {
6060                 block->bbSetRunRarely();
6061             }
6062         }
6063
6064         /* Mark all blocks within the covered range of the try */
6065
6066         for (block = tryBegBB; block && (block->bbCodeOffs < tryEndOff); block = block->bbNext)
6067         {
6068             /* Mark this BB as belonging to a 'try' block */
6069
6070             if (!block->hasTryIndex())
6071             {
6072                 block->setTryIndex(XTnum);
6073             }
6074
6075 #ifdef DEBUG
6076             /* Note: the BB can't span the 'try' block */
6077
6078             if (!(block->bbFlags & BBF_INTERNAL))
6079             {
6080                 noway_assert(tryBegOff <= block->bbCodeOffs);
6081                 noway_assert(tryEndOff >= block->bbCodeOffsEnd || tryEndOff == tryBegOff);
6082             }
6083 #endif
6084         }
6085
6086 /*  Init ebdHandlerNestingLevel of current clause, and bump up value for all
6087  *  enclosed clauses (which have to be before it in the table).
6088  *  Innermost try-finally blocks must precede outermost
6089  *  try-finally blocks.
6090  */
6091
6092 #if !FEATURE_EH_FUNCLETS
6093         HBtab->ebdHandlerNestingLevel = 0;
6094 #endif // !FEATURE_EH_FUNCLETS
6095
6096         HBtab->ebdEnclosingTryIndex = EHblkDsc::NO_ENCLOSING_INDEX;
6097         HBtab->ebdEnclosingHndIndex = EHblkDsc::NO_ENCLOSING_INDEX;
6098
6099         noway_assert(XTnum < compHndBBtabCount);
6100         noway_assert(XTnum == ehGetIndex(HBtab));
6101
6102         for (EHblkDsc* xtab = compHndBBtab; xtab < HBtab; xtab++)
6103         {
6104 #if !FEATURE_EH_FUNCLETS
6105             if (jitIsBetween(xtab->ebdHndBegOffs(), hndBegOff, hndEndOff))
6106             {
6107                 xtab->ebdHandlerNestingLevel++;
6108             }
6109 #endif // !FEATURE_EH_FUNCLETS
6110
6111             /* If we haven't recorded an enclosing try index for xtab then see
6112              *  if this EH region should be recorded.  We check if the
6113              *  first offset in the xtab lies within our region.  If so,
6114              *  the last offset also must lie within the region, due to
6115              *  nesting rules. verInsertEhNode(), below, will check for proper nesting.
6116              */
6117             if (xtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
6118             {
6119                 bool begBetween = jitIsBetween(xtab->ebdTryBegOffs(), tryBegOff, tryEndOff);
6120                 if (begBetween)
6121                 {
6122                     // Record the enclosing scope link
6123                     xtab->ebdEnclosingTryIndex = (unsigned short)XTnum;
6124                 }
6125             }
6126
6127             /* Do the same for the enclosing handler index.
6128              */
6129             if (xtab->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX)
6130             {
6131                 bool begBetween = jitIsBetween(xtab->ebdTryBegOffs(), hndBegOff, hndEndOff);
6132                 if (begBetween)
6133                 {
6134                     // Record the enclosing scope link
6135                     xtab->ebdEnclosingHndIndex = (unsigned short)XTnum;
6136                 }
6137             }
6138         }
6139
6140     } // end foreach handler table entry
6141
6142 #if !FEATURE_EH_FUNCLETS
6143
6144     EHblkDsc* HBtabEnd;
6145     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
6146     {
6147         if (ehMaxHndNestingCount <= HBtab->ebdHandlerNestingLevel)
6148             ehMaxHndNestingCount = HBtab->ebdHandlerNestingLevel + 1;
6149     }
6150
6151 #endif // !FEATURE_EH_FUNCLETS
6152
6153 #ifndef DEBUG
6154     if (tiVerificationNeeded)
6155 #endif
6156     {
6157         // always run these checks for a debug build
6158         verCheckNestingLevel(initRoot);
6159     }
6160
6161 #ifndef DEBUG
6162     // fgNormalizeEH assumes that this test has been passed.  And Ssa assumes that fgNormalizeEHTable
6163     // has been run.  So do this unless we're in minOpts mode (and always in debug).
6164     if (tiVerificationNeeded || !opts.MinOpts())
6165 #endif
6166     {
6167         fgCheckBasicBlockControlFlow();
6168     }
6169
6170 #ifdef DEBUG
6171     if (verbose)
6172     {
6173         JITDUMP("*************** After fgFindBasicBlocks() has created the EH table\n");
6174         fgDispHandlerTab();
6175     }
6176
6177     // We can't verify the handler table until all the IL legality checks have been done (above), since bad IL
6178     // (such as illegal nesting of regions) will trigger asserts here.
6179     fgVerifyHandlerTab();
6180 #endif
6181
6182     fgNormalizeEH();
6183 }
6184
6185 /*****************************************************************************
6186  * Check control flow constraints for well formed IL. Bail if any of the constraints
6187  * are violated.
6188  */
6189
6190 void Compiler::fgCheckBasicBlockControlFlow()
6191 {
6192     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6193
6194     EHblkDsc* HBtab;
6195
6196     for (BasicBlock* blk = fgFirstBB; blk; blk = blk->bbNext)
6197     {
6198         if (blk->bbFlags & BBF_INTERNAL)
6199         {
6200             continue;
6201         }
6202
6203         switch (blk->bbJumpKind)
6204         {
6205             case BBJ_NONE: // block flows into the next one (no jump)
6206
6207                 fgControlFlowPermitted(blk, blk->bbNext);
6208
6209                 break;
6210
6211             case BBJ_ALWAYS: // block does unconditional jump to target
6212
6213                 fgControlFlowPermitted(blk, blk->bbJumpDest);
6214
6215                 break;
6216
6217             case BBJ_COND: // block conditionally jumps to the target
6218
6219                 fgControlFlowPermitted(blk, blk->bbNext);
6220
6221                 fgControlFlowPermitted(blk, blk->bbJumpDest);
6222
6223                 break;
6224
6225             case BBJ_RETURN: // block ends with 'ret'
6226
6227                 if (blk->hasTryIndex() || blk->hasHndIndex())
6228                 {
6229                     BADCODE3("Return from a protected block", ". Before offset %04X", blk->bbCodeOffsEnd);
6230                 }
6231                 break;
6232
6233             case BBJ_EHFINALLYRET:
6234             case BBJ_EHFILTERRET:
6235
6236                 if (!blk->hasHndIndex()) // must be part of a handler
6237                 {
6238                     BADCODE3("Missing handler", ". Before offset %04X", blk->bbCodeOffsEnd);
6239                 }
6240
6241                 HBtab = ehGetDsc(blk->getHndIndex());
6242
6243                 // Endfilter allowed only in a filter block
6244                 if (blk->bbJumpKind == BBJ_EHFILTERRET)
6245                 {
6246                     if (!HBtab->HasFilter())
6247                     {
6248                         BADCODE("Unexpected endfilter");
6249                     }
6250                 }
6251                 // endfinally allowed only in a finally/fault block
6252                 else if (!HBtab->HasFinallyOrFaultHandler())
6253                 {
6254                     BADCODE("Unexpected endfinally");
6255                 }
6256
6257                 // The handler block should be the innermost block
6258                 // Exception blocks are listed, innermost first.
6259                 if (blk->hasTryIndex() && (blk->getTryIndex() < blk->getHndIndex()))
6260                 {
6261                     BADCODE("endfinally / endfilter in nested try block");
6262                 }
6263
6264                 break;
6265
6266             case BBJ_THROW: // block ends with 'throw'
6267                 /* throw is permitted from every BB, so nothing to check */
6268                 /* importer makes sure that rethrow is done from a catch */
6269                 break;
6270
6271             case BBJ_LEAVE: // block always jumps to the target, maybe out of guarded
6272                             // region. Used temporarily until importing
6273                 fgControlFlowPermitted(blk, blk->bbJumpDest, TRUE);
6274
6275                 break;
6276
6277             case BBJ_SWITCH: // block ends with a switch statement
6278
6279                 BBswtDesc* swtDesc;
6280                 swtDesc = blk->bbJumpSwt;
6281
6282                 assert(swtDesc);
6283
6284                 unsigned i;
6285                 for (i = 0; i < swtDesc->bbsCount; i++)
6286                 {
6287                     fgControlFlowPermitted(blk, swtDesc->bbsDstTab[i]);
6288                 }
6289
6290                 break;
6291
6292             case BBJ_EHCATCHRET:  // block ends with a leave out of a catch (only #if FEATURE_EH_FUNCLETS)
6293             case BBJ_CALLFINALLY: // block always calls the target finally
6294             default:
6295                 noway_assert(!"Unexpected bbJumpKind"); // these blocks don't get created until importing
6296                 break;
6297         }
6298     }
6299 }
6300
6301 /****************************************************************************
6302  * Check that the leave from the block is legal.
6303  * Consider removing this check here if we  can do it cheaply during importing
6304  */
6305
6306 void Compiler::fgControlFlowPermitted(BasicBlock* blkSrc, BasicBlock* blkDest, BOOL isLeave)
6307 {
6308     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6309
6310     unsigned srcHndBeg, destHndBeg;
6311     unsigned srcHndEnd, destHndEnd;
6312     bool     srcInFilter, destInFilter;
6313     bool     srcInCatch = false;
6314
6315     EHblkDsc* srcHndTab;
6316
6317     srcHndTab = ehInitHndRange(blkSrc, &srcHndBeg, &srcHndEnd, &srcInFilter);
6318     ehInitHndRange(blkDest, &destHndBeg, &destHndEnd, &destInFilter);
6319
6320     /* Impose the rules for leaving or jumping from handler blocks */
6321
6322     if (blkSrc->hasHndIndex())
6323     {
6324         srcInCatch = srcHndTab->HasCatchHandler() && srcHndTab->InHndRegionILRange(blkSrc);
6325
6326         /* Are we jumping within the same handler index? */
6327         if (BasicBlock::sameHndRegion(blkSrc, blkDest))
6328         {
6329             /* Do we have a filter clause? */
6330             if (srcHndTab->HasFilter())
6331             {
6332                 /* filters and catch handlers share same eh index  */
6333                 /* we need to check for control flow between them. */
6334                 if (srcInFilter != destInFilter)
6335                 {
6336                     if (!jitIsBetween(blkDest->bbCodeOffs, srcHndBeg, srcHndEnd))
6337                     {
6338                         BADCODE3("Illegal control flow between filter and handler", ". Before offset %04X",
6339                                  blkSrc->bbCodeOffsEnd);
6340                     }
6341                 }
6342             }
6343         }
6344         else
6345         {
6346             /* The handler indexes of blkSrc and blkDest are different */
6347             if (isLeave)
6348             {
6349                 /* Any leave instructions must not enter the dest handler from outside*/
6350                 if (!jitIsBetween(srcHndBeg, destHndBeg, destHndEnd))
6351                 {
6352                     BADCODE3("Illegal use of leave to enter handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6353                 }
6354             }
6355             else
6356             {
6357                 /* We must use a leave to exit a handler */
6358                 BADCODE3("Illegal control flow out of a handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6359             }
6360
6361             /* Do we have a filter clause? */
6362             if (srcHndTab->HasFilter())
6363             {
6364                 /* It is ok to leave from the handler block of a filter, */
6365                 /* but not from the filter block of a filter             */
6366                 if (srcInFilter != destInFilter)
6367                 {
6368                     BADCODE3("Illegal to leave a filter handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6369                 }
6370             }
6371
6372             /* We should never leave a finally handler */
6373             if (srcHndTab->HasFinallyHandler())
6374             {
6375                 BADCODE3("Illegal to leave a finally handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6376             }
6377
6378             /* We should never leave a fault handler */
6379             if (srcHndTab->HasFaultHandler())
6380             {
6381                 BADCODE3("Illegal to leave a fault handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6382             }
6383         }
6384     }
6385     else if (blkDest->hasHndIndex())
6386     {
6387         /* blkSrc was not inside a handler, but blkDst is inside a handler */
6388         BADCODE3("Illegal control flow into a handler", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6389     }
6390
6391     /* Are we jumping from a catch handler into the corresponding try? */
6392     /* VB uses this for "on error goto "                               */
6393
6394     if (isLeave && srcInCatch)
6395     {
6396         // inspect all handlers containing the jump source
6397
6398         bool      bValidJumpToTry   = false; // are we jumping in a valid way from a catch to the corresponding try?
6399         bool      bCatchHandlerOnly = true;  // false if we are jumping out of a non-catch handler
6400         EHblkDsc* ehTableEnd;
6401         EHblkDsc* ehDsc;
6402
6403         for (ehDsc = compHndBBtab, ehTableEnd = compHndBBtab + compHndBBtabCount;
6404              bCatchHandlerOnly && ehDsc < ehTableEnd; ehDsc++)
6405         {
6406             if (ehDsc->InHndRegionILRange(blkSrc))
6407             {
6408                 if (ehDsc->HasCatchHandler())
6409                 {
6410                     if (ehDsc->InTryRegionILRange(blkDest))
6411                     {
6412                         // If we already considered the jump for a different try/catch,
6413                         // we would have two overlapping try regions with two overlapping catch
6414                         // regions, which is illegal.
6415                         noway_assert(!bValidJumpToTry);
6416
6417                         // Allowed if it is the first instruction of an inner try
6418                         // (and all trys in between)
6419                         //
6420                         // try {
6421                         //  ..
6422                         // _tryAgain:
6423                         //  ..
6424                         //      try {
6425                         //      _tryNestedInner:
6426                         //        ..
6427                         //          try {
6428                         //          _tryNestedIllegal:
6429                         //            ..
6430                         //          } catch {
6431                         //            ..
6432                         //          }
6433                         //        ..
6434                         //      } catch {
6435                         //        ..
6436                         //      }
6437                         //  ..
6438                         // } catch {
6439                         //  ..
6440                         //  leave _tryAgain         // Allowed
6441                         //  ..
6442                         //  leave _tryNestedInner   // Allowed
6443                         //  ..
6444                         //  leave _tryNestedIllegal // Not Allowed
6445                         //  ..
6446                         // }
6447                         //
6448                         // Note: The leave is allowed also from catches nested inside the catch shown above.
6449
6450                         /* The common case where leave is to the corresponding try */
6451                         if (ehDsc->ebdIsSameTry(this, blkDest->getTryIndex()) ||
6452                             /* Also allowed is a leave to the start of a try which starts in the handler's try */
6453                             fgFlowToFirstBlockOfInnerTry(ehDsc->ebdTryBeg, blkDest, false))
6454                         {
6455                             bValidJumpToTry = true;
6456                         }
6457                     }
6458                 }
6459                 else
6460                 {
6461                     // We are jumping from a handler which is not a catch handler.
6462
6463                     // If it's a handler, but not a catch handler, it must be either a finally or fault
6464                     if (!ehDsc->HasFinallyOrFaultHandler())
6465                     {
6466                         BADCODE3("Handlers must be catch, finally, or fault", ". Before offset %04X",
6467                                  blkSrc->bbCodeOffsEnd);
6468                     }
6469
6470                     // Are we jumping out of this handler?
6471                     if (!ehDsc->InHndRegionILRange(blkDest))
6472                     {
6473                         bCatchHandlerOnly = false;
6474                     }
6475                 }
6476             }
6477             else if (ehDsc->InFilterRegionILRange(blkSrc))
6478             {
6479                 // Are we jumping out of a filter?
6480                 if (!ehDsc->InFilterRegionILRange(blkDest))
6481                 {
6482                     bCatchHandlerOnly = false;
6483                 }
6484             }
6485         }
6486
6487         if (bCatchHandlerOnly)
6488         {
6489             if (bValidJumpToTry)
6490             {
6491                 return;
6492             }
6493             else
6494             {
6495                 // FALL THROUGH
6496                 // This is either the case of a leave to outside the try/catch,
6497                 // or a leave to a try not nested in this try/catch.
6498                 // The first case is allowed, the second one will be checked
6499                 // later when we check the try block rules (it is illegal if we
6500                 // jump to the middle of the destination try).
6501             }
6502         }
6503         else
6504         {
6505             BADCODE3("illegal leave to exit a finally, fault or filter", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6506         }
6507     }
6508
6509     /* Check all the try block rules */
6510
6511     IL_OFFSET srcTryBeg;
6512     IL_OFFSET srcTryEnd;
6513     IL_OFFSET destTryBeg;
6514     IL_OFFSET destTryEnd;
6515
6516     ehInitTryRange(blkSrc, &srcTryBeg, &srcTryEnd);
6517     ehInitTryRange(blkDest, &destTryBeg, &destTryEnd);
6518
6519     /* Are we jumping between try indexes? */
6520     if (!BasicBlock::sameTryRegion(blkSrc, blkDest))
6521     {
6522         // Are we exiting from an inner to outer try?
6523         if (jitIsBetween(srcTryBeg, destTryBeg, destTryEnd) && jitIsBetween(srcTryEnd - 1, destTryBeg, destTryEnd))
6524         {
6525             if (!isLeave)
6526             {
6527                 BADCODE3("exit from try block without a leave", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6528             }
6529         }
6530         else if (jitIsBetween(destTryBeg, srcTryBeg, srcTryEnd))
6531         {
6532             // check that the dest Try is first instruction of an inner try
6533             if (!fgFlowToFirstBlockOfInnerTry(blkSrc, blkDest, false))
6534             {
6535                 BADCODE3("control flow into middle of try", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6536             }
6537         }
6538         else // there is no nesting relationship between src and dest
6539         {
6540             if (isLeave)
6541             {
6542                 // check that the dest Try is first instruction of an inner try sibling
6543                 if (!fgFlowToFirstBlockOfInnerTry(blkSrc, blkDest, true))
6544                 {
6545                     BADCODE3("illegal leave into middle of try", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6546                 }
6547             }
6548             else
6549             {
6550                 BADCODE3("illegal control flow in to/out of try block", ". Before offset %04X", blkSrc->bbCodeOffsEnd);
6551             }
6552         }
6553     }
6554 }
6555
6556 /*****************************************************************************
6557  *  Check that blkDest is the first block of an inner try or a sibling
6558  *    with no intervening trys in between
6559  */
6560
6561 bool Compiler::fgFlowToFirstBlockOfInnerTry(BasicBlock* blkSrc, BasicBlock* blkDest, bool sibling)
6562 {
6563     assert(!fgNormalizeEHDone); // These rules aren't quite correct after EH normalization has introduced new blocks
6564
6565     noway_assert(blkDest->hasTryIndex());
6566
6567     unsigned XTnum     = blkDest->getTryIndex();
6568     unsigned lastXTnum = blkSrc->hasTryIndex() ? blkSrc->getTryIndex() : compHndBBtabCount;
6569     noway_assert(XTnum < compHndBBtabCount);
6570     noway_assert(lastXTnum <= compHndBBtabCount);
6571
6572     EHblkDsc* HBtab = ehGetDsc(XTnum);
6573
6574     // check that we are not jumping into middle of try
6575     if (HBtab->ebdTryBeg != blkDest)
6576     {
6577         return false;
6578     }
6579
6580     if (sibling)
6581     {
6582         noway_assert(!BasicBlock::sameTryRegion(blkSrc, blkDest));
6583
6584         // find the l.u.b of the two try ranges
6585         // Set lastXTnum to the l.u.b.
6586
6587         HBtab = ehGetDsc(lastXTnum);
6588
6589         for (lastXTnum++, HBtab++; lastXTnum < compHndBBtabCount; lastXTnum++, HBtab++)
6590         {
6591             if (jitIsBetweenInclusive(blkDest->bbNum, HBtab->ebdTryBeg->bbNum, HBtab->ebdTryLast->bbNum))
6592             {
6593                 break;
6594             }
6595         }
6596     }
6597
6598     // now check there are no intervening trys between dest and l.u.b
6599     // (it is ok to have intervening trys as long as they all start at
6600     //  the same code offset)
6601
6602     HBtab = ehGetDsc(XTnum);
6603
6604     for (XTnum++, HBtab++; XTnum < lastXTnum; XTnum++, HBtab++)
6605     {
6606         if (HBtab->ebdTryBeg->bbNum < blkDest->bbNum && blkDest->bbNum <= HBtab->ebdTryLast->bbNum)
6607         {
6608             return false;
6609         }
6610     }
6611
6612     return true;
6613 }
6614
6615 /*****************************************************************************
6616  *  Returns the handler nesting level of the block.
6617  *  *pFinallyNesting is set to the nesting level of the inner-most
6618  *  finally-protected try the block is in.
6619  */
6620
6621 unsigned Compiler::fgGetNestingLevel(BasicBlock* block, unsigned* pFinallyNesting)
6622 {
6623     unsigned  curNesting = 0;            // How many handlers is the block in
6624     unsigned  tryFin     = (unsigned)-1; // curNesting when we see innermost finally-protected try
6625     unsigned  XTnum;
6626     EHblkDsc* HBtab;
6627
6628     /* We find the block's handler nesting level by walking over the
6629        complete exception table and find enclosing clauses. */
6630
6631     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
6632     {
6633         noway_assert(HBtab->ebdTryBeg && HBtab->ebdHndBeg);
6634
6635         if (HBtab->HasFinallyHandler() && (tryFin == (unsigned)-1) && bbInTryRegions(XTnum, block))
6636         {
6637             tryFin = curNesting;
6638         }
6639         else if (bbInHandlerRegions(XTnum, block))
6640         {
6641             curNesting++;
6642         }
6643     }
6644
6645     if (tryFin == (unsigned)-1)
6646     {
6647         tryFin = curNesting;
6648     }
6649
6650     if (pFinallyNesting)
6651     {
6652         *pFinallyNesting = curNesting - tryFin;
6653     }
6654
6655     return curNesting;
6656 }
6657
6658 /*****************************************************************************
6659  *
6660  *  Import the basic blocks of the procedure.
6661  */
6662
6663 void Compiler::fgImport()
6664 {
6665     fgHasPostfix = false;
6666
6667     impImport(fgFirstBB);
6668
6669     if (!(opts.eeFlags & CORJIT_FLG_SKIP_VERIFICATION))
6670     {
6671         CorInfoMethodRuntimeFlags verFlag;
6672         verFlag = tiIsVerifiableCode ? CORINFO_FLG_VERIFIABLE : CORINFO_FLG_UNVERIFIABLE;
6673         info.compCompHnd->setMethodAttribs(info.compMethodHnd, verFlag);
6674     }
6675 }
6676
6677 /*****************************************************************************
6678  * This function returns true if tree is a node with a call
6679  * that unconditionally throws an exception
6680  */
6681
6682 bool Compiler::fgIsThrow(GenTreePtr tree)
6683 {
6684     if ((tree->gtOper != GT_CALL) || (tree->gtCall.gtCallType != CT_HELPER))
6685     {
6686         return false;
6687     }
6688
6689     // TODO-Throughput: Replace all these calls to eeFindHelper() with a table based lookup
6690
6691     if ((tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_OVERFLOW)) ||
6692         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_VERIFICATION)) ||
6693         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_RNGCHKFAIL)) ||
6694         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWDIVZERO)) ||
6695 #if COR_JIT_EE_VERSION > 460
6696         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWNULLREF)) ||
6697 #endif // COR_JIT_EE_VERSION
6698         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW)) ||
6699         (tree->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_RETHROW)))
6700     {
6701         noway_assert(tree->gtFlags & GTF_CALL);
6702         noway_assert(tree->gtFlags & GTF_EXCEPT);
6703         return true;
6704     }
6705
6706     // TODO-CQ: there are a bunch of managed methods in [mscorlib]System.ThrowHelper
6707     // that would be nice to recognize.
6708
6709     return false;
6710 }
6711
6712 /*****************************************************************************
6713  * This function returns true for blocks that are in different hot-cold regions.
6714  * It returns false when the blocks are both in the same regions
6715  */
6716
6717 bool Compiler::fgInDifferentRegions(BasicBlock* blk1, BasicBlock* blk2)
6718 {
6719     noway_assert(blk1 != nullptr);
6720     noway_assert(blk2 != nullptr);
6721
6722     if (fgFirstColdBlock == nullptr)
6723     {
6724         return false;
6725     }
6726
6727     // If one block is Hot and the other is Cold then we are in different regions
6728     return ((blk1->bbFlags & BBF_COLD) != (blk2->bbFlags & BBF_COLD));
6729 }
6730
6731 bool Compiler::fgIsBlockCold(BasicBlock* blk)
6732 {
6733     noway_assert(blk != nullptr);
6734
6735     if (fgFirstColdBlock == nullptr)
6736     {
6737         return false;
6738     }
6739
6740     return ((blk->bbFlags & BBF_COLD) != 0);
6741 }
6742
6743 /*****************************************************************************
6744  * This function returns true if tree is a GT_COMMA node with a call
6745  * that unconditionally throws an exception
6746  */
6747
6748 bool Compiler::fgIsCommaThrow(GenTreePtr tree, bool forFolding /* = false */)
6749 {
6750     // Instead of always folding comma throws,
6751     // with stress enabled we only fold half the time
6752
6753     if (forFolding && compStressCompile(STRESS_FOLD, 50))
6754     {
6755         return false; /* Don't fold */
6756     }
6757
6758     /* Check for cast of a GT_COMMA with a throw overflow */
6759     if ((tree->gtOper == GT_COMMA) && (tree->gtFlags & GTF_CALL) && (tree->gtFlags & GTF_EXCEPT))
6760     {
6761         return (fgIsThrow(tree->gtOp.gtOp1));
6762     }
6763     return false;
6764 }
6765
6766 //------------------------------------------------------------------------
6767 // fgIsIndirOfAddrOfLocal: Determine whether "tree" is an indirection of a local.
6768 //
6769 // Arguments:
6770 //    tree - The tree node under consideration
6771 //
6772 // Return Value:
6773 //    If "tree" is a indirection (GT_IND, GT_BLK, or GT_OBJ) whose arg is an ADDR,
6774 //    whose arg in turn is a LCL_VAR, return that LCL_VAR node, else nullptr.
6775 //
6776 // static
6777 GenTreePtr Compiler::fgIsIndirOfAddrOfLocal(GenTreePtr tree)
6778 {
6779     GenTreePtr res = nullptr;
6780     if (tree->OperIsIndir())
6781     {
6782         GenTreePtr addr = tree->AsIndir()->Addr();
6783
6784         // Post rationalization, we can have Indir(Lea(..) trees. Therefore to recognize
6785         // Indir of addr of a local, skip over Lea in Indir(Lea(base, index, scale, offset))
6786         // to get to base variable.
6787         if (addr->OperGet() == GT_LEA)
6788         {
6789             // We use this method in backward dataflow after liveness computation - fgInterBlockLocalVarLiveness().
6790             // Therefore it is critical that we don't miss 'uses' of any local.  It may seem this method overlooks
6791             // if the index part of the LEA has indir( someAddrOperator ( lclVar ) ) to search for a use but it's
6792             // covered by the fact we're traversing the expression in execution order and we also visit the index.
6793             GenTreeAddrMode* lea  = addr->AsAddrMode();
6794             GenTreePtr       base = lea->Base();
6795
6796             if (base != nullptr)
6797             {
6798                 if (base->OperGet() == GT_IND)
6799                 {
6800                     return fgIsIndirOfAddrOfLocal(base);
6801                 }
6802                 // else use base as addr
6803                 addr = base;
6804             }
6805         }
6806
6807         if (addr->OperGet() == GT_ADDR)
6808         {
6809             GenTreePtr lclvar = addr->gtOp.gtOp1;
6810             if (lclvar->OperGet() == GT_LCL_VAR)
6811             {
6812                 res = lclvar;
6813             }
6814         }
6815         else if (addr->OperGet() == GT_LCL_VAR_ADDR)
6816         {
6817             res = addr;
6818         }
6819     }
6820     return res;
6821 }
6822
6823 GenTreePtr Compiler::fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfoHelpFunc helper)
6824 {
6825     bool     bNeedClassID = true;
6826     unsigned callFlags    = 0;
6827
6828     var_types type = TYP_BYREF;
6829
6830     // This is sort of ugly, as we have knowledge of what the helper is returning.
6831     // We need the return type.
6832     switch (helper)
6833     {
6834         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
6835             bNeedClassID = false;
6836             __fallthrough;
6837
6838         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
6839             callFlags |= GTF_CALL_HOISTABLE;
6840             __fallthrough;
6841
6842         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
6843         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
6844         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
6845         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
6846         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
6847             // type = TYP_BYREF;
6848             break;
6849
6850         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
6851             bNeedClassID = false;
6852             __fallthrough;
6853
6854         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
6855             callFlags |= GTF_CALL_HOISTABLE;
6856             __fallthrough;
6857
6858         case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
6859         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
6860         case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
6861         case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS:
6862             type = TYP_I_IMPL;
6863             break;
6864
6865         default:
6866             assert(!"unknown shared statics helper");
6867             break;
6868     }
6869
6870     GenTreeArgList* argList = nullptr;
6871
6872     GenTreePtr opModuleIDArg;
6873     GenTreePtr opClassIDArg;
6874
6875     // Get the class ID
6876     unsigned clsID;
6877     size_t   moduleID;
6878     void*    pclsID;
6879     void*    pmoduleID;
6880
6881     clsID = info.compCompHnd->getClassDomainID(cls, &pclsID);
6882
6883     moduleID = info.compCompHnd->getClassModuleIdForStatics(cls, nullptr, &pmoduleID);
6884
6885     if (!(callFlags & GTF_CALL_HOISTABLE))
6886     {
6887         if (info.compCompHnd->getClassAttribs(cls) & CORINFO_FLG_BEFOREFIELDINIT)
6888         {
6889             callFlags |= GTF_CALL_HOISTABLE;
6890         }
6891     }
6892
6893     if (pmoduleID)
6894     {
6895         opModuleIDArg = gtNewIconHandleNode((size_t)pmoduleID, GTF_ICON_CIDMID_HDL);
6896         opModuleIDArg = gtNewOperNode(GT_IND, TYP_I_IMPL, opModuleIDArg);
6897         opModuleIDArg->gtFlags |= GTF_IND_INVARIANT;
6898     }
6899     else
6900     {
6901         opModuleIDArg = gtNewIconNode((size_t)moduleID, TYP_I_IMPL);
6902     }
6903
6904     if (bNeedClassID)
6905     {
6906         if (pclsID)
6907         {
6908             opClassIDArg = gtNewIconHandleNode((size_t)pclsID, GTF_ICON_CIDMID_HDL);
6909             opClassIDArg = gtNewOperNode(GT_IND, TYP_INT, opClassIDArg);
6910             opClassIDArg->gtFlags |= GTF_IND_INVARIANT;
6911         }
6912         else
6913         {
6914             opClassIDArg = gtNewIconNode(clsID, TYP_INT);
6915         }
6916
6917         // call the helper to get the base
6918         argList = gtNewArgList(opModuleIDArg, opClassIDArg);
6919     }
6920     else
6921     {
6922         argList = gtNewArgList(opModuleIDArg);
6923     }
6924
6925     if (!s_helperCallProperties.NoThrow(helper))
6926     {
6927         callFlags |= GTF_EXCEPT;
6928     }
6929
6930     return gtNewHelperCallNode(helper, type, callFlags, argList);
6931 }
6932
6933 GenTreePtr Compiler::fgGetSharedCCtor(CORINFO_CLASS_HANDLE cls)
6934 {
6935 #ifdef FEATURE_READYTORUN_COMPILER
6936     if (opts.IsReadyToRun())
6937     {
6938         CORINFO_RESOLVED_TOKEN resolvedToken;
6939         ZeroMemory(&resolvedToken, sizeof(resolvedToken));
6940         resolvedToken.hClass = cls;
6941
6942         return impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_STATIC_BASE, TYP_BYREF);
6943     }
6944 #endif
6945
6946     // Call the shared non gc static helper, as its the fastest
6947     return fgGetStaticsCCtorHelper(cls, info.compCompHnd->getSharedCCtorHelper(cls));
6948 }
6949
6950 //
6951 // Returns true unless the address expression could
6952 // never represent a NULL
6953 //
6954 bool Compiler::fgAddrCouldBeNull(GenTreePtr addr)
6955 {
6956     if (addr->gtOper == GT_ADDR)
6957     {
6958         if (addr->gtOp.gtOp1->gtOper == GT_CNS_INT)
6959         {
6960             GenTreePtr cns1Tree = addr->gtOp.gtOp1;
6961             if (!cns1Tree->IsIconHandle())
6962             {
6963                 // Indirection of some random constant...
6964                 // It is safest just to return true
6965                 return true;
6966             }
6967         }
6968         else if (addr->gtOp.gtOp1->OperIsLocalAddr())
6969         {
6970             return false;
6971         }
6972         return false; // we can't have a null address
6973     }
6974     else if (addr->gtOper == GT_ADD)
6975     {
6976         if (addr->gtOp.gtOp1->gtOper == GT_CNS_INT)
6977         {
6978             GenTreePtr cns1Tree = addr->gtOp.gtOp1;
6979             if (!cns1Tree->IsIconHandle())
6980             {
6981                 if (!fgIsBigOffset(cns1Tree->gtIntCon.gtIconVal))
6982                 {
6983                     // Op1 was an ordinary small constant
6984                     return fgAddrCouldBeNull(addr->gtOp.gtOp2);
6985                 }
6986             }
6987             else // Op1 was a handle represented as a constant
6988             {
6989                 // Is Op2 also a constant?
6990                 if (addr->gtOp.gtOp2->gtOper == GT_CNS_INT)
6991                 {
6992                     GenTreePtr cns2Tree = addr->gtOp.gtOp2;
6993                     // Is this an addition of a handle and constant
6994                     if (!cns2Tree->IsIconHandle())
6995                     {
6996                         if (!fgIsBigOffset(cns2Tree->gtIntCon.gtIconVal))
6997                         {
6998                             // Op2 was an ordinary small constant
6999                             return false; // we can't have a null address
7000                         }
7001                     }
7002                 }
7003             }
7004         }
7005         else
7006         {
7007             // Op1 is not a constant
7008             // What about Op2?
7009             if (addr->gtOp.gtOp2->gtOper == GT_CNS_INT)
7010             {
7011                 GenTreePtr cns2Tree = addr->gtOp.gtOp2;
7012                 // Is this an addition of a small constant
7013                 if (!cns2Tree->IsIconHandle())
7014                 {
7015                     if (!fgIsBigOffset(cns2Tree->gtIntCon.gtIconVal))
7016                     {
7017                         // Op2 was an ordinary small constant
7018                         return fgAddrCouldBeNull(addr->gtOp.gtOp1);
7019                     }
7020                 }
7021             }
7022         }
7023     }
7024     return true; // default result: addr could be null
7025 }
7026
7027 /*****************************************************************************
7028  *  Optimize the call to the delegate constructor.
7029  */
7030
7031 GenTreePtr Compiler::fgOptimizeDelegateConstructor(GenTreePtr call, CORINFO_CONTEXT_HANDLE* ExactContextHnd)
7032 {
7033     noway_assert(call->gtOper == GT_CALL);
7034
7035     noway_assert(call->gtCall.gtCallType == CT_USER_FUNC);
7036     CORINFO_METHOD_HANDLE methHnd = call->gtCall.gtCallMethHnd;
7037     CORINFO_CLASS_HANDLE  clsHnd  = info.compCompHnd->getMethodClass(methHnd);
7038
7039     GenTreePtr targetMethod = call->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp1;
7040     noway_assert(targetMethod->TypeGet() == TYP_I_IMPL);
7041     genTreeOps oper = targetMethod->OperGet();
7042     if (oper == GT_FTN_ADDR || oper == GT_CALL || oper == GT_QMARK)
7043     {
7044         CORINFO_METHOD_HANDLE targetMethodHnd = nullptr;
7045         GenTreePtr            qmarkNode       = nullptr;
7046         if (oper == GT_FTN_ADDR)
7047         {
7048             targetMethodHnd = targetMethod->gtFptrVal.gtFptrMethod;
7049         }
7050         else if (oper == GT_CALL && targetMethod->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_VIRTUAL_FUNC_PTR))
7051         {
7052             GenTreePtr handleNode = targetMethod->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp2->gtOp.gtOp1;
7053
7054             if (handleNode->OperGet() == GT_CNS_INT)
7055             {
7056                 // it's a ldvirtftn case, fetch the methodhandle off the helper for ldvirtftn. It's the 3rd arg
7057                 targetMethodHnd = CORINFO_METHOD_HANDLE(handleNode->gtIntCon.gtCompileTimeHandle);
7058             }
7059             // Sometimes the argument to this is the result of a generic dictionary lookup, which shows
7060             // up as a GT_QMARK.
7061             else if (handleNode->OperGet() == GT_QMARK)
7062             {
7063                 qmarkNode = handleNode;
7064             }
7065         }
7066         // Sometimes we don't call CORINFO_HELP_VIRTUAL_FUNC_PTR but instead just call
7067         // CORINFO_HELP_RUNTIMEHANDLE_METHOD directly.
7068         else if (oper == GT_QMARK)
7069         {
7070             qmarkNode = targetMethod;
7071         }
7072         if (qmarkNode)
7073         {
7074             noway_assert(qmarkNode->OperGet() == GT_QMARK);
7075             // The argument is actually a generic dictionary lookup.  For delegate creation it looks
7076             // like:
7077             // GT_QMARK
7078             //  GT_COLON
7079             //      op1 -> call
7080             //              Arg 1 -> token (has compile time handle)
7081             //      op2 -> lclvar
7082             //
7083             //
7084             // In this case I can find the token (which is a method handle) and that is the compile time
7085             // handle.
7086             noway_assert(qmarkNode->gtOp.gtOp2->OperGet() == GT_COLON);
7087             noway_assert(qmarkNode->gtOp.gtOp2->gtOp.gtOp1->OperGet() == GT_CALL);
7088             GenTreePtr runtimeLookupCall = qmarkNode->gtOp.gtOp2->gtOp.gtOp1;
7089
7090             // This could be any of CORINFO_HELP_RUNTIMEHANDLE_(METHOD|CLASS)(_LOG?)
7091             GenTreePtr tokenNode = runtimeLookupCall->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp1;
7092             noway_assert(tokenNode->OperGet() == GT_CNS_INT);
7093             targetMethodHnd = CORINFO_METHOD_HANDLE(tokenNode->gtIntCon.gtCompileTimeHandle);
7094         }
7095
7096 #ifdef FEATURE_READYTORUN_COMPILER
7097         if (opts.IsReadyToRun())
7098         {
7099             // ReadyToRun has this optimization for a non-virtual function pointers only for now.
7100             if (oper == GT_FTN_ADDR)
7101             {
7102                 // The first argument of the helper is delegate this pointer
7103                 GenTreeArgList*      helperArgs = gtNewArgList(call->gtCall.gtCallObjp);
7104                 CORINFO_CONST_LOOKUP entryPoint;
7105
7106                 // The second argument of the helper is the target object pointers
7107                 helperArgs->gtOp.gtOp2 = gtNewArgList(call->gtCall.gtCallArgs->gtOp.gtOp1);
7108
7109                 call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, GTF_EXCEPT, helperArgs);
7110 #if COR_JIT_EE_VERSION > 460
7111                 info.compCompHnd->getReadyToRunDelegateCtorHelper(targetMethod->gtFptrVal.gtLdftnResolvedToken, clsHnd,
7112                                                                   &entryPoint);
7113 #else
7114                 info.compCompHnd->getReadyToRunHelper(targetMethod->gtFptrVal.gtLdftnResolvedToken,
7115                                                       CORINFO_HELP_READYTORUN_DELEGATE_CTOR, &entryPoint);
7116 #endif
7117                 call->gtCall.setEntryPoint(entryPoint);
7118             }
7119         }
7120         else
7121 #endif
7122             if (targetMethodHnd != nullptr)
7123         {
7124             CORINFO_METHOD_HANDLE alternateCtor = nullptr;
7125             DelegateCtorArgs      ctorData;
7126             ctorData.pMethod = info.compMethodHnd;
7127             ctorData.pArg3   = nullptr;
7128             ctorData.pArg4   = nullptr;
7129             ctorData.pArg5   = nullptr;
7130
7131             alternateCtor = info.compCompHnd->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, &ctorData);
7132             if (alternateCtor != methHnd)
7133             {
7134                 // we erase any inline info that may have been set for generics has it is not needed here,
7135                 // and in fact it will pass the wrong info to the inliner code
7136                 *ExactContextHnd = nullptr;
7137
7138                 call->gtCall.gtCallMethHnd = alternateCtor;
7139
7140                 noway_assert(call->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp2 == nullptr);
7141                 if (ctorData.pArg3)
7142                 {
7143                     call->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp2 =
7144                         gtNewArgList(gtNewIconHandleNode(size_t(ctorData.pArg3), GTF_ICON_FTN_ADDR));
7145
7146                     if (ctorData.pArg4)
7147                     {
7148                         call->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp2->gtOp.gtOp2 =
7149                             gtNewArgList(gtNewIconHandleNode(size_t(ctorData.pArg4), GTF_ICON_FTN_ADDR));
7150
7151                         if (ctorData.pArg5)
7152                         {
7153                             call->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp2->gtOp.gtOp2->gtOp.gtOp2 =
7154                                 gtNewArgList(gtNewIconHandleNode(size_t(ctorData.pArg5), GTF_ICON_FTN_ADDR));
7155                         }
7156                     }
7157                 }
7158             }
7159         }
7160     }
7161
7162     return call;
7163 }
7164
7165 bool Compiler::fgCastNeeded(GenTreePtr tree, var_types toType)
7166 {
7167     //
7168     // If tree is a relop and we need an 4-byte integer
7169     //  then we never need to insert a cast
7170     //
7171     if ((tree->OperKind() & GTK_RELOP) && (genActualType(toType) == TYP_INT))
7172     {
7173         return false;
7174     }
7175
7176     var_types fromType;
7177
7178     //
7179     // Is the tree as GT_CAST or a GT_CALL ?
7180     //
7181     if (tree->OperGet() == GT_CAST)
7182     {
7183         fromType = tree->CastToType();
7184     }
7185     else if (tree->OperGet() == GT_CALL)
7186     {
7187         fromType = (var_types)tree->gtCall.gtReturnType;
7188     }
7189     else
7190     {
7191         fromType = tree->TypeGet();
7192     }
7193
7194     //
7195     // If both types are the same then an additional cast is not necessary
7196     //
7197     if (toType == fromType)
7198     {
7199         return false;
7200     }
7201     //
7202     // If the sign-ness of the two types are different then a cast is necessary
7203     //
7204     if (varTypeIsUnsigned(toType) != varTypeIsUnsigned(fromType))
7205     {
7206         return true;
7207     }
7208     //
7209     // If the from type is the same size or smaller then an additional cast is not necessary
7210     //
7211     if (genTypeSize(toType) >= genTypeSize(fromType))
7212     {
7213         return false;
7214     }
7215
7216     //
7217     // Looks like we will need the cast
7218     //
7219     return true;
7220 }
7221
7222 // If assigning to a local var, add a cast if the target is
7223 // marked as NormalizedOnStore. Returns true if any change was made
7224 GenTreePtr Compiler::fgDoNormalizeOnStore(GenTreePtr tree)
7225 {
7226     //
7227     // Only normalize the stores in the global morph phase
7228     //
7229     if (fgGlobalMorph)
7230     {
7231         noway_assert(tree->OperGet() == GT_ASG);
7232
7233         GenTreePtr op1 = tree->gtOp.gtOp1;
7234         GenTreePtr op2 = tree->gtOp.gtOp2;
7235
7236         if (op1->gtOper == GT_LCL_VAR && genActualType(op1->TypeGet()) == TYP_INT)
7237         {
7238             // Small-typed arguments and aliased locals are normalized on load.
7239             // Other small-typed locals are normalized on store.
7240             // If it is an assignment to one of the latter, insert the cast on RHS
7241             unsigned   varNum = op1->gtLclVarCommon.gtLclNum;
7242             LclVarDsc* varDsc = &lvaTable[varNum];
7243
7244             if (varDsc->lvNormalizeOnStore())
7245             {
7246                 noway_assert(op1->gtType <= TYP_INT);
7247                 op1->gtType = TYP_INT;
7248
7249                 if (fgCastNeeded(op2, varDsc->TypeGet()))
7250                 {
7251                     op2              = gtNewCastNode(TYP_INT, op2, varDsc->TypeGet());
7252                     tree->gtOp.gtOp2 = op2;
7253
7254                     // Propagate GTF_COLON_COND
7255                     op2->gtFlags |= (tree->gtFlags & GTF_COLON_COND);
7256                 }
7257             }
7258         }
7259     }
7260
7261     return tree;
7262 }
7263
7264 /*****************************************************************************
7265  *
7266  *  Mark whether the edge "srcBB -> dstBB" forms a loop that will always
7267  *  execute a call or not.
7268  */
7269
7270 inline void Compiler::fgLoopCallTest(BasicBlock* srcBB, BasicBlock* dstBB)
7271 {
7272     /* Bail if this is not a backward edge */
7273
7274     if (srcBB->bbNum < dstBB->bbNum)
7275     {
7276         return;
7277     }
7278
7279     /* Unless we already know that there is a loop without a call here ... */
7280
7281     if (!(dstBB->bbFlags & BBF_LOOP_CALL0))
7282     {
7283         /* Check whether there is a loop path that doesn't call */
7284
7285         if (optReachWithoutCall(dstBB, srcBB))
7286         {
7287             dstBB->bbFlags |= BBF_LOOP_CALL0;
7288             dstBB->bbFlags &= ~BBF_LOOP_CALL1;
7289         }
7290         else
7291         {
7292             dstBB->bbFlags |= BBF_LOOP_CALL1;
7293         }
7294     }
7295     // if this loop will always call, then we can omit the GC Poll
7296     if ((GCPOLL_NONE != opts.compGCPollType) && (dstBB->bbFlags & BBF_LOOP_CALL1))
7297     {
7298         srcBB->bbFlags &= ~BBF_NEEDS_GCPOLL;
7299     }
7300 }
7301
7302 /*****************************************************************************
7303  *
7304  *  Mark which loops are guaranteed to execute a call.
7305  */
7306
7307 void Compiler::fgLoopCallMark()
7308 {
7309     BasicBlock* block;
7310
7311     /* If we've already marked all the block, bail */
7312
7313     if (fgLoopCallMarked)
7314     {
7315         return;
7316     }
7317
7318     fgLoopCallMarked = true;
7319
7320     /* Walk the blocks, looking for backward edges */
7321
7322     for (block = fgFirstBB; block; block = block->bbNext)
7323     {
7324         switch (block->bbJumpKind)
7325         {
7326             case BBJ_COND:
7327             case BBJ_CALLFINALLY:
7328             case BBJ_ALWAYS:
7329             case BBJ_EHCATCHRET:
7330                 fgLoopCallTest(block, block->bbJumpDest);
7331                 break;
7332
7333             case BBJ_SWITCH:
7334
7335                 unsigned jumpCnt;
7336                 jumpCnt = block->bbJumpSwt->bbsCount;
7337                 BasicBlock** jumpPtr;
7338                 jumpPtr = block->bbJumpSwt->bbsDstTab;
7339
7340                 do
7341                 {
7342                     fgLoopCallTest(block, *jumpPtr);
7343                 } while (++jumpPtr, --jumpCnt);
7344
7345                 break;
7346
7347             default:
7348                 break;
7349         }
7350     }
7351 }
7352
7353 /*****************************************************************************
7354  *
7355  *  Note the fact that the given block is a loop header.
7356  */
7357
7358 inline void Compiler::fgMarkLoopHead(BasicBlock* block)
7359 {
7360 #ifdef DEBUG
7361     if (verbose)
7362     {
7363         printf("fgMarkLoopHead: Checking loop head block BB%02u: ", block->bbNum);
7364     }
7365 #endif
7366
7367     /* Have we decided to generate fully interruptible code already? */
7368
7369     if (genInterruptible)
7370     {
7371 #ifdef DEBUG
7372         if (verbose)
7373         {
7374             printf("method is already fully interruptible\n");
7375         }
7376 #endif
7377         return;
7378     }
7379
7380     /* Is the loop head block known to execute a method call? */
7381
7382     if (block->bbFlags & BBF_GC_SAFE_POINT)
7383     {
7384 #ifdef DEBUG
7385         if (verbose)
7386         {
7387             printf("this block will execute a call\n");
7388         }
7389 #endif
7390         // single block loops that contain GC safe points don't need polls.
7391         block->bbFlags &= ~BBF_NEEDS_GCPOLL;
7392         return;
7393     }
7394
7395     /* Are dominator sets available? */
7396
7397     if (fgDomsComputed)
7398     {
7399         /* Make sure that we know which loops will always execute calls */
7400
7401         if (!fgLoopCallMarked)
7402         {
7403             fgLoopCallMark();
7404         }
7405
7406         /* Will every trip through our loop execute a call? */
7407
7408         if (block->bbFlags & BBF_LOOP_CALL1)
7409         {
7410 #ifdef DEBUG
7411             if (verbose)
7412             {
7413                 printf("this block dominates a block that will execute a call\n");
7414             }
7415 #endif
7416             return;
7417         }
7418     }
7419
7420     /*
7421      *  We have to make this method fully interruptible since we can not
7422      *  ensure that this loop will execute a call every time it loops.
7423      *
7424      *  We'll also need to generate a full register map for this method.
7425      */
7426
7427     assert(!codeGen->isGCTypeFixed());
7428
7429     if (!compCanEncodePtrArgCntMax())
7430     {
7431 #ifdef DEBUG
7432         if (verbose)
7433         {
7434             printf("a callsite with more than 1023 pushed args exists\n");
7435         }
7436 #endif
7437         return;
7438     }
7439
7440 #ifdef DEBUG
7441     if (verbose)
7442     {
7443         printf("no guaranteed callsite exits, marking method as fully interruptible\n");
7444     }
7445 #endif
7446
7447     // only enable fully interruptible code for if we're hijacking.
7448     if (GCPOLL_NONE == opts.compGCPollType)
7449     {
7450         genInterruptible = true;
7451     }
7452 }
7453
7454 GenTreePtr Compiler::fgGetCritSectOfStaticMethod()
7455 {
7456     noway_assert(!compIsForInlining());
7457
7458     noway_assert(info.compIsStatic); // This method should only be called for static methods.
7459
7460     GenTreePtr tree = nullptr;
7461
7462     CORINFO_LOOKUP_KIND kind = info.compCompHnd->getLocationOfThisType(info.compMethodHnd);
7463
7464     if (!kind.needsRuntimeLookup)
7465     {
7466         void *critSect = nullptr, **pCrit = nullptr;
7467         critSect = info.compCompHnd->getMethodSync(info.compMethodHnd, (void**)&pCrit);
7468         noway_assert((!critSect) != (!pCrit));
7469
7470         tree = gtNewIconEmbHndNode(critSect, pCrit, GTF_ICON_METHOD_HDL);
7471     }
7472     else
7473     {
7474         // Collectible types requires that for shared generic code, if we use the generic context paramter
7475         // that we report it. (This is a conservative approach, we could detect some cases particularly when the
7476         // context parameter is this that we don't need the eager reporting logic.)
7477         lvaGenericsContextUsed = true;
7478
7479         switch (kind.runtimeLookupKind)
7480         {
7481             case CORINFO_LOOKUP_THISOBJ:
7482             {
7483                 noway_assert(!"Should never get this for static method.");
7484                 break;
7485             }
7486
7487             case CORINFO_LOOKUP_CLASSPARAM:
7488             {
7489                 // In this case, the hidden param is the class handle.
7490                 tree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL);
7491                 break;
7492             }
7493
7494             case CORINFO_LOOKUP_METHODPARAM:
7495             {
7496                 // In this case, the hidden param is the method handle.
7497                 tree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL);
7498                 // Call helper CORINFO_HELP_GETCLASSFROMMETHODPARAM to get the class handle
7499                 // from the method handle.
7500                 tree = gtNewHelperCallNode(CORINFO_HELP_GETCLASSFROMMETHODPARAM, TYP_I_IMPL, 0, gtNewArgList(tree));
7501                 break;
7502             }
7503
7504             default:
7505             {
7506                 noway_assert(!"Unknown LOOKUP_KIND");
7507                 break;
7508             }
7509         }
7510
7511         noway_assert(tree); // tree should now contain the CORINFO_CLASS_HANDLE for the exact class.
7512
7513         // Given the class handle, get the pointer to the Monitor.
7514         tree = gtNewHelperCallNode(CORINFO_HELP_GETSYNCFROMCLASSHANDLE, TYP_I_IMPL, 0, gtNewArgList(tree));
7515     }
7516
7517     noway_assert(tree);
7518     return tree;
7519 }
7520
7521 #if !defined(_TARGET_X86_)
7522
7523 /*****************************************************************************
7524  *
7525  *  Add monitor enter/exit calls for synchronized methods, and a try/fault
7526  *  to ensure the 'exit' is called if the 'enter' was successful. On x86, we
7527  *  generate monitor enter/exit calls and tell the VM the code location of
7528  *  these calls. When an exception occurs between those locations, the VM
7529  *  automatically releases the lock. For non-x86 platforms, the JIT is
7530  *  responsible for creating a try/finally to protect the monitor enter/exit,
7531  *  and the VM doesn't need to know anything special about the method during
7532  *  exception processing -- it's just a normal try/finally.
7533  *
7534  *  We generate the following code:
7535  *
7536  *      void Foo()
7537  *      {
7538  *          unsigned byte acquired = 0;
7539  *          try {
7540  *              JIT_MonEnterWorker(<lock object>, &acquired);
7541  *
7542  *              *** all the preexisting user code goes here ***
7543  *
7544  *              JIT_MonExitWorker(<lock object>, &acquired);
7545  *          } fault {
7546  *              JIT_MonExitWorker(<lock object>, &acquired);
7547  *         }
7548  *      L_return:
7549  *         ret
7550  *      }
7551  *
7552  *  If the lock is actually acquired, then the 'acquired' variable is set to 1
7553  *  by the helper call. During normal exit, the finally is called, 'acquired'
7554  *  is 1, and the lock is released. If an exception occurs before the lock is
7555  *  acquired, but within the 'try' (extremely unlikely, but possible), 'acquired'
7556  *  will be 0, and the monitor exit call will quickly return without attempting
7557  *  to release the lock. Otherwise, 'acquired' will be 1, and the lock will be
7558  *  released during exception processing.
7559  *
7560  *  For synchronized methods, we generate a single return block.
7561  *  We can do this without creating additional "step" blocks because "ret" blocks
7562  *  must occur at the top-level (of the original code), not nested within any EH
7563  *  constructs. From the CLI spec, 12.4.2.8.2.3 "ret": "Shall not be enclosed in any
7564  *  protected block, filter, or handler." Also, 3.57: "The ret instruction cannot be
7565  *  used to transfer control out of a try, filter, catch, or finally block. From within
7566  *  a try or catch, use the leave instruction with a destination of a ret instruction
7567  *  that is outside all enclosing exception blocks."
7568  *
7569  *  In addition, we can add a "fault" at the end of a method and be guaranteed that no
7570  *  control falls through. From the CLI spec, section 12.4 "Control flow": "Control is not
7571  *  permitted to simply fall through the end of a method. All paths shall terminate with one
7572  *  of these instructions: ret, throw, jmp, or (tail. followed by call, calli, or callvirt)."
7573  *
7574  *  We only need to worry about "ret" and "throw", as the CLI spec prevents any other
7575  *  alternatives. Section 15.4.3.3 "Implementation information" states about exiting
7576  *  synchronized methods: "Exiting a synchronized method using a tail. call shall be
7577  *  implemented as though the tail. had not been specified." Section 3.37 "jmp" states:
7578  *  "The jmp instruction cannot be used to transferred control out of a try, filter,
7579  *  catch, fault or finally block; or out of a synchronized region." And, "throw" will
7580  *  be handled naturally; no additional work is required.
7581  */
7582
7583 void Compiler::fgAddSyncMethodEnterExit()
7584 {
7585     assert((info.compFlags & CORINFO_FLG_SYNCH) != 0);
7586
7587     // We need to do this transformation before funclets are created.
7588     assert(!fgFuncletsCreated);
7589
7590     // Assume we don't need to update the bbPreds lists.
7591     assert(!fgComputePredsDone);
7592
7593 #if !FEATURE_EH
7594     // If we don't support EH, we can't add the EH needed by synchronized methods.
7595     // Of course, we could simply ignore adding the EH constructs, since we don't
7596     // support exceptions being thrown in this mode, but we would still need to add
7597     // the monitor enter/exit, and that doesn't seem worth it for this minor case.
7598     // By the time EH is working, we can just enable the whole thing.
7599     NYI("No support for synchronized methods");
7600 #endif // !FEATURE_EH
7601
7602     // Create a scratch first BB where we can put the new variable initialization.
7603     // Don't put the scratch BB in the protected region.
7604
7605     fgEnsureFirstBBisScratch();
7606
7607     // Create a block for the start of the try region, where the monitor enter call
7608     // will go.
7609
7610     assert(fgFirstBB->bbFallsThrough());
7611
7612     BasicBlock* tryBegBB  = fgNewBBafter(BBJ_NONE, fgFirstBB, false);
7613     BasicBlock* tryLastBB = fgLastBB;
7614
7615     // Create a block for the fault.
7616
7617     assert(!tryLastBB->bbFallsThrough());
7618     BasicBlock* faultBB = fgNewBBafter(BBJ_EHFINALLYRET, tryLastBB, false);
7619
7620     assert(tryLastBB->bbNext == faultBB);
7621     assert(faultBB->bbNext == nullptr);
7622     assert(faultBB == fgLastBB);
7623
7624     { // Scope the EH region creation
7625
7626         // Add the new EH region at the end, since it is the least nested,
7627         // and thus should be last.
7628
7629         EHblkDsc* newEntry;
7630         unsigned  XTnew = compHndBBtabCount;
7631
7632         newEntry = fgAddEHTableEntry(XTnew);
7633
7634         // Initialize the new entry
7635
7636         newEntry->ebdHandlerType = EH_HANDLER_FAULT;
7637
7638         newEntry->ebdTryBeg  = tryBegBB;
7639         newEntry->ebdTryLast = tryLastBB;
7640
7641         newEntry->ebdHndBeg  = faultBB;
7642         newEntry->ebdHndLast = faultBB;
7643
7644         newEntry->ebdTyp = 0; // unused for fault
7645
7646         newEntry->ebdEnclosingTryIndex = EHblkDsc::NO_ENCLOSING_INDEX;
7647         newEntry->ebdEnclosingHndIndex = EHblkDsc::NO_ENCLOSING_INDEX;
7648
7649         newEntry->ebdTryBegOffset    = tryBegBB->bbCodeOffs;
7650         newEntry->ebdTryEndOffset    = tryLastBB->bbCodeOffsEnd;
7651         newEntry->ebdFilterBegOffset = 0;
7652         newEntry->ebdHndBegOffset    = 0; // handler doesn't correspond to any IL
7653         newEntry->ebdHndEndOffset    = 0; // handler doesn't correspond to any IL
7654
7655         // Set some flags on the new region. This is the same as when we set up
7656         // EH regions in fgFindBasicBlocks(). Note that the try has no enclosing
7657         // handler, and the fault has no enclosing try.
7658
7659         tryBegBB->bbFlags |= BBF_HAS_LABEL | BBF_DONT_REMOVE | BBF_TRY_BEG | BBF_IMPORTED;
7660
7661         faultBB->bbFlags |= BBF_HAS_LABEL | BBF_DONT_REMOVE | BBF_IMPORTED;
7662         faultBB->bbCatchTyp = BBCT_FAULT;
7663
7664         tryBegBB->setTryIndex(XTnew);
7665         tryBegBB->clearHndIndex();
7666
7667         faultBB->clearTryIndex();
7668         faultBB->setHndIndex(XTnew);
7669
7670         // Walk the user code blocks and set all blocks that don't already have a try handler
7671         // to point to the new try handler.
7672
7673         BasicBlock* tmpBB;
7674         for (tmpBB = tryBegBB->bbNext; tmpBB != faultBB; tmpBB = tmpBB->bbNext)
7675         {
7676             if (!tmpBB->hasTryIndex())
7677             {
7678                 tmpBB->setTryIndex(XTnew);
7679             }
7680         }
7681
7682         // Walk the EH table. Make every EH entry that doesn't already have an enclosing
7683         // try index mark this new entry as their enclosing try index.
7684
7685         unsigned  XTnum;
7686         EHblkDsc* HBtab;
7687
7688         for (XTnum = 0, HBtab = compHndBBtab; XTnum < XTnew; XTnum++, HBtab++)
7689         {
7690             if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
7691             {
7692                 HBtab->ebdEnclosingTryIndex =
7693                     (unsigned short)XTnew; // This EH region wasn't previously nested, but now it is.
7694             }
7695         }
7696
7697 #ifdef DEBUG
7698         if (verbose)
7699         {
7700             JITDUMP("Synchronized method - created additional EH descriptor EH#%u for try/fault wrapping monitor "
7701                     "enter/exit\n",
7702                     XTnew);
7703             fgDispBasicBlocks();
7704             fgDispHandlerTab();
7705         }
7706
7707         fgVerifyHandlerTab();
7708 #endif // DEBUG
7709     }
7710
7711     // Create a 'monitor acquired' boolean (actually, an unsigned byte: 1 = acquired, 0 = not acquired).
7712
7713     var_types typeMonAcquired = TYP_UBYTE;
7714     this->lvaMonAcquired      = lvaGrabTemp(true DEBUGARG("Synchronized method monitor acquired boolean"));
7715
7716     lvaTable[lvaMonAcquired].lvType = typeMonAcquired;
7717
7718     { // Scope the variables of the variable initialization
7719
7720         // Initialize the 'acquired' boolean.
7721
7722         GenTreePtr zero     = gtNewZeroConNode(genActualType(typeMonAcquired));
7723         GenTreePtr varNode  = gtNewLclvNode(lvaMonAcquired, typeMonAcquired);
7724         GenTreePtr initNode = gtNewAssignNode(varNode, zero);
7725
7726         fgInsertStmtAtEnd(fgFirstBB, initNode);
7727
7728 #ifdef DEBUG
7729         if (verbose)
7730         {
7731             printf("\nSynchronized method - Add 'acquired' initialization in first block BB%02u [%08p]\n", fgFirstBB,
7732                    dspPtr(fgFirstBB));
7733             gtDispTree(initNode);
7734             printf("\n");
7735         }
7736 #endif
7737     }
7738
7739     // Make a copy of the 'this' pointer to be used in the handler so it does not inhibit enregistration
7740     // of all uses of the variable.
7741     unsigned lvaCopyThis = 0;
7742     if (!info.compIsStatic)
7743     {
7744         lvaCopyThis                  = lvaGrabTemp(true DEBUGARG("Synchronized method monitor acquired boolean"));
7745         lvaTable[lvaCopyThis].lvType = TYP_REF;
7746
7747         GenTreePtr thisNode = gtNewLclvNode(info.compThisArg, TYP_REF);
7748         GenTreePtr copyNode = gtNewLclvNode(lvaCopyThis, TYP_REF);
7749         GenTreePtr initNode = gtNewAssignNode(copyNode, thisNode);
7750
7751         fgInsertStmtAtEnd(tryBegBB, initNode);
7752     }
7753
7754     fgCreateMonitorTree(lvaMonAcquired, info.compThisArg, tryBegBB, true /*enter*/);
7755
7756     // exceptional case
7757     fgCreateMonitorTree(lvaMonAcquired, lvaCopyThis, faultBB, false /*exit*/);
7758
7759     // non-exceptional cases
7760     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
7761     {
7762         if (block->bbJumpKind == BBJ_RETURN)
7763         {
7764             fgCreateMonitorTree(lvaMonAcquired, info.compThisArg, block, false /*exit*/);
7765         }
7766     }
7767 }
7768
7769 // fgCreateMonitorTree: Create tree to execute a monitor enter or exit operation for synchronized methods
7770 //    lvaMonAcquired: lvaNum of boolean variable that tracks if monitor has been acquired.
7771 //    lvaThisVar: lvaNum of variable being used as 'this' pointer, may not be the original one.  Is only used for
7772 //    nonstatic methods
7773 //    block: block to insert the tree in.  It is inserted at the end or in the case of a return, immediately before the
7774 //    GT_RETURN
7775 //    enter: whether to create a monitor enter or exit
7776
7777 GenTree* Compiler::fgCreateMonitorTree(unsigned lvaMonAcquired, unsigned lvaThisVar, BasicBlock* block, bool enter)
7778 {
7779     // Insert the expression "enter/exitCrit(this, &acquired)" or "enter/exitCrit(handle, &acquired)"
7780
7781     var_types  typeMonAcquired = TYP_UBYTE;
7782     GenTreePtr varNode         = gtNewLclvNode(lvaMonAcquired, typeMonAcquired);
7783     GenTreePtr varAddrNode     = gtNewOperNode(GT_ADDR, TYP_BYREF, varNode);
7784     GenTreePtr tree;
7785
7786     if (info.compIsStatic)
7787     {
7788         tree = fgGetCritSectOfStaticMethod();
7789         tree = gtNewHelperCallNode(enter ? CORINFO_HELP_MON_ENTER_STATIC : CORINFO_HELP_MON_EXIT_STATIC, TYP_VOID, 0,
7790                                    gtNewArgList(tree, varAddrNode));
7791     }
7792     else
7793     {
7794         tree = gtNewLclvNode(lvaThisVar, TYP_REF);
7795         tree = gtNewHelperCallNode(enter ? CORINFO_HELP_MON_ENTER : CORINFO_HELP_MON_EXIT, TYP_VOID, 0,
7796                                    gtNewArgList(tree, varAddrNode));
7797     }
7798
7799 #ifdef DEBUG
7800     if (verbose)
7801     {
7802         printf("\nSynchronized method - Add monitor %s call to block BB%02u [%08p]\n", enter ? "enter" : "exit", block,
7803                dspPtr(block));
7804         gtDispTree(tree);
7805         printf("\n");
7806     }
7807 #endif
7808
7809     if (block->bbJumpKind == BBJ_RETURN && block->lastStmt()->gtStmtExpr->gtOper == GT_RETURN)
7810     {
7811         GenTree* retNode = block->lastStmt()->gtStmtExpr;
7812         GenTree* retExpr = retNode->gtOp.gtOp1;
7813
7814         if (retExpr != nullptr)
7815         {
7816             // have to insert this immediately before the GT_RETURN so we transform:
7817             // ret(...) ->
7818             // ret(comma(comma(tmp=...,call mon_exit), tmp)
7819             //
7820             //
7821             // Before morph stage, it is possible to have a case of GT_RETURN(TYP_LONG, op1) where op1's type is
7822             // TYP_STRUCT (of 8-bytes) and op1 is call node. See the big comment block in impReturnInstruction()
7823             // for details for the case where info.compRetType is not the same as info.compRetNativeType.  For
7824             // this reason pass compMethodInfo->args.retTypeClass which is guaranteed to be a valid class handle
7825             // if the return type is a value class.  Note that fgInsertCommFormTemp() in turn uses this class handle
7826             // if the type of op1 is TYP_STRUCT to perform lvaSetStruct() on the new temp that is created, which
7827             // in turn passes it to VM to know the size of value type.
7828             GenTree* temp = fgInsertCommaFormTemp(&retNode->gtOp.gtOp1, info.compMethodInfo->args.retTypeClass);
7829
7830             GenTree* lclVar                 = retNode->gtOp.gtOp1->gtOp.gtOp2;
7831             retNode->gtOp.gtOp1->gtOp.gtOp2 = gtNewOperNode(GT_COMMA, retExpr->TypeGet(), tree, lclVar);
7832         }
7833         else
7834         {
7835             // Insert this immediately before the GT_RETURN
7836             fgInsertStmtNearEnd(block, tree);
7837         }
7838     }
7839     else
7840     {
7841         fgInsertStmtAtEnd(block, tree);
7842     }
7843
7844     return tree;
7845 }
7846
7847 // Convert a BBJ_RETURN block in a synchronized method to a BBJ_ALWAYS.
7848 // We've previously added a 'try' block around the original program code using fgAddSyncMethodEnterExit().
7849 // Thus, we put BBJ_RETURN blocks inside a 'try'. In IL this is illegal. Instead, we would
7850 // see a 'leave' inside a 'try' that would get transformed into BBJ_CALLFINALLY/BBJ_ALWAYS blocks
7851 // during importing, and the BBJ_ALWAYS would point at an outer block with the BBJ_RETURN.
7852 // Here, we mimic some of the logic of importing a LEAVE to get the same effect for synchronized methods.
7853 void Compiler::fgConvertSyncReturnToLeave(BasicBlock* block)
7854 {
7855     assert(!fgFuncletsCreated);
7856     assert(info.compFlags & CORINFO_FLG_SYNCH);
7857     assert(genReturnBB != nullptr);
7858     assert(genReturnBB != block);
7859     assert(fgReturnCount <= 1); // We have a single return for synchronized methods
7860     assert(block->bbJumpKind == BBJ_RETURN);
7861     assert((block->bbFlags & BBF_HAS_JMP) == 0);
7862     assert(block->hasTryIndex());
7863     assert(!block->hasHndIndex());
7864     assert(compHndBBtabCount >= 1);
7865
7866     unsigned tryIndex = block->getTryIndex();
7867     assert(tryIndex == compHndBBtabCount - 1); // The BBJ_RETURN must be at the top-level before we inserted the
7868                                                // try/finally, which must be the last EH region.
7869
7870     EHblkDsc* ehDsc = ehGetDsc(tryIndex);
7871     assert(ehDsc->ebdEnclosingTryIndex ==
7872            EHblkDsc::NO_ENCLOSING_INDEX); // There are no enclosing regions of the BBJ_RETURN block
7873     assert(ehDsc->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX);
7874
7875     // Convert the BBJ_RETURN to BBJ_ALWAYS, jumping to genReturnBB.
7876     block->bbJumpKind = BBJ_ALWAYS;
7877     block->bbJumpDest = genReturnBB;
7878     block->bbJumpDest->bbRefs++;
7879
7880 #ifdef DEBUG
7881     if (verbose)
7882     {
7883         printf("Synchronized method - convert block BB%02u to BBJ_ALWAYS [targets BB%02u]\n", block->bbNum,
7884                block->bbJumpDest->bbNum);
7885     }
7886 #endif
7887 }
7888
7889 #endif // !_TARGET_X86_
7890
7891 //------------------------------------------------------------------------
7892 // fgAddReversePInvokeEnterExit: Add enter/exit calls for reverse PInvoke methods
7893 //
7894 // Arguments:
7895 //      None.
7896 //
7897 // Return Value:
7898 //      None.
7899
7900 void Compiler::fgAddReversePInvokeEnterExit()
7901 {
7902     assert(opts.IsReversePInvoke());
7903
7904 #if COR_JIT_EE_VERSION > 460
7905     lvaReversePInvokeFrameVar = lvaGrabTempWithImplicitUse(false DEBUGARG("Reverse Pinvoke FrameVar"));
7906
7907     LclVarDsc* varDsc   = &lvaTable[lvaReversePInvokeFrameVar];
7908     varDsc->lvType      = TYP_BLK;
7909     varDsc->lvExactSize = eeGetEEInfo()->sizeOfReversePInvokeFrame;
7910
7911     GenTreePtr tree;
7912
7913     // Add enter pinvoke exit callout at the start of prolog
7914
7915     tree = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));
7916
7917     tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, TYP_VOID, 0, gtNewArgList(tree));
7918
7919     fgEnsureFirstBBisScratch();
7920
7921     fgInsertStmtAtBeg(fgFirstBB, tree);
7922
7923 #ifdef DEBUG
7924     if (verbose)
7925     {
7926         printf("\nReverse PInvoke method - Add reverse pinvoke enter in first basic block [%08p]\n", dspPtr(fgFirstBB));
7927         gtDispTree(tree);
7928         printf("\n");
7929     }
7930 #endif
7931
7932     // Add reverse pinvoke exit callout at the end of epilog
7933
7934     tree = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));
7935
7936     tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, TYP_VOID, 0, gtNewArgList(tree));
7937
7938     assert(genReturnBB != nullptr);
7939
7940     fgInsertStmtAtEnd(genReturnBB, tree);
7941
7942 #ifdef DEBUG
7943     if (verbose)
7944     {
7945         printf("\nReverse PInvoke method - Add reverse pinvoke exit in return basic block [%08p]\n",
7946                dspPtr(genReturnBB));
7947         gtDispTree(tree);
7948         printf("\n");
7949     }
7950 #endif
7951
7952 #endif // COR_JIT_EE_VERSION > 460
7953 }
7954
7955 /*****************************************************************************
7956  *
7957  *  Return 'true' if there is more than one BBJ_RETURN block.
7958  */
7959
7960 bool Compiler::fgMoreThanOneReturnBlock()
7961 {
7962     unsigned retCnt = 0;
7963
7964     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
7965     {
7966         if (block->bbJumpKind == BBJ_RETURN)
7967         {
7968             retCnt++;
7969             if (retCnt > 1)
7970             {
7971                 return true;
7972             }
7973         }
7974     }
7975
7976     return false;
7977 }
7978
7979 /*****************************************************************************
7980  *
7981  *  Add any internal blocks/trees we may need
7982  */
7983
7984 void Compiler::fgAddInternal()
7985 {
7986     noway_assert(!compIsForInlining());
7987
7988     /*
7989         <BUGNUM> VSW441487 </BUGNUM>
7990
7991         The "this" pointer is implicitly used in the following cases:
7992             1. Locking of synchronized methods
7993             2. Dictionary access of shared generics code
7994             3. If a method has "catch(FooException<T>)", the EH code accesses "this" to determine T.
7995             4. Initializing the type from generic methods which require precise cctor semantics
7996             5. Verifier does special handling of "this" in the .ctor
7997
7998         However, we might overwrite it with a "starg 0".
7999         In this case, we will redirect all "ldarg(a)/starg(a) 0" to a temp lvaTable[lvaArg0Var]
8000     */
8001
8002     if (!info.compIsStatic)
8003     {
8004         if (lvaArg0Var != info.compThisArg)
8005         {
8006             // When we're using the general encoder, we mark compThisArg address-taken to ensure that it is not
8007             // enregistered (since the decoder always reports a stack location for "this" for generics
8008             // context vars).
8009             bool lva0CopiedForGenericsCtxt;
8010 #ifndef JIT32_GCENCODER
8011             lva0CopiedForGenericsCtxt = ((info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0);
8012 #else  // JIT32_GCENCODER
8013             lva0CopiedForGenericsCtxt = false;
8014 #endif // JIT32_GCENCODER
8015             noway_assert(lva0CopiedForGenericsCtxt || !lvaTable[info.compThisArg].lvAddrExposed);
8016             noway_assert(!lvaTable[info.compThisArg].lvArgWrite);
8017             noway_assert(lvaTable[lvaArg0Var].lvAddrExposed || lvaTable[lvaArg0Var].lvArgWrite ||
8018                          lva0CopiedForGenericsCtxt);
8019
8020             var_types thisType = lvaTable[info.compThisArg].TypeGet();
8021
8022             // Now assign the original input "this" to the temp
8023
8024             GenTreePtr tree;
8025
8026             tree = gtNewLclvNode(lvaArg0Var, thisType);
8027
8028             tree = gtNewAssignNode(tree,                                     // dst
8029                                    gtNewLclvNode(info.compThisArg, thisType) // src
8030                                    );
8031
8032             /* Create a new basic block and stick the assignment in it */
8033
8034             fgEnsureFirstBBisScratch();
8035
8036             fgInsertStmtAtEnd(fgFirstBB, tree);
8037
8038 #ifdef DEBUG
8039             if (verbose)
8040             {
8041                 printf("\nCopy \"this\" to lvaArg0Var in first basic block [%08p]\n", dspPtr(fgFirstBB));
8042                 gtDispTree(tree);
8043                 printf("\n");
8044             }
8045 #endif
8046         }
8047     }
8048
8049     // Grab a temp for the security object.
8050     // (Note: opts.compDbgEnC currently also causes the security object to be generated. See Compiler::compCompile)
8051     if (opts.compNeedSecurityCheck)
8052     {
8053         noway_assert(lvaSecurityObject == BAD_VAR_NUM);
8054         lvaSecurityObject                  = lvaGrabTempWithImplicitUse(false DEBUGARG("security check"));
8055         lvaTable[lvaSecurityObject].lvType = TYP_REF;
8056     }
8057
8058     /* Assume we will generate a single shared return sequence */
8059
8060     ULONG returnWeight = 0;
8061     bool  oneReturn;
8062     bool  allProfWeight;
8063
8064     //
8065     //  We will generate just one epilog (return block)
8066     //   when we are asked to generate enter/leave callbacks
8067     //   or for methods with PInvoke
8068     //   or for methods calling into unmanaged code
8069     //   or for synchronized methods.
8070     //
8071     if (compIsProfilerHookNeeded() || (info.compCallUnmanaged != 0) || opts.IsReversePInvoke() ||
8072         ((info.compFlags & CORINFO_FLG_SYNCH) != 0))
8073     {
8074         // We will generate only one return block
8075         // We will transform the BBJ_RETURN blocks
8076         //  into jumps to the one return block
8077         //
8078         oneReturn     = true;
8079         allProfWeight = false;
8080     }
8081     else
8082     {
8083         //
8084         // We are allowed to have multiple individual exits
8085         // However we can still decide to have a single return
8086         //
8087         oneReturn     = false;
8088         allProfWeight = true;
8089
8090         // Count the BBJ_RETURN blocks and set the returnWeight to the
8091         // sum of all these blocks.
8092         //
8093         fgReturnCount = 0;
8094         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
8095         {
8096             if (block->bbJumpKind == BBJ_RETURN)
8097             {
8098                 //
8099                 // returnCount is the count of BBJ_RETURN blocks in this method
8100                 //
8101                 fgReturnCount++;
8102                 //
8103                 // If all BBJ_RETURN blocks have a valid profiled weights
8104                 // then allProfWeight will be true, else it is false
8105                 //
8106                 if ((block->bbFlags & BBF_PROF_WEIGHT) == 0)
8107                 {
8108                     allProfWeight = false;
8109                 }
8110                 //
8111                 // returnWeight is the sum of the weights of all BBJ_RETURN blocks
8112                 returnWeight += block->bbWeight;
8113             }
8114         }
8115
8116         //
8117         // If we only have one (or zero) return blocks then
8118         // we do not need a special one return block
8119         //
8120         if (fgReturnCount > 1)
8121         {
8122             //
8123             // should we generate a single return block?
8124             //
8125             if (fgReturnCount > 4)
8126             {
8127                 // Our epilog encoding only supports up to 4 epilogs
8128                 // TODO-CQ: support >4 return points for ARM/AMD64, which presumably support any number of epilogs?
8129                 //
8130                 oneReturn = true;
8131             }
8132             else if (compCodeOpt() == SMALL_CODE)
8133             {
8134                 // For the Small_Code case we always generate a
8135                 // single return block when we have multiple
8136                 // return points
8137                 //
8138                 oneReturn = true;
8139             }
8140         }
8141     }
8142
8143 #if !defined(_TARGET_X86_)
8144     // Add the synchronized method enter/exit calls and try/finally protection. Note
8145     // that this must happen before the one BBJ_RETURN block is created below, so the
8146     // BBJ_RETURN block gets placed at the top-level, not within an EH region. (Otherwise,
8147     // we'd have to be really careful when creating the synchronized method try/finally
8148     // not to include the BBJ_RETURN block.)
8149     if ((info.compFlags & CORINFO_FLG_SYNCH) != 0)
8150     {
8151         fgAddSyncMethodEnterExit();
8152     }
8153 #endif // !_TARGET_X86_
8154
8155     if (oneReturn)
8156     {
8157         genReturnBB         = fgNewBBinRegion(BBJ_RETURN);
8158         genReturnBB->bbRefs = 1; // bbRefs gets update later, for now it should be 1
8159         fgReturnCount++;
8160
8161         if (allProfWeight)
8162         {
8163             //
8164             // if we have profile data for all BBJ_RETURN blocks
8165             // then we can set BBF_PROF_WEIGHT for genReturnBB
8166             //
8167             genReturnBB->bbFlags |= BBF_PROF_WEIGHT;
8168         }
8169         else
8170         {
8171             //
8172             // We can't rely upon the calculated returnWeight unless
8173             // all of the BBJ_RETURN blocks had valid profile weights
8174             // So we will use the weight of the first block instead
8175             //
8176             returnWeight = fgFirstBB->bbWeight;
8177         }
8178
8179         //
8180         // Set the weight of the oneReturn block
8181         //
8182         genReturnBB->bbWeight = min(returnWeight, BB_MAX_WEIGHT);
8183
8184         if (returnWeight == 0)
8185         {
8186             //
8187             // If necessary set the Run Rarely flag
8188             //
8189             genReturnBB->bbFlags |= BBF_RUN_RARELY;
8190         }
8191         else
8192         {
8193             // Make sure that the RunRarely flag is clear
8194             // because fgNewBBinRegion will set it to true
8195             //
8196             genReturnBB->bbFlags &= ~BBF_RUN_RARELY;
8197         }
8198
8199         genReturnBB->bbFlags |= (BBF_INTERNAL | BBF_DONT_REMOVE);
8200
8201         noway_assert(genReturnBB->bbNext == nullptr);
8202
8203 #ifdef DEBUG
8204         if (verbose)
8205         {
8206             printf("\n genReturnBB [BB%02u] created\n", genReturnBB->bbNum);
8207         }
8208 #endif
8209     }
8210     else
8211     {
8212         //
8213         // We don't have a oneReturn block for this method
8214         //
8215         genReturnBB = nullptr;
8216     }
8217
8218     // If there is a return value, then create a temp for it.  Real returns will store the value in there and
8219     // it'll be reloaded by the single return.
8220     if (genReturnBB && compMethodHasRetVal())
8221     {
8222         genReturnLocal = lvaGrabTemp(true DEBUGARG("Single return block return value"));
8223
8224         if (compMethodReturnsNativeScalarType())
8225         {
8226             lvaTable[genReturnLocal].lvType = genActualType(info.compRetNativeType);
8227         }
8228         else if (compMethodReturnsRetBufAddr())
8229         {
8230             lvaTable[genReturnLocal].lvType = TYP_BYREF;
8231         }
8232         else if (compMethodReturnsMultiRegRetType())
8233         {
8234             lvaTable[genReturnLocal].lvType = TYP_STRUCT;
8235             lvaSetStruct(genReturnLocal, info.compMethodInfo->args.retTypeClass, true);
8236             lvaTable[genReturnLocal].lvIsMultiRegRet = true;
8237         }
8238         else
8239         {
8240             assert(!"unreached");
8241         }
8242
8243         if (varTypeIsFloating(lvaTable[genReturnLocal].lvType))
8244         {
8245             this->compFloatingPointUsed = true;
8246         }
8247
8248         if (!varTypeIsFloating(info.compRetType))
8249         {
8250             lvaTable[genReturnLocal].setPrefReg(REG_INTRET, this);
8251 #ifdef REG_FLOATRET
8252         }
8253         else
8254         {
8255             lvaTable[genReturnLocal].setPrefReg(REG_FLOATRET, this);
8256         }
8257 #endif
8258
8259 #ifdef DEBUG
8260         // This temporary should not be converted to a double in stress mode,
8261         // because we introduce assigns to it after the stress conversion
8262         lvaTable[genReturnLocal].lvKeepType = 1;
8263 #endif
8264     }
8265     else
8266     {
8267         genReturnLocal = BAD_VAR_NUM;
8268     }
8269
8270     if (info.compCallUnmanaged != 0)
8271     {
8272         // The P/Invoke helpers only require a frame variable, so only allocate the
8273         // TCB variable if we're not using them.
8274         if (!opts.ShouldUsePInvokeHelpers())
8275         {
8276             info.compLvFrameListRoot = lvaGrabTemp(false DEBUGARG("Pinvoke FrameListRoot"));
8277         }
8278
8279         lvaInlinedPInvokeFrameVar = lvaGrabTempWithImplicitUse(false DEBUGARG("Pinvoke FrameVar"));
8280
8281         LclVarDsc* varDsc = &lvaTable[lvaInlinedPInvokeFrameVar];
8282         varDsc->addPrefReg(RBM_PINVOKE_TCB, this);
8283         varDsc->lvType = TYP_BLK;
8284         // Make room for the inlined frame.
8285         varDsc->lvExactSize = eeGetEEInfo()->inlinedCallFrameInfo.size;
8286 #if FEATURE_FIXED_OUT_ARGS
8287         // Grab and reserve space for TCB, Frame regs used in PInvoke epilog to pop the inlined frame.
8288         // See genPInvokeMethodEpilog() for use of the grabbed var. This is only necessary if we are
8289         // not using the P/Invoke helpers.
8290         if (!opts.ShouldUsePInvokeHelpers() && compJmpOpUsed)
8291         {
8292             lvaPInvokeFrameRegSaveVar = lvaGrabTempWithImplicitUse(false DEBUGARG("PInvokeFrameRegSave Var"));
8293             varDsc                    = &lvaTable[lvaPInvokeFrameRegSaveVar];
8294             varDsc->lvType            = TYP_BLK;
8295             varDsc->lvExactSize       = 2 * REGSIZE_BYTES;
8296         }
8297 #endif
8298     }
8299
8300     // Do we need to insert a "JustMyCode" callback?
8301
8302     CORINFO_JUST_MY_CODE_HANDLE* pDbgHandle = nullptr;
8303     CORINFO_JUST_MY_CODE_HANDLE  dbgHandle  = nullptr;
8304     if (opts.compDbgCode && !(opts.eeFlags & CORJIT_FLG_IL_STUB))
8305     {
8306         dbgHandle = info.compCompHnd->getJustMyCodeHandle(info.compMethodHnd, &pDbgHandle);
8307     }
8308
8309 #ifdef _TARGET_ARM64_
8310     // TODO-ARM64-NYI: don't do just-my-code
8311     dbgHandle  = nullptr;
8312     pDbgHandle = nullptr;
8313 #endif // _TARGET_ARM64_
8314
8315     noway_assert(!dbgHandle || !pDbgHandle);
8316
8317     if (dbgHandle || pDbgHandle)
8318     {
8319         GenTreePtr guardCheckVal =
8320             gtNewOperNode(GT_IND, TYP_INT, gtNewIconEmbHndNode(dbgHandle, pDbgHandle, GTF_ICON_TOKEN_HDL));
8321         GenTreePtr guardCheckCond = gtNewOperNode(GT_EQ, TYP_INT, guardCheckVal, gtNewZeroConNode(TYP_INT));
8322         guardCheckCond->gtFlags |= GTF_RELOP_QMARK;
8323
8324         // Create the callback which will yield the final answer
8325
8326         GenTreePtr callback = gtNewHelperCallNode(CORINFO_HELP_DBG_IS_JUST_MY_CODE, TYP_VOID);
8327         callback            = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), callback);
8328
8329         // Stick the conditional call at the start of the method
8330
8331         fgEnsureFirstBBisScratch();
8332         fgInsertStmtAtEnd(fgFirstBB, gtNewQmarkNode(TYP_VOID, guardCheckCond, callback));
8333     }
8334
8335     /* Do we need to call out for security ? */
8336
8337     if (tiSecurityCalloutNeeded)
8338     {
8339         // We must have grabbed this local.
8340         noway_assert(opts.compNeedSecurityCheck);
8341         noway_assert(lvaSecurityObject != BAD_VAR_NUM);
8342
8343         GenTreePtr tree;
8344
8345         /* Insert the expression "call JIT_Security_Prolog(MethodHnd, &SecurityObject)" */
8346
8347         tree = gtNewIconEmbMethHndNode(info.compMethodHnd);
8348
8349         tree = gtNewHelperCallNode(info.compCompHnd->getSecurityPrologHelper(info.compMethodHnd), TYP_VOID, 0,
8350                                    gtNewArgList(tree, gtNewOperNode(GT_ADDR, TYP_BYREF,
8351                                                                     gtNewLclvNode(lvaSecurityObject, TYP_REF))));
8352
8353         /* Create a new basic block and stick the call in it */
8354
8355         fgEnsureFirstBBisScratch();
8356
8357         fgInsertStmtAtEnd(fgFirstBB, tree);
8358
8359 #ifdef DEBUG
8360         if (verbose)
8361         {
8362             printf("\ntiSecurityCalloutNeeded - Add call JIT_Security_Prolog(%08p) statement ",
8363                    dspPtr(info.compMethodHnd));
8364             printTreeID(tree);
8365             printf(" in first basic block [%08p]\n", dspPtr(fgFirstBB));
8366             gtDispTree(tree);
8367             printf("\n");
8368         }
8369 #endif
8370     }
8371
8372 #if defined(_TARGET_X86_)
8373
8374     /* Is this a 'synchronized' method? */
8375
8376     if (info.compFlags & CORINFO_FLG_SYNCH)
8377     {
8378         GenTreePtr tree = NULL;
8379
8380         /* Insert the expression "enterCrit(this)" or "enterCrit(handle)" */
8381
8382         if (info.compIsStatic)
8383         {
8384             tree = fgGetCritSectOfStaticMethod();
8385
8386             tree = gtNewHelperCallNode(CORINFO_HELP_MON_ENTER_STATIC, TYP_VOID, 0, gtNewArgList(tree));
8387         }
8388         else
8389         {
8390             noway_assert(lvaTable[info.compThisArg].lvType == TYP_REF);
8391
8392             tree = gtNewLclvNode(info.compThisArg, TYP_REF);
8393
8394             tree = gtNewHelperCallNode(CORINFO_HELP_MON_ENTER, TYP_VOID, 0, gtNewArgList(tree));
8395         }
8396
8397         /* Create a new basic block and stick the call in it */
8398
8399         fgEnsureFirstBBisScratch();
8400
8401         fgInsertStmtAtEnd(fgFirstBB, tree);
8402
8403 #ifdef DEBUG
8404         if (verbose)
8405         {
8406             printf("\nSynchronized method - Add enterCrit statement in first basic block [%08p]\n", dspPtr(fgFirstBB));
8407             gtDispTree(tree);
8408             printf("\n");
8409         }
8410 #endif
8411
8412         /* We must be generating a single exit point for this to work */
8413
8414         noway_assert(oneReturn);
8415         noway_assert(genReturnBB);
8416
8417         /* Create the expression "exitCrit(this)" or "exitCrit(handle)" */
8418
8419         if (info.compIsStatic)
8420         {
8421             tree = fgGetCritSectOfStaticMethod();
8422
8423             tree = gtNewHelperCallNode(CORINFO_HELP_MON_EXIT_STATIC, TYP_VOID, 0, gtNewArgList(tree));
8424         }
8425         else
8426         {
8427             tree = gtNewLclvNode(info.compThisArg, TYP_REF);
8428
8429             tree = gtNewHelperCallNode(CORINFO_HELP_MON_EXIT, TYP_VOID, 0, gtNewArgList(tree));
8430         }
8431
8432         fgInsertStmtAtEnd(genReturnBB, tree);
8433
8434 #ifdef DEBUG
8435         if (verbose)
8436         {
8437             printf("\nSynchronized method - Add exit expression ");
8438             printTreeID(tree);
8439             printf("\n");
8440         }
8441 #endif
8442
8443         // Reset cookies used to track start and end of the protected region in synchronized methods
8444         syncStartEmitCookie = NULL;
8445         syncEndEmitCookie   = NULL;
8446     }
8447
8448 #endif // _TARGET_X86_
8449
8450     /* Do we need to do runtime call out to check the security? */
8451
8452     if (tiRuntimeCalloutNeeded)
8453     {
8454         GenTreePtr tree;
8455
8456         /* Insert the expression "call verificationRuntimeCheck(MethodHnd)" */
8457
8458         tree = gtNewIconEmbMethHndNode(info.compMethodHnd);
8459
8460         tree = gtNewHelperCallNode(CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, TYP_VOID, 0, gtNewArgList(tree));
8461
8462         /* Create a new basic block and stick the call in it */
8463
8464         fgEnsureFirstBBisScratch();
8465
8466         fgInsertStmtAtEnd(fgFirstBB, tree);
8467
8468 #ifdef DEBUG
8469         if (verbose)
8470         {
8471             printf("\ntiRuntimeCalloutNeeded - Call verificationRuntimeCheck(%08p) statement in first basic block "
8472                    "[%08p]\n",
8473                    dspPtr(info.compMethodHnd), dspPtr(fgFirstBB));
8474             gtDispTree(tree);
8475             printf("\n");
8476         }
8477 #endif
8478     }
8479
8480     if (opts.IsReversePInvoke())
8481     {
8482         fgAddReversePInvokeEnterExit();
8483     }
8484
8485     //
8486     //  Add 'return' expression to the return block if we made it as "oneReturn" before.
8487     //
8488     if (oneReturn)
8489     {
8490         GenTreePtr tree;
8491
8492         //
8493         // Make the 'return' expression.
8494         //
8495
8496         // make sure to reload the return value as part of the return (it is saved by the "real return").
8497         if (genReturnLocal != BAD_VAR_NUM)
8498         {
8499             noway_assert(compMethodHasRetVal());
8500
8501             GenTreePtr retTemp = gtNewLclvNode(genReturnLocal, lvaTable[genReturnLocal].TypeGet());
8502
8503             // make sure copy prop ignores this node (make sure it always does a reload from the temp).
8504             retTemp->gtFlags |= GTF_DONT_CSE;
8505             tree = gtNewOperNode(GT_RETURN, retTemp->gtType, retTemp);
8506         }
8507         else
8508         {
8509             noway_assert(info.compRetType == TYP_VOID || varTypeIsStruct(info.compRetType));
8510             // return void
8511             tree = new (this, GT_RETURN) GenTreeOp(GT_RETURN, TYP_VOID);
8512         }
8513
8514         /* Add 'return' expression to the return block */
8515
8516         noway_assert(genReturnBB);
8517
8518         fgInsertStmtAtEnd(genReturnBB, tree);
8519
8520 #ifdef DEBUG
8521         if (verbose)
8522         {
8523             printf("\noneReturn statement tree ");
8524             printTreeID(tree);
8525             printf(" added to genReturnBB [%08p]\n", dspPtr(genReturnBB));
8526             gtDispTree(tree);
8527             printf("\n");
8528         }
8529 #endif
8530     }
8531
8532 #ifdef DEBUG
8533     if (verbose)
8534     {
8535         printf("\n*************** After fgAddInternal()\n");
8536         fgDispBasicBlocks();
8537         fgDispHandlerTab();
8538     }
8539 #endif
8540 }
8541
8542 /*****************************************************************************
8543  *
8544  *  Create a new statement from tree and wire the links up.
8545  */
8546 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTreePtr tree, BasicBlock* block, IL_OFFSETX offs)
8547 {
8548     GenTreeStmt* stmt = gtNewStmt(tree, offs);
8549     gtSetStmtInfo(stmt);
8550     fgSetStmtSeq(stmt);
8551
8552 #if DEBUG
8553     if (block != nullptr)
8554     {
8555         fgDebugCheckNodeLinks(block, stmt);
8556     }
8557 #endif
8558
8559     return stmt;
8560 }
8561
8562 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTreePtr tree)
8563 {
8564     return fgNewStmtFromTree(tree, nullptr, BAD_IL_OFFSET);
8565 }
8566
8567 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTreePtr tree, BasicBlock* block)
8568 {
8569     return fgNewStmtFromTree(tree, block, BAD_IL_OFFSET);
8570 }
8571
8572 GenTreeStmt* Compiler::fgNewStmtFromTree(GenTreePtr tree, IL_OFFSETX offs)
8573 {
8574     return fgNewStmtFromTree(tree, nullptr, offs);
8575 }
8576
8577 //------------------------------------------------------------------------
8578 // fgFindBlockILOffset: Given a block, find the IL offset corresponding to the first statement
8579 //      in the block with a legal IL offset. Skip any leading statements that have BAD_IL_OFFSET.
8580 //      If no statement has an initialized statement offset (including the case where there are
8581 //      no statements in the block), then return BAD_IL_OFFSET. This function is used when
8582 //      blocks are split or modified, and we want to maintain the IL offset as much as possible
8583 //      to preserve good debugging behavior.
8584 //
8585 // Arguments:
8586 //      block - The block to check.
8587 //
8588 // Return Value:
8589 //      The first good IL offset of a statement in the block, or BAD_IL_OFFSET if such an IL offset
8590 //      cannot be found.
8591 //
8592 //      If we are not built with DEBUGGING_SUPPORT or DEBUG, then always report BAD_IL_OFFSET,
8593 //      since in that case statements don't contain an IL offset. The effect will be that split
8594 //      blocks will lose their IL offset information.
8595
8596 IL_OFFSET Compiler::fgFindBlockILOffset(BasicBlock* block)
8597 {
8598     // This function searches for IL offsets in statement nodes, so it can't be used in LIR. We
8599     // could have a similar function for LIR that searches for GT_IL_OFFSET nodes.
8600     assert(!block->IsLIR());
8601
8602 #if defined(DEBUGGING_SUPPORT) || defined(DEBUG)
8603     for (GenTree* stmt = block->bbTreeList; stmt != nullptr; stmt = stmt->gtNext)
8604     {
8605         assert(stmt->IsStatement());
8606         if (stmt->gtStmt.gtStmtILoffsx != BAD_IL_OFFSET)
8607         {
8608             return jitGetILoffs(stmt->gtStmt.gtStmtILoffsx);
8609         }
8610     }
8611 #endif // defined(DEBUGGING_SUPPORT) || defined(DEBUG)
8612
8613     return BAD_IL_OFFSET;
8614 }
8615
8616 //------------------------------------------------------------------------------
8617 // fgSplitBlockAtEnd - split the given block into two blocks.
8618 //                   All code in the block stays in the original block.
8619 //                   Control falls through from original to new block, and
8620 //                   the new block is returned.
8621 //------------------------------------------------------------------------------
8622 BasicBlock* Compiler::fgSplitBlockAtEnd(BasicBlock* curr)
8623 {
8624     // We'd like to use fgNewBBafter(), but we need to update the preds list before linking in the new block.
8625     // (We need the successors of 'curr' to be correct when we do this.)
8626     BasicBlock* newBlock = bbNewBasicBlock(curr->bbJumpKind);
8627
8628     // Start the new block with no refs. When we set the preds below, this will get updated correctly.
8629     newBlock->bbRefs = 0;
8630
8631     // For each successor of the original block, set the new block as their predecessor.
8632     // Note we are using the "rational" version of the successor iterator that does not hide the finallyret arcs.
8633     // Without these arcs, a block 'b' may not be a member of succs(preds(b))
8634     if (curr->bbJumpKind != BBJ_SWITCH)
8635     {
8636         unsigned numSuccs = curr->NumSucc(this);
8637         for (unsigned i = 0; i < numSuccs; i++)
8638         {
8639             BasicBlock* succ = curr->GetSucc(i, this);
8640             if (succ != newBlock)
8641             {
8642                 JITDUMP("BB%02u previous predecessor was BB%02u, now is BB%02u\n", succ->bbNum, curr->bbNum,
8643                         newBlock->bbNum);
8644                 fgReplacePred(succ, curr, newBlock);
8645             }
8646         }
8647
8648         newBlock->bbJumpDest = curr->bbJumpDest;
8649         curr->bbJumpDest     = nullptr;
8650     }
8651     else
8652     {
8653         // In the case of a switch statement there's more complicated logic in order to wire up the predecessor lists
8654         // but fortunately there's an existing method that implements this functionality.
8655         newBlock->bbJumpSwt = curr->bbJumpSwt;
8656
8657         fgChangeSwitchBlock(curr, newBlock);
8658
8659         curr->bbJumpSwt = nullptr;
8660     }
8661
8662     newBlock->inheritWeight(curr);
8663
8664     // Set the new block's flags. Note that the new block isn't BBF_INTERNAL unless the old block is.
8665     newBlock->bbFlags = curr->bbFlags;
8666
8667     // Remove flags that the new block can't have.
8668     newBlock->bbFlags &= ~(BBF_TRY_BEG | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1 | BBF_HAS_LABEL |
8669                            BBF_JMP_TARGET | BBF_FUNCLET_BEG | BBF_LOOP_PREHEADER | BBF_KEEP_BBJ_ALWAYS);
8670
8671     // Remove the GC safe bit on the new block. It seems clear that if we split 'curr' at the end,
8672     // such that all the code is left in 'curr', and 'newBlock' just gets the control flow, then
8673     // both 'curr' and 'newBlock' could accurately retain an existing GC safe bit. However, callers
8674     // use this function to split blocks in the middle, or at the beginning, and they don't seem to
8675     // be careful about updating this flag appropriately. So, removing the GC safe bit is simply
8676     // conservative: some functions might end up being fully interruptible that could be partially
8677     // interruptible if we exercised more care here.
8678     newBlock->bbFlags &= ~BBF_GC_SAFE_POINT;
8679
8680 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
8681     newBlock->bbFlags &= ~(BBF_FINALLY_TARGET);
8682 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
8683
8684     // The new block has no code, so we leave bbCodeOffs/bbCodeOffsEnd set to BAD_IL_OFFSET. If a caller
8685     // puts code in the block, then it needs to update these.
8686
8687     // Insert the new block in the block list after the 'curr' block.
8688     fgInsertBBafter(curr, newBlock);
8689     fgExtendEHRegionAfter(curr); // The new block is in the same EH region as the old block.
8690
8691     // Remove flags from the old block that are no longer possible.
8692     curr->bbFlags &= ~(BBF_HAS_JMP | BBF_RETLESS_CALL);
8693
8694     // Default to fallthru, and add the arc for that.
8695     curr->bbJumpKind = BBJ_NONE;
8696     fgAddRefPred(newBlock, curr);
8697
8698     return newBlock;
8699 }
8700
8701 //------------------------------------------------------------------------------
8702 // fgSplitBlockAfterStatement - Split the given block, with all code after
8703 //                              the given statement going into the second block.
8704 //------------------------------------------------------------------------------
8705 BasicBlock* Compiler::fgSplitBlockAfterStatement(BasicBlock* curr, GenTree* stmt)
8706 {
8707     assert(!curr->IsLIR()); // No statements in LIR, so you can't use this function.
8708
8709     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
8710
8711     if (stmt)
8712     {
8713         newBlock->bbTreeList = stmt->gtNext;
8714         if (newBlock->bbTreeList)
8715         {
8716             newBlock->bbTreeList->gtPrev = curr->bbTreeList->gtPrev;
8717         }
8718         curr->bbTreeList->gtPrev = stmt;
8719         stmt->gtNext             = nullptr;
8720
8721         // Update the IL offsets of the blocks to match the split.
8722
8723         assert(newBlock->bbCodeOffs == BAD_IL_OFFSET);
8724         assert(newBlock->bbCodeOffsEnd == BAD_IL_OFFSET);
8725
8726         // curr->bbCodeOffs remains the same
8727         newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
8728
8729         IL_OFFSET splitPointILOffset = fgFindBlockILOffset(newBlock);
8730
8731         curr->bbCodeOffsEnd  = splitPointILOffset;
8732         newBlock->bbCodeOffs = splitPointILOffset;
8733     }
8734     else
8735     {
8736         assert(curr->bbTreeList == nullptr); // if no tree was given then it better be an empty block
8737     }
8738
8739     return newBlock;
8740 }
8741
8742 //------------------------------------------------------------------------------
8743 // fgSplitBlockAfterNode - Split the given block, with all code after
8744 //                         the given node going into the second block.
8745 //                         This function is only used in LIR.
8746 //------------------------------------------------------------------------------
8747 BasicBlock* Compiler::fgSplitBlockAfterNode(BasicBlock* curr, GenTree* node)
8748 {
8749     assert(curr->IsLIR());
8750
8751     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
8752
8753     if (node != nullptr)
8754     {
8755         LIR::Range& currBBRange = LIR::AsRange(curr);
8756
8757         if (node != currBBRange.LastNode())
8758         {
8759             LIR::Range nodesToMove = currBBRange.Remove(node->gtNext, currBBRange.LastNode());
8760             LIR::AsRange(newBlock).InsertAtBeginning(std::move(nodesToMove));
8761         }
8762
8763         // Update the IL offsets of the blocks to match the split.
8764
8765         assert(newBlock->bbCodeOffs == BAD_IL_OFFSET);
8766         assert(newBlock->bbCodeOffsEnd == BAD_IL_OFFSET);
8767
8768         // curr->bbCodeOffs remains the same
8769         newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
8770
8771         // Search backwards from the end of the current block looking for the IL offset to use
8772         // for the end IL offset for the original block.
8773         IL_OFFSET                   splitPointILOffset = BAD_IL_OFFSET;
8774         LIR::Range::ReverseIterator riter;
8775         LIR::Range::ReverseIterator riterEnd;
8776         for (riter = currBBRange.rbegin(), riterEnd = currBBRange.rend(); riter != riterEnd; ++riter)
8777         {
8778             if ((*riter)->gtOper == GT_IL_OFFSET)
8779             {
8780                 GenTreeStmt* stmt = (*riter)->AsStmt();
8781                 if (stmt->gtStmtILoffsx != BAD_IL_OFFSET)
8782                 {
8783                     splitPointILOffset = jitGetILoffs(stmt->gtStmtILoffsx);
8784                     break;
8785                 }
8786             }
8787         }
8788
8789         curr->bbCodeOffsEnd = splitPointILOffset;
8790
8791         // Also use this as the beginning offset of the next block. Presumably we could/should
8792         // look to see if the first node is a GT_IL_OFFSET node, and use that instead.
8793         newBlock->bbCodeOffs = splitPointILOffset;
8794     }
8795     else
8796     {
8797         assert(curr->bbTreeList == nullptr); // if no node was given then it better be an empty block
8798     }
8799
8800     return newBlock;
8801 }
8802
8803 //------------------------------------------------------------------------------
8804 // fgSplitBlockAtBeginning - Split the given block into two blocks.
8805 //                         Control falls through from original to new block,
8806 //                         and the new block is returned.
8807 //                         All code in the original block goes into the new block
8808 //------------------------------------------------------------------------------
8809 BasicBlock* Compiler::fgSplitBlockAtBeginning(BasicBlock* curr)
8810 {
8811     BasicBlock* newBlock = fgSplitBlockAtEnd(curr);
8812
8813     newBlock->bbTreeList = curr->bbTreeList;
8814     curr->bbTreeList     = nullptr;
8815
8816     // The new block now has all the code, and the old block has none. Update the
8817     // IL offsets for the block to reflect this.
8818
8819     newBlock->bbCodeOffs    = curr->bbCodeOffs;
8820     newBlock->bbCodeOffsEnd = curr->bbCodeOffsEnd;
8821
8822     curr->bbCodeOffs    = BAD_IL_OFFSET;
8823     curr->bbCodeOffsEnd = BAD_IL_OFFSET;
8824
8825     return newBlock;
8826 }
8827
8828 //------------------------------------------------------------------------
8829 // fgSplitEdge: Splits the edge between a block 'curr' and its successor 'succ' by creating a new block
8830 //              that replaces 'succ' as a successor of 'curr', and which branches unconditionally
8831 //              to (or falls through to) 'succ'. Note that for a BBJ_COND block 'curr',
8832 //              'succ' might be the fall-through path or the branch path from 'curr'.
8833 //
8834 // Arguments:
8835 //    curr - A block which branches conditionally to 'succ'
8836 //    succ - The target block
8837 //
8838 // Return Value:
8839 //    Returns a new block, that is a successor of 'curr' and which branches unconditionally to 'succ'
8840 //
8841 // Assumptions:
8842 //    'curr' must have a bbJumpKind of BBJ_COND or BBJ_SWITCH
8843 //
8844 // Notes:
8845 //    The returned block is empty.
8846
8847 BasicBlock* Compiler::fgSplitEdge(BasicBlock* curr, BasicBlock* succ)
8848 {
8849     assert(curr->bbJumpKind == BBJ_COND || curr->bbJumpKind == BBJ_SWITCH);
8850     assert(fgGetPredForBlock(succ, curr) != nullptr);
8851
8852     BasicBlock* newBlock;
8853     if (succ == curr->bbNext)
8854     {
8855         // The successor is the fall-through path of a BBJ_COND, or
8856         // an immediately following block of a BBJ_SWITCH (which has
8857         // no fall-through path). For this case, simply insert a new
8858         // fall-through block after 'curr'.
8859         newBlock = fgNewBBafter(BBJ_NONE, curr, true /*extendRegion*/);
8860     }
8861     else
8862     {
8863         newBlock = fgNewBBinRegion(BBJ_ALWAYS, curr, curr->isRunRarely());
8864         // The new block always jumps to 'succ'
8865         newBlock->bbJumpDest = succ;
8866     }
8867     newBlock->bbFlags |= (curr->bbFlags & succ->bbFlags & (BBF_BACKWARD_JUMP));
8868
8869     JITDUMP("Splitting edge from BB%02u to BB%02u; adding BB%02u\n", curr->bbNum, succ->bbNum, newBlock->bbNum);
8870
8871     if (curr->bbJumpKind == BBJ_COND)
8872     {
8873         fgReplacePred(succ, curr, newBlock);
8874         if (curr->bbJumpDest == succ)
8875         {
8876             // Now 'curr' jumps to newBlock
8877             curr->bbJumpDest = newBlock;
8878             newBlock->bbFlags |= BBF_JMP_TARGET;
8879         }
8880         fgAddRefPred(newBlock, curr);
8881     }
8882     else
8883     {
8884         assert(curr->bbJumpKind == BBJ_SWITCH);
8885
8886         // newBlock replaces 'succ' in the switch.
8887         fgReplaceSwitchJumpTarget(curr, newBlock, succ);
8888
8889         // And 'succ' has 'newBlock' as a new predecessor.
8890         fgAddRefPred(succ, newBlock);
8891     }
8892
8893     // This isn't accurate, but it is complex to compute a reasonable number so just assume that we take the
8894     // branch 50% of the time.
8895     newBlock->inheritWeightPercentage(curr, 50);
8896
8897     // The bbLiveIn and bbLiveOut are both equal to the bbLiveIn of 'succ'
8898     if (fgLocalVarLivenessDone)
8899     {
8900         VarSetOps::Assign(this, newBlock->bbLiveIn, succ->bbLiveIn);
8901         VarSetOps::Assign(this, newBlock->bbLiveOut, succ->bbLiveIn);
8902     }
8903
8904     return newBlock;
8905 }
8906
8907 /*****************************************************************************/
8908 /*****************************************************************************/
8909
8910 void Compiler::fgFindOperOrder()
8911 {
8912 #ifdef DEBUG
8913     if (verbose)
8914     {
8915         printf("*************** In fgFindOperOrder()\n");
8916     }
8917 #endif
8918
8919     BasicBlock*  block;
8920     GenTreeStmt* stmt;
8921
8922     /* Walk the basic blocks and for each statement determine
8923      * the evaluation order, cost, FP levels, etc... */
8924
8925     for (block = fgFirstBB; block; block = block->bbNext)
8926     {
8927         compCurBB = block;
8928         for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
8929         {
8930             /* Recursively process the statement */
8931
8932             compCurStmt = stmt;
8933             gtSetStmtInfo(stmt);
8934         }
8935     }
8936 }
8937
8938 /*****************************************************************************/
8939 void Compiler::fgSimpleLowering()
8940 {
8941     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
8942     {
8943         // Walk the statement trees in this basic block, converting ArrLength nodes.
8944         compCurBB = block; // Used in fgRngChkTarget.
8945
8946 #ifdef LEGACY_BACKEND
8947         for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt; stmt = stmt->gtNextStmt)
8948         {
8949             for (GenTreePtr tree = stmt->gtStmtList; tree; tree = tree->gtNext)
8950             {
8951 #else
8952             LIR::Range& range         = LIR::AsRange(block);
8953             for (GenTree* tree : range)
8954             {
8955                 {
8956 #endif
8957                 if (tree->gtOper == GT_ARR_LENGTH)
8958                 {
8959                     GenTreeArrLen* arrLen = tree->AsArrLen();
8960                     GenTreePtr     arr    = arrLen->gtArrLen.ArrRef();
8961                     GenTreePtr     add;
8962                     GenTreePtr     con;
8963
8964                     /* Create the expression "*(array_addr + ArrLenOffs)" */
8965
8966                     noway_assert(arr->gtNext == tree);
8967
8968                     noway_assert(arrLen->ArrLenOffset() == offsetof(CORINFO_Array, length) ||
8969                                  arrLen->ArrLenOffset() == offsetof(CORINFO_String, stringLen));
8970
8971                     if ((arr->gtOper == GT_CNS_INT) && (arr->gtIntCon.gtIconVal == 0))
8972                     {
8973                         // If the array is NULL, then we should get a NULL reference
8974                         // exception when computing its length.  We need to maintain
8975                         // an invariant where there is no sum of two constants node, so
8976                         // let's simply return an indirection of NULL.
8977
8978                         add = arr;
8979                     }
8980                     else
8981                     {
8982                         con             = gtNewIconNode(arrLen->ArrLenOffset(), TYP_I_IMPL);
8983                         con->gtRsvdRegs = 0;
8984
8985                         add             = gtNewOperNode(GT_ADD, TYP_REF, arr, con);
8986                         add->gtRsvdRegs = arr->gtRsvdRegs;
8987
8988 #ifdef LEGACY_BACKEND
8989                         con->gtCopyFPlvl(arr);
8990
8991                         add->gtCopyFPlvl(arr);
8992                         add->CopyCosts(arr);
8993
8994                         arr->gtNext = con;
8995                         con->gtPrev = arr;
8996
8997                         con->gtNext = add;
8998                         add->gtPrev = con;
8999
9000                         add->gtNext  = tree;
9001                         tree->gtPrev = add;
9002 #else
9003                         range.InsertAfter(arr, con, add);
9004 #endif
9005                     }
9006
9007                     // Change to a GT_IND.
9008                     tree->ChangeOperUnchecked(GT_IND);
9009
9010                     tree->gtOp.gtOp1 = add;
9011                 }
9012                 else if (tree->OperGet() == GT_ARR_BOUNDS_CHECK
9013 #ifdef FEATURE_SIMD
9014                          || tree->OperGet() == GT_SIMD_CHK
9015 #endif // FEATURE_SIMD
9016                          )
9017                 {
9018                     // Add in a call to an error routine.
9019                     fgSetRngChkTarget(tree, false);
9020                 }
9021             }
9022         }
9023     }
9024
9025 #ifdef DEBUG
9026     if (verbose && fgRngChkThrowAdded)
9027     {
9028         printf("\nAfter fgSimpleLowering() added some RngChk throw blocks");
9029         fgDispBasicBlocks();
9030         fgDispHandlerTab();
9031         printf("\n");
9032     }
9033 #endif
9034 }
9035
9036 /*****************************************************************************
9037  */
9038
9039 void Compiler::fgUpdateRefCntForClone(BasicBlock* addedToBlock, GenTreePtr clonedTree)
9040 {
9041     assert(clonedTree->gtOper != GT_STMT);
9042
9043     if (lvaLocalVarRefCounted)
9044     {
9045         compCurBB = addedToBlock;
9046         fgWalkTreePre(&clonedTree, Compiler::lvaIncRefCntsCB, (void*)this, true);
9047     }
9048 }
9049
9050 /*****************************************************************************
9051  */
9052
9053 void Compiler::fgUpdateRefCntForExtract(GenTreePtr wholeTree, GenTreePtr keptTree)
9054 {
9055     if (lvaLocalVarRefCounted)
9056     {
9057         /*  Update the refCnts of removed lcl vars - The problem is that
9058          *  we have to consider back the side effects trees so we first
9059          *  increment all refCnts for side effects then decrement everything
9060          *  in the statement
9061          */
9062         if (keptTree)
9063         {
9064             fgWalkTreePre(&keptTree, Compiler::lvaIncRefCntsCB, (void*)this, true);
9065         }
9066
9067         fgWalkTreePre(&wholeTree, Compiler::lvaDecRefCntsCB, (void*)this, true);
9068     }
9069 }
9070
9071 VARSET_VALRET_TP Compiler::fgGetVarBits(GenTreePtr tree)
9072 {
9073     VARSET_TP VARSET_INIT_NOCOPY(varBits, VarSetOps::MakeEmpty(this));
9074
9075     assert(tree->gtOper == GT_LCL_VAR || tree->gtOper == GT_LCL_FLD || tree->gtOper == GT_REG_VAR);
9076
9077     unsigned int lclNum = tree->gtLclVarCommon.gtLclNum;
9078     LclVarDsc*   varDsc = lvaTable + lclNum;
9079     if (varDsc->lvTracked)
9080     {
9081         VarSetOps::AddElemD(this, varBits, varDsc->lvVarIndex);
9082     }
9083     else if (varDsc->lvType == TYP_STRUCT && varDsc->lvPromoted)
9084     {
9085         for (unsigned i = varDsc->lvFieldLclStart; i < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++i)
9086         {
9087             noway_assert(lvaTable[i].lvIsStructField);
9088             if (lvaTable[i].lvTracked)
9089             {
9090                 unsigned varIndex = lvaTable[i].lvVarIndex;
9091                 noway_assert(varIndex < lvaTrackedCount);
9092                 VarSetOps::AddElemD(this, varBits, varIndex);
9093             }
9094         }
9095     }
9096     return varBits;
9097 }
9098
9099 /*****************************************************************************
9100  *
9101  *  Find and remove any basic blocks that are useless (e.g. they have not been
9102  *  imported because they are not reachable, or they have been optimized away).
9103  */
9104
9105 void Compiler::fgRemoveEmptyBlocks()
9106 {
9107     BasicBlock* cur;
9108     BasicBlock* nxt;
9109
9110     /* If we remove any blocks, we'll have to do additional work */
9111
9112     unsigned removedBlks = 0;
9113
9114     for (cur = fgFirstBB; cur != nullptr; cur = nxt)
9115     {
9116         /* Get hold of the next block (in case we delete 'cur') */
9117
9118         nxt = cur->bbNext;
9119
9120         /* Should this block be removed? */
9121
9122         if (!(cur->bbFlags & BBF_IMPORTED))
9123         {
9124             noway_assert(cur->isEmpty());
9125
9126             if (ehCanDeleteEmptyBlock(cur))
9127             {
9128                 /* Mark the block as removed */
9129
9130                 cur->bbFlags |= BBF_REMOVED;
9131
9132                 /* Remember that we've removed a block from the list */
9133
9134                 removedBlks++;
9135
9136 #ifdef DEBUG
9137                 if (verbose)
9138                 {
9139                     printf("BB%02u was not imported, marked as removed (%d)\n", cur->bbNum, removedBlks);
9140                 }
9141 #endif // DEBUG
9142
9143                 /* Drop the block from the list */
9144
9145                 fgUnlinkBlock(cur);
9146             }
9147             else
9148             {
9149                 // We were prevented from deleting this block by EH normalization. Mark the block as imported.
9150                 cur->bbFlags |= BBF_IMPORTED;
9151             }
9152         }
9153     }
9154
9155     /* If no blocks were removed, we're done */
9156
9157     if (removedBlks == 0)
9158     {
9159         return;
9160     }
9161
9162     /*  Update all references in the exception handler table.
9163      *  Mark the new blocks as non-removable.
9164      *
9165      *  We may have made the entire try block unreachable.
9166      *  Check for this case and remove the entry from the EH table.
9167      */
9168
9169     unsigned  XTnum;
9170     EHblkDsc* HBtab;
9171     INDEBUG(unsigned delCnt = 0;)
9172
9173     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
9174     {
9175     AGAIN:
9176         /* If the beginning of the try block was not imported, we
9177          * need to remove the entry from the EH table. */
9178
9179         if (HBtab->ebdTryBeg->bbFlags & BBF_REMOVED)
9180         {
9181             noway_assert(!(HBtab->ebdTryBeg->bbFlags & BBF_IMPORTED));
9182 #ifdef DEBUG
9183             if (verbose)
9184             {
9185                 printf("Beginning of try block (BB%02u) not imported "
9186                        "- remove index #%u from the EH table\n",
9187                        HBtab->ebdTryBeg->bbNum, XTnum + delCnt);
9188             }
9189             delCnt++;
9190 #endif // DEBUG
9191
9192             fgRemoveEHTableEntry(XTnum);
9193
9194             if (XTnum < compHndBBtabCount)
9195             {
9196                 // There are more entries left to process, so do more. Note that
9197                 // HBtab now points to the next entry, that we copied down to the
9198                 // current slot. XTnum also stays the same.
9199                 goto AGAIN;
9200             }
9201
9202             break; // no more entries (we deleted the last one), so exit the loop
9203         }
9204
9205 /* At this point we know we have a valid try block */
9206
9207 #ifdef DEBUG
9208         assert(HBtab->ebdTryBeg->bbFlags & BBF_IMPORTED);
9209         assert(HBtab->ebdTryBeg->bbFlags & BBF_DONT_REMOVE);
9210
9211         assert(HBtab->ebdHndBeg->bbFlags & BBF_IMPORTED);
9212         assert(HBtab->ebdHndBeg->bbFlags & BBF_DONT_REMOVE);
9213
9214         if (HBtab->HasFilter())
9215         {
9216             assert(HBtab->ebdFilter->bbFlags & BBF_IMPORTED);
9217             assert(HBtab->ebdFilter->bbFlags & BBF_DONT_REMOVE);
9218         }
9219 #endif // DEBUG
9220
9221         fgSkipRmvdBlocks(HBtab);
9222     } /* end of the for loop over XTnum */
9223
9224     // Renumber the basic blocks
9225     JITDUMP("\nRenumbering the basic blocks for fgRemoveEmptyBlocks\n");
9226     fgRenumberBlocks();
9227
9228 #ifdef DEBUG
9229     fgVerifyHandlerTab();
9230 #endif // DEBUG
9231 }
9232
9233 /*****************************************************************************
9234  *
9235  * Remove a useless statement from a basic block.
9236  * The default is to decrement ref counts of included vars
9237  *
9238  */
9239
9240 void Compiler::fgRemoveStmt(BasicBlock* block,
9241                             GenTreePtr  node,
9242                             // whether to decrement ref counts for tracked vars in statement
9243                             bool updateRefCount)
9244 {
9245     noway_assert(node);
9246     assert(fgOrder == FGOrderTree);
9247
9248     GenTreeStmt* tree = block->firstStmt();
9249     GenTreeStmt* stmt = node->AsStmt();
9250
9251 #ifdef DEBUG
9252     if (verbose &&
9253         stmt->gtStmtExpr->gtOper != GT_NOP) // Don't print if it is a GT_NOP. Too much noise from the inliner.
9254     {
9255         printf("\nRemoving statement ");
9256         printTreeID(stmt);
9257         printf(" in BB%02u as useless:\n", block->bbNum);
9258         gtDispTree(stmt);
9259     }
9260 #endif // DEBUG
9261
9262     if (opts.compDbgCode && stmt->gtPrev != stmt && stmt->gtStmtILoffsx != BAD_IL_OFFSET)
9263     {
9264         /* TODO: For debuggable code, should we remove significant
9265            statement boundaries. Or should we leave a GT_NO_OP in its place? */
9266     }
9267
9268     /* Is it the first statement in the list? */
9269
9270     GenTreeStmt* firstStmt = block->firstStmt();
9271     if (firstStmt == stmt)
9272     {
9273         if (firstStmt->gtNext == nullptr)
9274         {
9275             assert(firstStmt == block->lastStmt());
9276
9277             /* this is the only statement - basic block becomes empty */
9278             block->bbTreeList = nullptr;
9279         }
9280         else
9281         {
9282             block->bbTreeList         = tree->gtNext;
9283             block->bbTreeList->gtPrev = tree->gtPrev;
9284         }
9285         goto DONE;
9286     }
9287
9288     /* Is it the last statement in the list? */
9289
9290     if (stmt == block->lastStmt())
9291     {
9292         stmt->gtPrev->gtNext      = nullptr;
9293         block->bbTreeList->gtPrev = stmt->gtPrev;
9294         goto DONE;
9295     }
9296
9297     tree = stmt->gtPrevStmt;
9298     noway_assert(tree);
9299
9300     tree->gtNext         = stmt->gtNext;
9301     stmt->gtNext->gtPrev = tree;
9302
9303 DONE:
9304     fgStmtRemoved = true;
9305
9306     if (optValnumCSE_phase)
9307     {
9308         optValnumCSE_UnmarkCSEs(stmt->gtStmtExpr, nullptr);
9309     }
9310     else
9311     {
9312         if (updateRefCount)
9313         {
9314             if (fgStmtListThreaded)
9315             {
9316                 fgWalkTreePre(&stmt->gtStmtExpr, Compiler::lvaDecRefCntsCB, (void*)this, true);
9317             }
9318         }
9319     }
9320
9321 #ifdef DEBUG
9322     if (verbose)
9323     {
9324         if (block->bbTreeList == nullptr)
9325         {
9326             printf("\nBB%02u becomes empty", block->bbNum);
9327         }
9328         printf("\n");
9329     }
9330 #endif // DEBUG
9331 }
9332
9333 /******************************************************************************/
9334 // Returns true if the operator is involved in control-flow
9335 // TODO-Cleanup: Move this into genTreeKinds in genTree.h
9336
9337 inline bool OperIsControlFlow(genTreeOps oper)
9338 {
9339     switch (oper)
9340     {
9341         case GT_JTRUE:
9342         case GT_SWITCH:
9343         case GT_LABEL:
9344
9345         case GT_CALL:
9346         case GT_JMP:
9347
9348         case GT_RETURN:
9349         case GT_RETFILT:
9350 #if !FEATURE_EH_FUNCLETS
9351         case GT_END_LFIN:
9352 #endif // !FEATURE_EH_FUNCLETS
9353             return true;
9354
9355         default:
9356             return false;
9357     }
9358 }
9359
9360 /******************************************************************************
9361  *  Tries to throw away a stmt. The statement can be anywhere in block->bbTreeList.
9362  *  Returns true if it did remove the statement.
9363  */
9364
9365 bool Compiler::fgCheckRemoveStmt(BasicBlock* block, GenTreePtr node)
9366 {
9367     if (opts.compDbgCode)
9368     {
9369         return false;
9370     }
9371
9372     GenTreeStmt* stmt = node->AsStmt();
9373
9374     GenTreePtr tree = stmt->gtStmtExpr;
9375     genTreeOps oper = tree->OperGet();
9376
9377     if (OperIsControlFlow(oper) || oper == GT_NO_OP)
9378     {
9379         return false;
9380     }
9381
9382     // TODO: Use a recursive version of gtNodeHasSideEffects()
9383     if (tree->gtFlags & GTF_SIDE_EFFECT)
9384     {
9385         return false;
9386     }
9387
9388     fgRemoveStmt(block, stmt);
9389     return true;
9390 }
9391
9392 /****************************************************************************************************
9393  *
9394  *
9395  */
9396 bool Compiler::fgCanCompactBlocks(BasicBlock* block, BasicBlock* bNext)
9397 {
9398     if ((block == nullptr) || (bNext == nullptr))
9399     {
9400         return false;
9401     }
9402
9403     noway_assert(block->bbNext == bNext);
9404
9405     if (block->bbJumpKind != BBJ_NONE)
9406     {
9407         return false;
9408     }
9409
9410     // If the next block has multiple incoming edges, we can still compact if the first block is empty.
9411     // However, not if it is the beginning of a handler.
9412     if (bNext->countOfInEdges() != 1 &&
9413         (!block->isEmpty() || (block->bbFlags & BBF_FUNCLET_BEG) || (block->bbCatchTyp != BBCT_NONE)))
9414     {
9415         return false;
9416     }
9417
9418     if (bNext->bbFlags & BBF_DONT_REMOVE)
9419     {
9420         return false;
9421     }
9422
9423     // Don't compact the first block if it was specially created as a scratch block.
9424     if (fgBBisScratch(block))
9425     {
9426         return false;
9427     }
9428
9429 #if defined(_TARGET_ARM_)
9430     // We can't compact a finally target block, as we need to generate special code for such blocks during code
9431     // generation
9432     if ((bNext->bbFlags & BBF_FINALLY_TARGET) != 0)
9433         return false;
9434 #endif
9435
9436     // We don't want to compact blocks that are in different Hot/Cold regions
9437     //
9438     if (fgInDifferentRegions(block, bNext))
9439     {
9440         return false;
9441     }
9442
9443     // We cannot compact two blocks in different EH regions.
9444     //
9445     if (fgCanRelocateEHRegions)
9446     {
9447         if (!BasicBlock::sameEHRegion(block, bNext))
9448         {
9449             return false;
9450         }
9451     }
9452     // if there is a switch predecessor don't bother because we'd have to update the uniquesuccs as well
9453     // (if they are valid)
9454     for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext)
9455     {
9456         if (pred->flBlock->bbJumpKind == BBJ_SWITCH)
9457         {
9458             return false;
9459         }
9460     }
9461
9462     return true;
9463 }
9464
9465 /*****************************************************************************************************
9466  *
9467  *  Function called to compact two given blocks in the flowgraph
9468  *  Assumes that all necessary checks have been performed,
9469  *  i.e. fgCanCompactBlocks returns true.
9470  *
9471  *  Uses for this function - whenever we change links, insert blocks,...
9472  *  It will keep the flowgraph data in synch - bbNum, bbRefs, bbPreds
9473  */
9474
9475 void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext)
9476 {
9477     noway_assert(block != nullptr);
9478     noway_assert((block->bbFlags & BBF_REMOVED) == 0);
9479     noway_assert(block->bbJumpKind == BBJ_NONE);
9480
9481     noway_assert(bNext == block->bbNext);
9482     noway_assert(bNext != nullptr);
9483     noway_assert((bNext->bbFlags & BBF_REMOVED) == 0);
9484     noway_assert(bNext->countOfInEdges() == 1 || block->isEmpty());
9485     noway_assert(bNext->bbPreds);
9486
9487 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9488     noway_assert((bNext->bbFlags & BBF_FINALLY_TARGET) == 0);
9489 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9490
9491     // Make sure the second block is not the start of a TRY block or an exception handler
9492
9493     noway_assert(bNext->bbCatchTyp == BBCT_NONE);
9494     noway_assert((bNext->bbFlags & BBF_TRY_BEG) == 0);
9495     noway_assert((bNext->bbFlags & BBF_DONT_REMOVE) == 0);
9496
9497     /* both or none must have an exception handler */
9498     noway_assert(block->hasTryIndex() == bNext->hasTryIndex());
9499
9500 #ifdef DEBUG
9501     if (verbose)
9502     {
9503         printf("\nCompacting blocks BB%02u and BB%02u:\n", block->bbNum, bNext->bbNum);
9504     }
9505 #endif
9506
9507     if (bNext->countOfInEdges() > 1)
9508     {
9509         JITDUMP("Second block has multiple incoming edges\n");
9510
9511         assert(block->isEmpty());
9512         block->bbFlags |= BBF_JMP_TARGET;
9513         for (flowList* pred = bNext->bbPreds; pred; pred = pred->flNext)
9514         {
9515             fgReplaceJumpTarget(pred->flBlock, block, bNext);
9516
9517             if (pred->flBlock != block)
9518             {
9519                 fgAddRefPred(block, pred->flBlock);
9520             }
9521         }
9522         bNext->bbPreds = nullptr;
9523     }
9524     else
9525     {
9526         noway_assert(bNext->bbPreds->flNext == nullptr);
9527         noway_assert(bNext->bbPreds->flBlock == block);
9528     }
9529
9530     /* Start compacting - move all the statements in the second block to the first block */
9531
9532     // First move any phi definitions of the second block after the phi defs of the first.
9533     // TODO-CQ: This may be the wrong thing to do.  If we're compacting blocks, it's because a
9534     // control-flow choice was constant-folded away.  So probably phi's need to go away,
9535     // as well, in favor of one of the incoming branches.  Or at least be modified.
9536
9537     assert(block->IsLIR() == bNext->IsLIR());
9538     if (block->IsLIR())
9539     {
9540         LIR::Range& blockRange = LIR::AsRange(block);
9541         LIR::Range& nextRange  = LIR::AsRange(bNext);
9542
9543         // Does the next block have any phis?
9544         GenTree*           nextFirstNonPhi = nullptr;
9545         LIR::ReadOnlyRange nextPhis        = nextRange.PhiNodes();
9546         if (!nextPhis.IsEmpty())
9547         {
9548             GenTree* blockLastPhi = blockRange.LastPhiNode();
9549             nextFirstNonPhi       = nextPhis.LastNode()->gtNext;
9550
9551             LIR::Range phisToMove = nextRange.Remove(std::move(nextPhis));
9552             blockRange.InsertAfter(blockLastPhi, std::move(phisToMove));
9553         }
9554         else
9555         {
9556             nextFirstNonPhi = nextRange.FirstNode();
9557         }
9558
9559         // Does the block have any other code?
9560         if (nextFirstNonPhi != nullptr)
9561         {
9562             LIR::Range nextNodes = nextRange.Remove(nextFirstNonPhi, nextRange.LastNode());
9563             blockRange.InsertAtEnd(std::move(nextNodes));
9564         }
9565     }
9566     else
9567     {
9568         GenTreePtr blkNonPhi1   = block->FirstNonPhiDef();
9569         GenTreePtr bNextNonPhi1 = bNext->FirstNonPhiDef();
9570         GenTreePtr blkFirst     = block->firstStmt();
9571         GenTreePtr bNextFirst   = bNext->firstStmt();
9572
9573         // Does the second have any phis?
9574         if (bNextFirst != nullptr && bNextFirst != bNextNonPhi1)
9575         {
9576             GenTreePtr bNextLast = bNextFirst->gtPrev;
9577             assert(bNextLast->gtNext == nullptr);
9578
9579             // Does "blk" have phis?
9580             if (blkNonPhi1 != blkFirst)
9581             {
9582                 // Yes, has phis.
9583                 // Insert after the last phi of "block."
9584                 // First, bNextPhis after last phi of block.
9585                 GenTreePtr blkLastPhi;
9586                 if (blkNonPhi1 != nullptr)
9587                 {
9588                     blkLastPhi = blkNonPhi1->gtPrev;
9589                 }
9590                 else
9591                 {
9592                     blkLastPhi = blkFirst->gtPrev;
9593                 }
9594
9595                 blkLastPhi->gtNext = bNextFirst;
9596                 bNextFirst->gtPrev = blkLastPhi;
9597
9598                 // Now, rest of "block" after last phi of "bNext".
9599                 GenTreePtr bNextLastPhi = nullptr;
9600                 if (bNextNonPhi1 != nullptr)
9601                 {
9602                     bNextLastPhi = bNextNonPhi1->gtPrev;
9603                 }
9604                 else
9605                 {
9606                     bNextLastPhi = bNextFirst->gtPrev;
9607                 }
9608
9609                 bNextLastPhi->gtNext = blkNonPhi1;
9610                 if (blkNonPhi1 != nullptr)
9611                 {
9612                     blkNonPhi1->gtPrev = bNextLastPhi;
9613                 }
9614                 else
9615                 {
9616                     // block has no non phis, so make the last statement be the last added phi.
9617                     blkFirst->gtPrev = bNextLastPhi;
9618                 }
9619
9620                 // Now update the bbTreeList of "bNext".
9621                 bNext->bbTreeList = bNextNonPhi1;
9622                 if (bNextNonPhi1 != nullptr)
9623                 {
9624                     bNextNonPhi1->gtPrev = bNextLast;
9625                 }
9626             }
9627             else
9628             {
9629                 if (blkFirst != nullptr) // If "block" has no statements, fusion will work fine...
9630                 {
9631                     // First, bNextPhis at start of block.
9632                     GenTreePtr blkLast = blkFirst->gtPrev;
9633                     block->bbTreeList  = bNextFirst;
9634                     // Now, rest of "block" (if it exists) after last phi of "bNext".
9635                     GenTreePtr bNextLastPhi = nullptr;
9636                     if (bNextNonPhi1 != nullptr)
9637                     {
9638                         // There is a first non phi, so the last phi is before it.
9639                         bNextLastPhi = bNextNonPhi1->gtPrev;
9640                     }
9641                     else
9642                     {
9643                         // All the statements are phi defns, so the last one is the prev of the first.
9644                         bNextLastPhi = bNextFirst->gtPrev;
9645                     }
9646                     bNextFirst->gtPrev   = blkLast;
9647                     bNextLastPhi->gtNext = blkFirst;
9648                     blkFirst->gtPrev     = bNextLastPhi;
9649                     // Now update the bbTreeList of "bNext"
9650                     bNext->bbTreeList = bNextNonPhi1;
9651                     if (bNextNonPhi1 != nullptr)
9652                     {
9653                         bNextNonPhi1->gtPrev = bNextLast;
9654                     }
9655                 }
9656             }
9657         }
9658
9659         // Now proceed with the updated bbTreeLists.
9660         GenTreePtr stmtList1 = block->firstStmt();
9661         GenTreePtr stmtList2 = bNext->firstStmt();
9662
9663         /* the block may have an empty list */
9664
9665         if (stmtList1)
9666         {
9667             GenTreePtr stmtLast1 = block->lastStmt();
9668
9669             /* The second block may be a GOTO statement or something with an empty bbTreeList */
9670             if (stmtList2)
9671             {
9672                 GenTreePtr stmtLast2 = bNext->lastStmt();
9673
9674                 /* append list2 to list 1 */
9675
9676                 stmtLast1->gtNext = stmtList2;
9677                 stmtList2->gtPrev = stmtLast1;
9678                 stmtList1->gtPrev = stmtLast2;
9679             }
9680         }
9681         else
9682         {
9683             /* block was formerly empty and now has bNext's statements */
9684             block->bbTreeList = stmtList2;
9685         }
9686     }
9687
9688     // Note we could update the local variable weights here by
9689     // calling lvaMarkLocalVars, with the block and weight adjustment.
9690
9691     // If either block or bNext has a profile weight
9692     // or if both block and bNext have non-zero weights
9693     // then we select the highest weight block.
9694
9695     if ((block->bbFlags & BBF_PROF_WEIGHT) || (bNext->bbFlags & BBF_PROF_WEIGHT) ||
9696         (block->bbWeight && bNext->bbWeight))
9697     {
9698         // We are keeping block so update its fields
9699         // when bNext has a greater weight
9700
9701         if (block->bbWeight < bNext->bbWeight)
9702         {
9703             block->bbWeight = bNext->bbWeight;
9704
9705             block->bbFlags |= (bNext->bbFlags & BBF_PROF_WEIGHT); // Set the profile weight flag (if necessary)
9706             if (block->bbWeight != 0)
9707             {
9708                 block->bbFlags &= ~BBF_RUN_RARELY; // Clear any RarelyRun flag
9709             }
9710         }
9711     }
9712     // otherwise if either block has a zero weight we select the zero weight
9713     else
9714     {
9715         noway_assert((block->bbWeight == BB_ZERO_WEIGHT) || (bNext->bbWeight == BB_ZERO_WEIGHT));
9716         block->bbWeight = BB_ZERO_WEIGHT;
9717         block->bbFlags |= BBF_RUN_RARELY; // Set the RarelyRun flag
9718     }
9719
9720     /* set the right links */
9721
9722     block->bbJumpKind = bNext->bbJumpKind;
9723     VarSetOps::AssignAllowUninitRhs(this, block->bbLiveOut, bNext->bbLiveOut);
9724
9725     // Update the beginning and ending IL offsets (bbCodeOffs and bbCodeOffsEnd).
9726     // Set the beginning IL offset to the minimum, and the ending offset to the maximum, of the respective blocks.
9727     // If one block has an unknown offset, we take the other block.
9728     // We are merging into 'block', so if its values are correct, just leave them alone.
9729     // TODO: we should probably base this on the statements within.
9730
9731     if (block->bbCodeOffs == BAD_IL_OFFSET)
9732     {
9733         block->bbCodeOffs = bNext->bbCodeOffs; // If they are both BAD_IL_OFFSET, this doesn't change anything.
9734     }
9735     else if (bNext->bbCodeOffs != BAD_IL_OFFSET)
9736     {
9737         // The are both valid offsets; compare them.
9738         if (block->bbCodeOffs > bNext->bbCodeOffs)
9739         {
9740             block->bbCodeOffs = bNext->bbCodeOffs;
9741         }
9742     }
9743
9744     if (block->bbCodeOffsEnd == BAD_IL_OFFSET)
9745     {
9746         block->bbCodeOffsEnd = bNext->bbCodeOffsEnd; // If they are both BAD_IL_OFFSET, this doesn't change anything.
9747     }
9748     else if (bNext->bbCodeOffsEnd != BAD_IL_OFFSET)
9749     {
9750         // The are both valid offsets; compare them.
9751         if (block->bbCodeOffsEnd < bNext->bbCodeOffsEnd)
9752         {
9753             block->bbCodeOffsEnd = bNext->bbCodeOffsEnd;
9754         }
9755     }
9756
9757     if (((block->bbFlags & BBF_INTERNAL) != 0) && ((bNext->bbFlags & BBF_INTERNAL) == 0))
9758     {
9759         // If 'block' is an internal block and 'bNext' isn't, then adjust the flags set on 'block'.
9760         block->bbFlags &= ~BBF_INTERNAL; // Clear the BBF_INTERNAL flag
9761         block->bbFlags |= BBF_IMPORTED;  // Set the BBF_IMPORTED flag
9762     }
9763
9764     /* Update the flags for block with those found in bNext */
9765
9766     block->bbFlags |= (bNext->bbFlags & BBF_COMPACT_UPD);
9767
9768     /* mark bNext as removed */
9769
9770     bNext->bbFlags |= BBF_REMOVED;
9771
9772     /* Unlink bNext and update all the marker pointers if necessary */
9773
9774     fgUnlinkRange(block->bbNext, bNext);
9775
9776     // If bNext was the last block of a try or handler, update the EH table.
9777
9778     ehUpdateForDeletedBlock(bNext);
9779
9780     /* If we're collapsing a block created after the dominators are
9781        computed, rename the block and reuse dominator information from
9782        the other block */
9783     if (fgDomsComputed && block->bbNum > fgDomBBcount)
9784     {
9785         BlockSetOps::Assign(this, block->bbReach, bNext->bbReach);
9786         BlockSetOps::ClearD(this, bNext->bbReach);
9787
9788         block->bbIDom = bNext->bbIDom;
9789         bNext->bbIDom = nullptr;
9790
9791         // In this case, there's no need to update the preorder and postorder numbering
9792         // since we're changing the bbNum, this makes the basic block all set.
9793         block->bbNum = bNext->bbNum;
9794     }
9795
9796     /* Set the jump targets */
9797
9798     switch (bNext->bbJumpKind)
9799     {
9800         case BBJ_CALLFINALLY:
9801             // Propagate RETLESS property
9802             block->bbFlags |= (bNext->bbFlags & BBF_RETLESS_CALL);
9803
9804             __fallthrough;
9805
9806         case BBJ_COND:
9807         case BBJ_ALWAYS:
9808         case BBJ_EHCATCHRET:
9809             block->bbJumpDest = bNext->bbJumpDest;
9810
9811             /* Update the predecessor list for 'bNext->bbJumpDest' */
9812             fgReplacePred(bNext->bbJumpDest, bNext, block);
9813
9814             /* Update the predecessor list for 'bNext->bbNext' if it is different than 'bNext->bbJumpDest' */
9815             if (bNext->bbJumpKind == BBJ_COND && bNext->bbJumpDest != bNext->bbNext)
9816             {
9817                 fgReplacePred(bNext->bbNext, bNext, block);
9818             }
9819             break;
9820
9821         case BBJ_NONE:
9822             /* Update the predecessor list for 'bNext->bbNext' */
9823             fgReplacePred(bNext->bbNext, bNext, block);
9824             break;
9825
9826         case BBJ_EHFILTERRET:
9827             fgReplacePred(bNext->bbJumpDest, bNext, block);
9828             break;
9829
9830         case BBJ_EHFINALLYRET:
9831         {
9832             unsigned  hndIndex = block->getHndIndex();
9833             EHblkDsc* ehDsc    = ehGetDsc(hndIndex);
9834
9835             if (ehDsc->HasFinallyHandler()) // No need to do this for fault handlers
9836             {
9837                 BasicBlock* begBlk;
9838                 BasicBlock* endBlk;
9839                 ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
9840
9841                 BasicBlock* finBeg = ehDsc->ebdHndBeg;
9842
9843                 for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
9844                 {
9845                     if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg)
9846                     {
9847                         continue;
9848                     }
9849
9850                     noway_assert(bcall->isBBCallAlwaysPair());
9851                     fgReplacePred(bcall->bbNext, bNext, block);
9852                 }
9853             }
9854         }
9855         break;
9856
9857         case BBJ_THROW:
9858         case BBJ_RETURN:
9859             /* no jumps or fall through blocks to set here */
9860             break;
9861
9862         case BBJ_SWITCH:
9863             block->bbJumpSwt = bNext->bbJumpSwt;
9864             // We are moving the switch jump from bNext to block.  Examine the jump targets
9865             // of the BBJ_SWITCH at bNext and replace the predecessor to 'bNext' with ones to 'block'
9866             fgChangeSwitchBlock(bNext, block);
9867             break;
9868
9869         default:
9870             noway_assert(!"Unexpected bbJumpKind");
9871             break;
9872     }
9873
9874     fgUpdateLoopsAfterCompacting(block, bNext);
9875
9876 #if DEBUG
9877     if (verbose && 0)
9878     {
9879         printf("\nAfter compacting:\n");
9880         fgDispBasicBlocks(false);
9881     }
9882 #endif
9883
9884 #if DEBUG
9885     if (JitConfig.JitSlowDebugChecksEnabled() != 0)
9886     {
9887         // Make sure that the predecessor lists are accurate
9888         fgDebugCheckBBlist();
9889     }
9890 #endif // DEBUG
9891 }
9892
9893 void Compiler::fgUpdateLoopsAfterCompacting(BasicBlock* block, BasicBlock* bNext)
9894 {
9895     /* Check if the removed block is not part the loop table */
9896     noway_assert(bNext);
9897
9898     for (unsigned loopNum = 0; loopNum < optLoopCount; loopNum++)
9899     {
9900         /* Some loops may have been already removed by
9901          * loop unrolling or conditional folding */
9902
9903         if (optLoopTable[loopNum].lpFlags & LPFLG_REMOVED)
9904         {
9905             continue;
9906         }
9907
9908         /* Check the loop head (i.e. the block preceding the loop) */
9909
9910         if (optLoopTable[loopNum].lpHead == bNext)
9911         {
9912             optLoopTable[loopNum].lpHead = block;
9913         }
9914
9915         /* Check the loop bottom */
9916
9917         if (optLoopTable[loopNum].lpBottom == bNext)
9918         {
9919             optLoopTable[loopNum].lpBottom = block;
9920         }
9921
9922         /* Check the loop exit */
9923
9924         if (optLoopTable[loopNum].lpExit == bNext)
9925         {
9926             noway_assert(optLoopTable[loopNum].lpExitCnt == 1);
9927             optLoopTable[loopNum].lpExit = block;
9928         }
9929
9930         /* Check the loop entry */
9931
9932         if (optLoopTable[loopNum].lpEntry == bNext)
9933         {
9934             optLoopTable[loopNum].lpEntry = block;
9935         }
9936     }
9937 }
9938
9939 /*****************************************************************************************************
9940  *
9941  *  Function called to remove a block when it is unreachable.
9942  *
9943  *  This function cannot remove the first block.
9944  */
9945
9946 void Compiler::fgUnreachableBlock(BasicBlock* block)
9947 {
9948     // genReturnBB should never be removed, as we might have special hookups there.
9949     // Therefore, we should never come here to remove the statements in the genReturnBB block.
9950     // For example, <BUGNUM> in VSW 364383, </BUGNUM>
9951     // the profiler hookup needs to have the "void GT_RETURN" statement
9952     // to properly set the info.compProfilerCallback flag.
9953     noway_assert(block != genReturnBB);
9954
9955     if (block->bbFlags & BBF_REMOVED)
9956     {
9957         return;
9958     }
9959
9960 /* Removing an unreachable block */
9961
9962 #ifdef DEBUG
9963     if (verbose)
9964     {
9965         printf("\nRemoving unreachable BB%02u\n", block->bbNum);
9966     }
9967 #endif // DEBUG
9968
9969     noway_assert(block->bbPrev != nullptr); // Can use this function to remove the first block
9970
9971 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9972     assert(!block->bbPrev->isBBCallAlwaysPair()); // can't remove the BBJ_ALWAYS of a BBJ_CALLFINALLY / BBJ_ALWAYS pair
9973 #endif                                            // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
9974
9975     /* First walk the statement trees in this basic block and delete each stmt */
9976
9977     /* Make the block publicly available */
9978     compCurBB = block;
9979
9980     if (block->IsLIR())
9981     {
9982         LIR::Range& blockRange = LIR::AsRange(block);
9983         if (!blockRange.IsEmpty())
9984         {
9985             blockRange.Delete(this, block, blockRange.FirstNode(), blockRange.LastNode());
9986         }
9987     }
9988     else
9989     {
9990         // TODO-Cleanup: I'm not sure why this happens -- if the block is unreachable, why does it have phis?
9991         // Anyway, remove any phis.
9992
9993         GenTreePtr firstNonPhi = block->FirstNonPhiDef();
9994         if (block->bbTreeList != firstNonPhi)
9995         {
9996             if (firstNonPhi != nullptr)
9997             {
9998                 firstNonPhi->gtPrev = block->lastStmt();
9999             }
10000             block->bbTreeList = firstNonPhi;
10001         }
10002
10003         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
10004         {
10005             fgRemoveStmt(block, stmt);
10006         }
10007         noway_assert(block->bbTreeList == nullptr);
10008     }
10009
10010     /* Next update the loop table and bbWeights */
10011     optUpdateLoopsBeforeRemoveBlock(block);
10012
10013     /* Mark the block as removed */
10014     block->bbFlags |= BBF_REMOVED;
10015
10016     /* update bbRefs and bbPreds for the blocks reached by this block */
10017     fgRemoveBlockAsPred(block);
10018 }
10019
10020 /*****************************************************************************************************
10021  *
10022  *  Function called to remove or morph a GT_JTRUE statement when we jump to the same
10023  *  block when both the condition is true or false.
10024  */
10025 void Compiler::fgRemoveJTrue(BasicBlock* block)
10026 {
10027     noway_assert(block->bbJumpKind == BBJ_COND && block->bbJumpDest == block->bbNext);
10028     assert(compRationalIRForm == block->IsLIR());
10029
10030     flowList* flow = fgGetPredForBlock(block->bbNext, block);
10031     noway_assert(flow->flDupCount == 2);
10032
10033     // Change the BBJ_COND to BBJ_NONE, and adjust the refCount and dupCount.
10034     block->bbJumpKind = BBJ_NONE;
10035     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
10036     --block->bbNext->bbRefs;
10037     --flow->flDupCount;
10038
10039 #ifdef DEBUG
10040     block->bbJumpDest = nullptr;
10041     if (verbose)
10042     {
10043         printf("Block BB%02u becoming a BBJ_NONE to BB%02u (jump target is the same whether the condition is true or "
10044                "false)\n",
10045                block->bbNum, block->bbNext->bbNum);
10046     }
10047 #endif
10048
10049     /* Remove the block jump condition */
10050
10051     if (block->IsLIR())
10052     {
10053         LIR::Range& blockRange = LIR::AsRange(block);
10054
10055         GenTree* test = blockRange.LastNode();
10056         assert(test->OperGet() == GT_JTRUE);
10057
10058         bool               isClosed;
10059         unsigned           sideEffects;
10060         LIR::ReadOnlyRange testRange = blockRange.GetTreeRange(test, &isClosed, &sideEffects);
10061
10062         // TODO-LIR: this should really be checking GTF_ALL_EFFECT, but that produces unacceptable
10063         //            diffs compared to the existing backend.
10064         if (isClosed && ((sideEffects & GTF_SIDE_EFFECT) == 0))
10065         {
10066             // If the jump and its operands form a contiguous, side-effect-free range,
10067             // remove them.
10068             blockRange.Delete(this, block, std::move(testRange));
10069         }
10070         else
10071         {
10072             // Otherwise, just remove the jump node itself.
10073             blockRange.Remove(test);
10074         }
10075     }
10076     else
10077     {
10078         GenTreeStmt* test = block->lastStmt();
10079         GenTree*     tree = test->gtStmtExpr;
10080
10081         noway_assert(tree->gtOper == GT_JTRUE);
10082
10083         GenTree* sideEffList = nullptr;
10084
10085         if (tree->gtFlags & GTF_SIDE_EFFECT)
10086         {
10087             gtExtractSideEffList(tree, &sideEffList);
10088
10089             if (sideEffList)
10090             {
10091                 noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
10092 #ifdef DEBUG
10093                 if (verbose)
10094                 {
10095                     printf("Extracted side effects list from condition...\n");
10096                     gtDispTree(sideEffList);
10097                     printf("\n");
10098                 }
10099 #endif
10100             }
10101         }
10102
10103         // Delete the cond test or replace it with the side effect tree
10104         if (sideEffList == nullptr)
10105         {
10106             fgRemoveStmt(block, test);
10107         }
10108         else
10109         {
10110             test->gtStmtExpr = sideEffList;
10111
10112             fgMorphBlockStmt(block, test DEBUGARG("fgRemoveJTrue"));
10113         }
10114     }
10115 }
10116
10117 /*****************************************************************************************************
10118  *
10119  *  Function to return the last basic block in the main part of the function. With funclets, it is
10120  *  the block immediately before the first funclet.
10121  *  An inclusive end of the main method.
10122  */
10123
10124 BasicBlock* Compiler::fgLastBBInMainFunction()
10125 {
10126 #if FEATURE_EH_FUNCLETS
10127
10128     if (fgFirstFuncletBB != nullptr)
10129     {
10130         return fgFirstFuncletBB->bbPrev;
10131     }
10132
10133 #endif // FEATURE_EH_FUNCLETS
10134
10135     assert(fgLastBB->bbNext == nullptr);
10136
10137     return fgLastBB;
10138 }
10139
10140 /*****************************************************************************************************
10141  *
10142  *  Function to return the first basic block after the main part of the function. With funclets, it is
10143  *  the block of the first funclet.  Otherwise it is NULL if there are no funclets (fgLastBB->bbNext).
10144  *  This is equivalent to fgLastBBInMainFunction()->bbNext
10145  *  An exclusive end of the main method.
10146  */
10147
10148 BasicBlock* Compiler::fgEndBBAfterMainFunction()
10149 {
10150 #if FEATURE_EH_FUNCLETS
10151
10152     if (fgFirstFuncletBB != nullptr)
10153     {
10154         return fgFirstFuncletBB;
10155     }
10156
10157 #endif // FEATURE_EH_FUNCLETS
10158
10159     assert(fgLastBB->bbNext == nullptr);
10160
10161     return nullptr;
10162 }
10163
10164 // Removes the block from the bbPrev/bbNext chain
10165 // Updates fgFirstBB and fgLastBB if necessary
10166 // Does not update fgFirstFuncletBB or fgFirstColdBlock (fgUnlinkRange does)
10167
10168 void Compiler::fgUnlinkBlock(BasicBlock* block)
10169 {
10170     if (block->bbPrev)
10171     {
10172         block->bbPrev->bbNext = block->bbNext;
10173         if (block->bbNext)
10174         {
10175             block->bbNext->bbPrev = block->bbPrev;
10176         }
10177         else
10178         {
10179             fgLastBB = block->bbPrev;
10180         }
10181     }
10182     else
10183     {
10184         assert(block == fgFirstBB);
10185         assert(block != fgLastBB);
10186         assert((fgFirstBBScratch == nullptr) || (fgFirstBBScratch == fgFirstBB));
10187
10188         fgFirstBB         = block->bbNext;
10189         fgFirstBB->bbPrev = nullptr;
10190
10191         if (fgFirstBBScratch != nullptr)
10192         {
10193 #ifdef DEBUG
10194             // We had created an initial scratch BB, but now we're deleting it.
10195             if (verbose)
10196             {
10197                 printf("Unlinking scratch BB%02u\n", block->bbNum);
10198             }
10199 #endif // DEBUG
10200             fgFirstBBScratch = nullptr;
10201         }
10202     }
10203 }
10204
10205 /*****************************************************************************************************
10206  *
10207  *  Function called to unlink basic block range [bBeg .. bEnd] from the basic block list.
10208  *
10209  *  'bBeg' can't be the first block.
10210  */
10211
10212 void Compiler::fgUnlinkRange(BasicBlock* bBeg, BasicBlock* bEnd)
10213 {
10214     assert(bBeg != nullptr);
10215     assert(bEnd != nullptr);
10216
10217     BasicBlock* bPrev = bBeg->bbPrev;
10218     assert(bPrev != nullptr); // Can't unlink a range starting with the first block
10219
10220     bPrev->setNext(bEnd->bbNext);
10221
10222     /* If we removed the last block in the method then update fgLastBB */
10223     if (fgLastBB == bEnd)
10224     {
10225         fgLastBB = bPrev;
10226         noway_assert(fgLastBB->bbNext == nullptr);
10227     }
10228
10229     // If bEnd was the first Cold basic block update fgFirstColdBlock
10230     if (fgFirstColdBlock == bEnd)
10231     {
10232         fgFirstColdBlock = bPrev->bbNext;
10233     }
10234
10235 #if FEATURE_EH_FUNCLETS
10236 #ifdef DEBUG
10237     // You can't unlink a range that includes the first funclet block. A range certainly
10238     // can't cross the non-funclet/funclet region. And you can't unlink the first block
10239     // of the first funclet with this, either. (If that's necessary, it could be allowed
10240     // by updating fgFirstFuncletBB to bEnd->bbNext.)
10241     for (BasicBlock* tempBB = bBeg; tempBB != bEnd->bbNext; tempBB = tempBB->bbNext)
10242     {
10243         assert(tempBB != fgFirstFuncletBB);
10244     }
10245 #endif // DEBUG
10246 #endif // FEATURE_EH_FUNCLETS
10247 }
10248
10249 /*****************************************************************************************************
10250  *
10251  *  Function called to remove a basic block
10252  */
10253
10254 void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable)
10255 {
10256     BasicBlock* bPrev = block->bbPrev;
10257
10258     /* The block has to be either unreachable or empty */
10259
10260     PREFIX_ASSUME(block != nullptr);
10261
10262     JITDUMP("fgRemoveBlock BB%02u\n", block->bbNum);
10263
10264     // If we've cached any mappings from switch blocks to SwitchDesc's (which contain only the
10265     // *unique* successors of the switch block), invalidate that cache, since an entry in one of
10266     // the SwitchDescs might be removed.
10267     InvalidateUniqueSwitchSuccMap();
10268
10269     noway_assert((block == fgFirstBB) || (bPrev && (bPrev->bbNext == block)));
10270     noway_assert(!(block->bbFlags & BBF_DONT_REMOVE));
10271
10272     // Should never remove a genReturnBB, as we might have special hookups there.
10273     noway_assert(block != genReturnBB);
10274
10275 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10276     // Don't remove a finally target
10277     assert(!(block->bbFlags & BBF_FINALLY_TARGET));
10278 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10279
10280     if (unreachable)
10281     {
10282         PREFIX_ASSUME(bPrev != nullptr);
10283
10284         fgUnreachableBlock(block);
10285
10286         /* If this is the last basic block update fgLastBB */
10287         if (block == fgLastBB)
10288         {
10289             fgLastBB = bPrev;
10290         }
10291
10292 #if FEATURE_EH_FUNCLETS
10293         // If block was the fgFirstFuncletBB then set fgFirstFuncletBB to block->bbNext
10294         if (block == fgFirstFuncletBB)
10295         {
10296             fgFirstFuncletBB = block->bbNext;
10297         }
10298 #endif // FEATURE_EH_FUNCLETS
10299
10300         if (bPrev->bbJumpKind == BBJ_CALLFINALLY)
10301         {
10302             // bPrev CALL becomes RETLESS as the BBJ_ALWAYS block is unreachable
10303             bPrev->bbFlags |= BBF_RETLESS_CALL;
10304
10305 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10306             NO_WAY("No retless call finally blocks; need unwind target instead");
10307 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10308         }
10309         else if (bPrev->bbJumpKind == BBJ_ALWAYS && bPrev->bbJumpDest == block->bbNext &&
10310                  !(bPrev->bbFlags & BBF_KEEP_BBJ_ALWAYS) && (block != fgFirstColdBlock) &&
10311                  (block->bbNext != fgFirstColdBlock))
10312         {
10313             // previous block is a BBJ_ALWAYS to the next block: change to BBJ_NONE.
10314             // Note that we don't do it if bPrev follows a BBJ_CALLFINALLY block (BBF_KEEP_BBJ_ALWAYS),
10315             // because that would violate our invariant that BBJ_CALLFINALLY blocks are followed by
10316             // BBJ_ALWAYS blocks.
10317             bPrev->bbJumpKind = BBJ_NONE;
10318             bPrev->bbFlags &= ~BBF_NEEDS_GCPOLL;
10319         }
10320
10321         // If this is the first Cold basic block update fgFirstColdBlock
10322         if (block == fgFirstColdBlock)
10323         {
10324             fgFirstColdBlock = block->bbNext;
10325         }
10326
10327         /* Unlink this block from the bbNext chain */
10328         fgUnlinkBlock(block);
10329
10330         /* At this point the bbPreds and bbRefs had better be zero */
10331         noway_assert((block->bbRefs == 0) && (block->bbPreds == nullptr));
10332
10333         /*  A BBJ_CALLFINALLY is usually paired with a BBJ_ALWAYS.
10334          *  If we delete such a BBJ_CALLFINALLY we also delete the BBJ_ALWAYS
10335          */
10336         if (block->isBBCallAlwaysPair())
10337         {
10338             BasicBlock* leaveBlk = block->bbNext;
10339             noway_assert(leaveBlk->bbJumpKind == BBJ_ALWAYS);
10340
10341             leaveBlk->bbFlags &= ~BBF_DONT_REMOVE;
10342             leaveBlk->bbRefs  = 0;
10343             leaveBlk->bbPreds = nullptr;
10344
10345             fgRemoveBlock(leaveBlk, true);
10346
10347 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10348             fgClearFinallyTargetBit(leaveBlk->bbJumpDest);
10349 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
10350         }
10351         else if (block->bbJumpKind == BBJ_RETURN)
10352         {
10353             fgRemoveReturnBlock(block);
10354         }
10355     }
10356     else // block is empty
10357     {
10358         noway_assert(block->isEmpty());
10359
10360         /* The block cannot follow a non-retless BBJ_CALLFINALLY (because we don't know who may jump to it) */
10361         noway_assert((bPrev == nullptr) || !bPrev->isBBCallAlwaysPair());
10362
10363         /* This cannot be the last basic block */
10364         noway_assert(block != fgLastBB);
10365
10366 #ifdef DEBUG
10367         if (verbose)
10368         {
10369             printf("Removing empty BB%02u\n", block->bbNum);
10370         }
10371 #endif // DEBUG
10372
10373 #ifdef DEBUG
10374         /* Some extra checks for the empty case */
10375
10376         switch (block->bbJumpKind)
10377         {
10378             case BBJ_NONE:
10379                 break;
10380
10381             case BBJ_ALWAYS:
10382                 /* Do not remove a block that jumps to itself - used for while (true){} */
10383                 noway_assert(block->bbJumpDest != block);
10384
10385                 /* Empty GOTO can be removed iff bPrev is BBJ_NONE */
10386                 noway_assert(bPrev && bPrev->bbJumpKind == BBJ_NONE);
10387                 break;
10388
10389             default:
10390                 noway_assert(!"Empty block of this type cannot be removed!");
10391                 break;
10392         }
10393 #endif // DEBUG
10394
10395         noway_assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS);
10396
10397         /* Who is the "real" successor of this block? */
10398
10399         BasicBlock* succBlock;
10400
10401         if (block->bbJumpKind == BBJ_ALWAYS)
10402         {
10403             succBlock = block->bbJumpDest;
10404         }
10405         else
10406         {
10407             succBlock = block->bbNext;
10408         }
10409
10410         bool skipUnmarkLoop = false;
10411
10412         // If block is the backedge for a loop and succBlock precedes block
10413         // then the succBlock becomes the new LOOP HEAD
10414         // NOTE: there's an assumption here that the blocks are numbered in increasing bbNext order.
10415         // NOTE 2: if fgDomsComputed is false, then we can't check reachability. However, if this is
10416         // the case, then the loop structures probably are also invalid, and shouldn't be used. This
10417         // can be the case late in compilation (such as Lower), where remnants of earlier created
10418         // structures exist, but haven't been maintained.
10419         if (block->isLoopHead() && (succBlock->bbNum <= block->bbNum))
10420         {
10421             succBlock->bbFlags |= BBF_LOOP_HEAD;
10422             if (fgDomsComputed && fgReachable(succBlock, block))
10423             {
10424                 /* Mark all the reachable blocks between 'succBlock' and 'block', excluding 'block' */
10425                 optMarkLoopBlocks(succBlock, block, true);
10426             }
10427         }
10428         else if (succBlock->isLoopHead() && bPrev && (succBlock->bbNum <= bPrev->bbNum))
10429         {
10430             skipUnmarkLoop = true;
10431         }
10432
10433         noway_assert(succBlock);
10434
10435         // If this is the first Cold basic block update fgFirstColdBlock
10436         if (block == fgFirstColdBlock)
10437         {
10438             fgFirstColdBlock = block->bbNext;
10439         }
10440
10441 #if FEATURE_EH_FUNCLETS
10442         // Update fgFirstFuncletBB if necessary
10443         if (block == fgFirstFuncletBB)
10444         {
10445             fgFirstFuncletBB = block->bbNext;
10446         }
10447 #endif // FEATURE_EH_FUNCLETS
10448
10449         /* First update the loop table and bbWeights */
10450         optUpdateLoopsBeforeRemoveBlock(block, skipUnmarkLoop);
10451
10452         /* Remove the block */
10453
10454         if (bPrev == nullptr)
10455         {
10456             /* special case if this is the first BB */
10457
10458             noway_assert(block == fgFirstBB);
10459
10460             /* Must be a fall through to next block */
10461
10462             noway_assert(block->bbJumpKind == BBJ_NONE);
10463
10464             /* old block no longer gets the extra ref count for being the first block */
10465             block->bbRefs--;
10466             succBlock->bbRefs++;
10467
10468             /* Set the new firstBB */
10469             fgUnlinkBlock(block);
10470
10471             /* Always treat the initial block as a jump target */
10472             fgFirstBB->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
10473         }
10474         else
10475         {
10476             fgUnlinkBlock(block);
10477         }
10478
10479         /* mark the block as removed and set the change flag */
10480
10481         block->bbFlags |= BBF_REMOVED;
10482
10483         /* Update bbRefs and bbPreds.
10484          * All blocks jumping to 'block' now jump to 'succBlock'.
10485          * First, remove 'block' from the predecessor list of succBlock.
10486          */
10487
10488         fgRemoveRefPred(succBlock, block);
10489
10490         for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
10491         {
10492             BasicBlock* predBlock = pred->flBlock;
10493
10494             /* Are we changing a loop backedge into a forward jump? */
10495
10496             if (block->isLoopHead() && (predBlock->bbNum >= block->bbNum) && (predBlock->bbNum <= succBlock->bbNum))
10497             {
10498                 /* First update the loop table and bbWeights */
10499                 optUpdateLoopsBeforeRemoveBlock(predBlock);
10500             }
10501
10502             /* If predBlock is a new predecessor, then add it to succBlock's
10503                predecessor's list. */
10504             if (predBlock->bbJumpKind != BBJ_SWITCH)
10505             {
10506                 // Even if the pred is not a switch, we could have a conditional branch
10507                 // to the fallthrough, so duplicate there could be preds
10508                 for (unsigned i = 0; i < pred->flDupCount; i++)
10509                 {
10510                     fgAddRefPred(succBlock, predBlock);
10511                 }
10512             }
10513
10514             /* change all jumps to the removed block */
10515             switch (predBlock->bbJumpKind)
10516             {
10517                 default:
10518                     noway_assert(!"Unexpected bbJumpKind in fgRemoveBlock()");
10519                     break;
10520
10521                 case BBJ_NONE:
10522                     noway_assert(predBlock == bPrev);
10523                     PREFIX_ASSUME(bPrev != nullptr);
10524
10525                     /* In the case of BBJ_ALWAYS we have to change the type of its predecessor */
10526                     if (block->bbJumpKind == BBJ_ALWAYS)
10527                     {
10528                         /* bPrev now becomes a BBJ_ALWAYS */
10529                         bPrev->bbJumpKind = BBJ_ALWAYS;
10530                         bPrev->bbJumpDest = succBlock;
10531                     }
10532                     break;
10533
10534                 case BBJ_COND:
10535                     /* The links for the direct predecessor case have already been updated above */
10536                     if (predBlock->bbJumpDest != block)
10537                     {
10538                         succBlock->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
10539                         break;
10540                     }
10541
10542                     /* Check if both side of the BBJ_COND now jump to the same block */
10543                     if (predBlock->bbNext == succBlock)
10544                     {
10545                         // Make sure we are replacing "block" with "succBlock" in predBlock->bbJumpDest.
10546                         noway_assert(predBlock->bbJumpDest == block);
10547                         predBlock->bbJumpDest = succBlock;
10548                         fgRemoveJTrue(predBlock);
10549                         break;
10550                     }
10551
10552                     /* Fall through for the jump case */
10553                     __fallthrough;
10554
10555                 case BBJ_CALLFINALLY:
10556                 case BBJ_ALWAYS:
10557                 case BBJ_EHCATCHRET:
10558                     noway_assert(predBlock->bbJumpDest == block);
10559                     predBlock->bbJumpDest = succBlock;
10560                     succBlock->bbFlags |= BBF_HAS_LABEL | BBF_JMP_TARGET;
10561                     break;
10562
10563                 case BBJ_SWITCH:
10564                     // Change any jumps from 'predBlock' (a BBJ_SWITCH) to 'block' to jump to 'succBlock'
10565                     //
10566                     // For the jump targets of 'predBlock' (a BBJ_SWITCH) that jump to 'block'
10567                     // remove the old predecessor at 'block' from 'predBlock'  and
10568                     // add the new predecessor at 'succBlock' from 'predBlock'
10569                     //
10570                     fgReplaceSwitchJumpTarget(predBlock, succBlock, block);
10571                     break;
10572             }
10573         }
10574     }
10575
10576     if (bPrev != nullptr)
10577     {
10578         switch (bPrev->bbJumpKind)
10579         {
10580             case BBJ_CALLFINALLY:
10581                 // If prev is a BBJ_CALLFINALLY it better be marked as RETLESS
10582                 noway_assert(bPrev->bbFlags & BBF_RETLESS_CALL);
10583                 break;
10584
10585             case BBJ_ALWAYS:
10586                 // Check for branch to next block. Just make sure the BBJ_ALWAYS block is not
10587                 // part of a BBJ_CALLFINALLY/BBJ_ALWAYS pair. We do this here and don't rely on fgUpdateFlowGraph
10588                 // because we can be called by ComputeDominators and it expects it to remove this jump to
10589                 // the next block. This is the safest fix. We should remove all this BBJ_CALLFINALLY/BBJ_ALWAYS
10590                 // pairing.
10591
10592                 if ((bPrev->bbJumpDest == bPrev->bbNext) &&
10593                     !fgInDifferentRegions(bPrev, bPrev->bbJumpDest)) // We don't remove a branch from Hot -> Cold
10594                 {
10595                     if ((bPrev == fgFirstBB) || !bPrev->bbPrev->isBBCallAlwaysPair())
10596                     {
10597                         // It's safe to change the jump type
10598                         bPrev->bbJumpKind = BBJ_NONE;
10599                         bPrev->bbFlags &= ~BBF_NEEDS_GCPOLL;
10600                     }
10601                 }
10602                 break;
10603
10604             case BBJ_COND:
10605                 /* Check for branch to next block */
10606                 if (bPrev->bbJumpDest == bPrev->bbNext)
10607                 {
10608                     fgRemoveJTrue(bPrev);
10609                 }
10610                 break;
10611
10612             default:
10613                 break;
10614         }
10615
10616         ehUpdateForDeletedBlock(block);
10617     }
10618 }
10619
10620 /*****************************************************************************
10621  *
10622  *  Function called to connect to block that previously had a fall through
10623  */
10624
10625 BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst)
10626 {
10627     BasicBlock* jmpBlk = nullptr;
10628
10629     /* If bSrc is non-NULL */
10630
10631     if (bSrc != nullptr)
10632     {
10633         /* If bSrc falls through to a block that is not bDst, we will insert a jump to bDst */
10634
10635         if (bSrc->bbFallsThrough() && (bSrc->bbNext != bDst))
10636         {
10637             switch (bSrc->bbJumpKind)
10638             {
10639
10640                 case BBJ_NONE:
10641                     bSrc->bbJumpKind = BBJ_ALWAYS;
10642                     bSrc->bbJumpDest = bDst;
10643                     bSrc->bbJumpDest->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
10644 #ifdef DEBUG
10645                     if (verbose)
10646                     {
10647                         printf("Block BB%02u ended with a BBJ_NONE, Changed to an unconditional jump to BB%02u\n",
10648                                bSrc->bbNum, bSrc->bbJumpDest->bbNum);
10649                     }
10650 #endif
10651                     break;
10652
10653                 case BBJ_CALLFINALLY:
10654                 case BBJ_COND:
10655
10656                     // Add a new block after bSrc which jumps to 'bDst'
10657                     jmpBlk = fgNewBBafter(BBJ_ALWAYS, bSrc, true);
10658
10659                     if (fgComputePredsDone)
10660                     {
10661                         fgAddRefPred(jmpBlk, bSrc, fgGetPredForBlock(bDst, bSrc));
10662                     }
10663
10664                     // When adding a new jmpBlk we will set the bbWeight and bbFlags
10665                     //
10666                     if (fgHaveValidEdgeWeights)
10667                     {
10668                         noway_assert(fgComputePredsDone);
10669
10670                         flowList* newEdge = fgGetPredForBlock(jmpBlk, bSrc);
10671
10672                         jmpBlk->bbWeight = (newEdge->flEdgeWeightMin + newEdge->flEdgeWeightMax) / 2;
10673                         if (bSrc->bbWeight == 0)
10674                         {
10675                             jmpBlk->bbWeight = 0;
10676                         }
10677
10678                         if (jmpBlk->bbWeight == 0)
10679                         {
10680                             jmpBlk->bbFlags |= BBF_RUN_RARELY;
10681                         }
10682
10683                         BasicBlock::weight_t weightDiff = (newEdge->flEdgeWeightMax - newEdge->flEdgeWeightMin);
10684                         BasicBlock::weight_t slop       = BasicBlock::GetSlopFraction(bSrc, bDst);
10685
10686                         //
10687                         // If the [min/max] values for our edge weight is within the slop factor
10688                         //  then we will set the BBF_PROF_WEIGHT flag for the block
10689                         //
10690                         if (weightDiff <= slop)
10691                         {
10692                             jmpBlk->bbFlags |= BBF_PROF_WEIGHT;
10693                         }
10694                     }
10695                     else
10696                     {
10697                         // We set the bbWeight to the smaller of bSrc->bbWeight or bDst->bbWeight
10698                         if (bSrc->bbWeight < bDst->bbWeight)
10699                         {
10700                             jmpBlk->bbWeight = bSrc->bbWeight;
10701                             jmpBlk->bbFlags |= (bSrc->bbFlags & BBF_RUN_RARELY);
10702                         }
10703                         else
10704                         {
10705                             jmpBlk->bbWeight = bDst->bbWeight;
10706                             jmpBlk->bbFlags |= (bDst->bbFlags & BBF_RUN_RARELY);
10707                         }
10708                     }
10709
10710                     jmpBlk->bbJumpDest = bDst;
10711                     jmpBlk->bbJumpDest->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
10712
10713                     if (fgComputePredsDone)
10714                     {
10715                         fgReplacePred(bDst, bSrc, jmpBlk);
10716                     }
10717                     else
10718                     {
10719                         jmpBlk->bbFlags |= BBF_IMPORTED;
10720                     }
10721
10722 #ifdef DEBUG
10723                     if (verbose)
10724                     {
10725                         printf("Added an unconditional jump to BB%02u after block BB%02u\n", jmpBlk->bbJumpDest->bbNum,
10726                                bSrc->bbNum);
10727                     }
10728 #endif // DEBUG
10729                     break;
10730
10731                 default:
10732                     noway_assert(!"Unexpected bbJumpKind");
10733                     break;
10734             }
10735         }
10736         else
10737         {
10738             // If bSrc is an unconditional branch to the next block
10739             // then change it to a BBJ_NONE block
10740             //
10741             if ((bSrc->bbJumpKind == BBJ_ALWAYS) && !(bSrc->bbFlags & BBF_KEEP_BBJ_ALWAYS) &&
10742                 (bSrc->bbJumpDest == bSrc->bbNext))
10743             {
10744                 bSrc->bbJumpKind = BBJ_NONE;
10745                 bSrc->bbFlags &= ~BBF_NEEDS_GCPOLL;
10746 #ifdef DEBUG
10747                 if (verbose)
10748                 {
10749                     printf("Changed an unconditional jump from BB%02u to the next block BB%02u into a BBJ_NONE block\n",
10750                            bSrc->bbNum, bSrc->bbNext->bbNum);
10751                 }
10752 #endif // DEBUG
10753             }
10754         }
10755     }
10756
10757     return jmpBlk;
10758 }
10759
10760 /*****************************************************************************
10761  Walk the flow graph, reassign block numbers to keep them in ascending order.
10762  Returns 'true' if any renumbering was actually done, OR if we change the
10763  maximum number of assigned basic blocks (this can happen if we do inlining,
10764  create a new, high-numbered block, then that block goes away. We go to
10765  renumber the blocks, none of them actually change number, but we shrink the
10766  maximum assigned block number. This affects the block set epoch).
10767 */
10768
10769 bool Compiler::fgRenumberBlocks()
10770 {
10771     // If we renumber the blocks the dominator information will be out-of-date
10772     if (fgDomsComputed)
10773     {
10774         noway_assert(!"Can't call Compiler::fgRenumberBlocks() when fgDomsComputed==true");
10775     }
10776
10777 #ifdef DEBUG
10778     if (verbose)
10779     {
10780         printf("\n*************** Before renumbering the basic blocks\n");
10781         fgDispBasicBlocks();
10782         fgDispHandlerTab();
10783     }
10784 #endif // DEBUG
10785
10786     bool        renumbered  = false;
10787     bool        newMaxBBNum = false;
10788     BasicBlock* block;
10789
10790     unsigned numStart = 1 + (compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : 0);
10791     unsigned num;
10792
10793     for (block = fgFirstBB, num = numStart; block != nullptr; block = block->bbNext, num++)
10794     {
10795         noway_assert((block->bbFlags & BBF_REMOVED) == 0);
10796
10797         if (block->bbNum != num)
10798         {
10799             renumbered = true;
10800 #ifdef DEBUG
10801             if (verbose)
10802             {
10803                 printf("Renumber BB%02u to BB%02u\n", block->bbNum, num);
10804             }
10805 #endif // DEBUG
10806             block->bbNum = num;
10807         }
10808
10809         if (block->bbNext == nullptr)
10810         {
10811             fgLastBB  = block;
10812             fgBBcount = num - numStart + 1;
10813             if (compIsForInlining())
10814             {
10815                 if (impInlineInfo->InlinerCompiler->fgBBNumMax != num)
10816                 {
10817                     impInlineInfo->InlinerCompiler->fgBBNumMax = num;
10818                     newMaxBBNum                                = true;
10819                 }
10820             }
10821             else
10822             {
10823                 if (fgBBNumMax != num)
10824                 {
10825                     fgBBNumMax  = num;
10826                     newMaxBBNum = true;
10827                 }
10828             }
10829         }
10830     }
10831
10832 #ifdef DEBUG
10833     if (verbose)
10834     {
10835         printf("\n*************** After renumbering the basic blocks\n");
10836         if (renumbered)
10837         {
10838             fgDispBasicBlocks();
10839             fgDispHandlerTab();
10840         }
10841         else
10842         {
10843             printf("=============== No blocks renumbered!\n");
10844         }
10845     }
10846 #endif // DEBUG
10847
10848     // Now update the BlockSet epoch, which depends on the block numbers.
10849     // If any blocks have been renumbered then create a new BlockSet epoch.
10850     // Even if we have not renumbered any blocks, we might still need to force
10851     // a new BlockSet epoch, for one of several reasons. If there are any new
10852     // blocks with higher numbers than the former maximum numbered block, then we
10853     // need a new epoch with a new size matching the new largest numbered block.
10854     // Also, if the number of blocks is different from the last time we set the
10855     // BlockSet epoch, then we need a new epoch. This wouldn't happen if we
10856     // renumbered blocks after every block addition/deletion, but it might be
10857     // the case that we can change the number of blocks, then set the BlockSet
10858     // epoch without renumbering, then change the number of blocks again, then
10859     // renumber.
10860     if (renumbered || newMaxBBNum)
10861     {
10862         NewBasicBlockEpoch();
10863
10864         // The key in the unique switch successor map is dependent on the block number, so invalidate that cache.
10865         InvalidateUniqueSwitchSuccMap();
10866     }
10867     else
10868     {
10869         EnsureBasicBlockEpoch();
10870     }
10871
10872     // Tell our caller if any blocks actually were renumbered.
10873     return renumbered || newMaxBBNum;
10874 }
10875
10876 /*****************************************************************************
10877  *
10878  *  Is the BasicBlock bJump a forward branch?
10879  *   Optionally bSrc can be supplied to indicate that
10880  *   bJump must be forward with respect to bSrc
10881  */
10882 bool Compiler::fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc /* = NULL */)
10883 {
10884     bool result = false;
10885
10886     if ((bJump->bbJumpKind == BBJ_COND) || (bJump->bbJumpKind == BBJ_ALWAYS))
10887     {
10888         BasicBlock* bDest = bJump->bbJumpDest;
10889         BasicBlock* bTemp = (bSrc == nullptr) ? bJump : bSrc;
10890
10891         while (true)
10892         {
10893             bTemp = bTemp->bbNext;
10894
10895             if (bTemp == nullptr)
10896             {
10897                 break;
10898             }
10899
10900             if (bTemp == bDest)
10901             {
10902                 result = true;
10903                 break;
10904             }
10905         }
10906     }
10907
10908     return result;
10909 }
10910
10911 /*****************************************************************************
10912  *
10913  *  Function called to expand the set of rarely run blocks
10914  */
10915
10916 bool Compiler::fgExpandRarelyRunBlocks()
10917 {
10918     bool result = false;
10919
10920 #ifdef DEBUG
10921     if (verbose)
10922     {
10923         printf("\n*************** In fgExpandRarelyRunBlocks()\n");
10924     }
10925
10926     const char* reason = nullptr;
10927 #endif
10928
10929     // We expand the number of rarely run blocks by observing
10930     // that a block that falls into or jumps to a rarely run block,
10931     // must itself be rarely run and when we have a conditional
10932     // jump in which both branches go to rarely run blocks then
10933     // the block must itself be rarely run
10934
10935     BasicBlock* block;
10936     BasicBlock* bPrev;
10937
10938     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
10939     {
10940         if (bPrev->isRunRarely())
10941         {
10942             continue;
10943         }
10944
10945         /* bPrev is known to be a normal block here */
10946         switch (bPrev->bbJumpKind)
10947         {
10948             case BBJ_ALWAYS:
10949
10950                 /* Is the jump target rarely run? */
10951                 if (bPrev->bbJumpDest->isRunRarely())
10952                 {
10953                     INDEBUG(reason = "Unconditional jump to a rarely run block";)
10954                     goto NEW_RARELY_RUN;
10955                 }
10956                 break;
10957
10958             case BBJ_CALLFINALLY:
10959
10960                 // Check for a BBJ_CALLFINALLY followed by a rarely run paired BBJ_ALWAYS
10961                 //
10962                 if (bPrev->isBBCallAlwaysPair())
10963                 {
10964                     /* Is the next block rarely run? */
10965                     if (block->isRunRarely())
10966                     {
10967                         INDEBUG(reason = "Call of finally followed by a rarely run block";)
10968                         goto NEW_RARELY_RUN;
10969                     }
10970                 }
10971                 break;
10972
10973             case BBJ_NONE:
10974
10975                 /* is fall through target rarely run? */
10976                 if (block->isRunRarely())
10977                 {
10978                     INDEBUG(reason = "Falling into a rarely run block";)
10979                     goto NEW_RARELY_RUN;
10980                 }
10981                 break;
10982
10983             case BBJ_COND:
10984
10985                 if (!block->isRunRarely())
10986                 {
10987                     continue;
10988                 }
10989
10990                 /* If both targets of the BBJ_COND are run rarely then don't reorder */
10991                 if (bPrev->bbJumpDest->isRunRarely())
10992                 {
10993                     /* bPrev should also be marked as run rarely */
10994                     if (!bPrev->isRunRarely())
10995                     {
10996                         INDEBUG(reason = "Both sides of a conditional jump are rarely run";)
10997
10998                     NEW_RARELY_RUN:
10999                         /* If the weight of the block was obtained from a profile run,
11000                            than it's more accurate than our static analysis */
11001                         if (bPrev->bbFlags & BBF_PROF_WEIGHT)
11002                         {
11003                             continue;
11004                         }
11005                         result = true;
11006
11007 #ifdef DEBUG
11008                         assert(reason != nullptr);
11009                         if (verbose)
11010                         {
11011                             printf("%s, marking BB%02u as rarely run\n", reason, bPrev->bbNum);
11012                         }
11013 #endif // DEBUG
11014
11015                         /* Must not have previously been marked */
11016                         noway_assert(!bPrev->isRunRarely());
11017
11018                         /* Mark bPrev as a new rarely run block */
11019                         bPrev->bbSetRunRarely();
11020
11021                         BasicBlock* bPrevPrev = nullptr;
11022                         BasicBlock* tmpbb;
11023
11024                         if ((bPrev->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)
11025                         {
11026                             // If we've got a BBJ_CALLFINALLY/BBJ_ALWAYS pair, treat the BBJ_CALLFINALLY as an
11027                             // additional predecessor for the BBJ_ALWAYS block
11028                             tmpbb = bPrev->bbPrev;
11029                             noway_assert(tmpbb != nullptr);
11030 #if FEATURE_EH_FUNCLETS
11031                             noway_assert(tmpbb->isBBCallAlwaysPair());
11032                             bPrevPrev = tmpbb;
11033 #else
11034                                 if (tmpbb->bbJumpKind == BBJ_CALLFINALLY)
11035                                 {
11036                                     bPrevPrev = tmpbb;
11037                                 }
11038 #endif
11039                         }
11040
11041                         /* Now go back to it's earliest predecessor to see */
11042                         /* if it too should now be marked as rarely run    */
11043                         flowList* pred = bPrev->bbPreds;
11044
11045                         if ((pred != nullptr) || (bPrevPrev != nullptr))
11046                         {
11047                             // bPrevPrev will be set to the lexically
11048                             // earliest predecessor of bPrev.
11049
11050                             while (pred != nullptr)
11051                             {
11052                                 if (bPrevPrev == nullptr)
11053                                 {
11054                                     // Initially we select the first block in the bbPreds list
11055                                     bPrevPrev = pred->flBlock;
11056                                     continue;
11057                                 }
11058
11059                                 // Walk the flow graph lexically forward from pred->flBlock
11060                                 // if we find (block == bPrevPrev) then
11061                                 // pred->flBlock is an earlier predecessor.
11062                                 for (tmpbb = pred->flBlock; tmpbb != nullptr; tmpbb = tmpbb->bbNext)
11063                                 {
11064                                     if (tmpbb == bPrevPrev)
11065                                     {
11066                                         /* We found an ealier predecessor */
11067                                         bPrevPrev = pred->flBlock;
11068                                         break;
11069                                     }
11070                                     else if (tmpbb == bPrev)
11071                                     {
11072                                         // We have reached bPrev so stop walking
11073                                         // as this cannot be an earlier predecessor
11074                                         break;
11075                                     }
11076                                 }
11077
11078                                 // Onto the next predecessor
11079                                 pred = pred->flNext;
11080                             }
11081
11082                             // Walk the flow graph forward from bPrevPrev
11083                             // if we don't find (tmpbb == bPrev) then our candidate
11084                             // bPrevPrev is lexically after bPrev and we do not
11085                             // want to select it as our new block
11086
11087                             for (tmpbb = bPrevPrev; tmpbb != nullptr; tmpbb = tmpbb->bbNext)
11088                             {
11089                                 if (tmpbb == bPrev)
11090                                 {
11091                                     // Set up block back to the lexically
11092                                     // earliest predecessor of pPrev
11093
11094                                     block = bPrevPrev;
11095                                 }
11096                             }
11097                         }
11098                     }
11099                     break;
11100
11101                     default:
11102                         break;
11103                 }
11104         }
11105     }
11106
11107     // Now iterate over every block to see if we can prove that a block is rarely run
11108     // (i.e. when all predecessors to the block are rarely run)
11109     //
11110     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
11111     {
11112         // If block is not run rarely, then check to make sure that it has
11113         // at least one non-rarely run block.
11114
11115         if (!block->isRunRarely())
11116         {
11117             bool rare = true;
11118
11119             /* Make sure that block has at least one normal predecessor */
11120             for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext)
11121             {
11122                 /* Find the fall through predecessor, if any */
11123                 if (!pred->flBlock->isRunRarely())
11124                 {
11125                     rare = false;
11126                     break;
11127                 }
11128             }
11129
11130             if (rare)
11131             {
11132                 // If 'block' is the start of a handler or filter then we cannot make it
11133                 // rarely run because we may have an exceptional edge that
11134                 // branches here.
11135                 //
11136                 if (bbIsHandlerBeg(block))
11137                 {
11138                     rare = false;
11139                 }
11140             }
11141
11142             if (rare)
11143             {
11144                 block->bbSetRunRarely();
11145                 result = true;
11146
11147 #ifdef DEBUG
11148                 if (verbose)
11149                 {
11150                     printf("All branches to BB%02u are from rarely run blocks, marking as rarely run\n", block->bbNum);
11151                 }
11152 #endif // DEBUG
11153
11154                 // When marking a BBJ_CALLFINALLY as rarely run we also mark
11155                 // the BBJ_ALWAYS that comes after it as rarely run
11156                 //
11157                 if (block->isBBCallAlwaysPair())
11158                 {
11159                     BasicBlock* bNext = block->bbNext;
11160                     PREFIX_ASSUME(bNext != nullptr);
11161                     bNext->bbSetRunRarely();
11162 #ifdef DEBUG
11163                     if (verbose)
11164                     {
11165                         printf("Also marking the BBJ_ALWAYS at BB%02u as rarely run\n", bNext->bbNum);
11166                     }
11167 #endif // DEBUG
11168                 }
11169             }
11170         }
11171
11172         /* COMPACT blocks if possible */
11173         if (bPrev->bbJumpKind == BBJ_NONE)
11174         {
11175             if (fgCanCompactBlocks(bPrev, block))
11176             {
11177                 fgCompactBlocks(bPrev, block);
11178
11179                 block = bPrev;
11180                 continue;
11181             }
11182         }
11183         //
11184         // if bPrev->bbWeight is not based upon profile data we can adjust
11185         // the weights of bPrev and block
11186         //
11187         else if (bPrev->isBBCallAlwaysPair() &&             // we must have a BBJ_CALLFINALLY and BBK_ALWAYS pair
11188                  (bPrev->bbWeight != block->bbWeight) &&    // the weights are currently different
11189                  ((bPrev->bbFlags & BBF_PROF_WEIGHT) == 0)) // and the BBJ_CALLFINALLY block is not using profiled
11190                                                             // weights
11191         {
11192             if (block->isRunRarely())
11193             {
11194                 bPrev->bbWeight =
11195                     block->bbWeight; // the BBJ_CALLFINALLY block now has the same weight as the BBJ_ALWAYS block
11196                 bPrev->bbFlags |= BBF_RUN_RARELY; // and is now rarely run
11197 #ifdef DEBUG
11198                 if (verbose)
11199                 {
11200                     printf("Marking the BBJ_CALLFINALLY block at BB%02u as rarely run because BB%02u is rarely run\n",
11201                            bPrev->bbNum, block->bbNum);
11202                 }
11203 #endif // DEBUG
11204             }
11205             else if (bPrev->isRunRarely())
11206             {
11207                 block->bbWeight =
11208                     bPrev->bbWeight; // the BBJ_ALWAYS block now has the same weight as the BBJ_CALLFINALLY block
11209                 block->bbFlags |= BBF_RUN_RARELY; // and is now rarely run
11210 #ifdef DEBUG
11211                 if (verbose)
11212                 {
11213                     printf("Marking the BBJ_ALWAYS block at BB%02u as rarely run because BB%02u is rarely run\n",
11214                            block->bbNum, bPrev->bbNum);
11215                 }
11216 #endif // DEBUG
11217             }
11218             else // Both blocks are hot, bPrev is known not to be using profiled weight
11219             {
11220                 bPrev->bbWeight =
11221                     block->bbWeight; // the BBJ_CALLFINALLY block now has the same weight as the BBJ_ALWAYS block
11222             }
11223             noway_assert(block->bbWeight == bPrev->bbWeight);
11224         }
11225     }
11226
11227     return result;
11228 }
11229
11230 /*****************************************************************************
11231  *
11232  *  Returns true if it is allowable (based upon the EH regions)
11233  *  to place block bAfter immediately after bBefore. It is allowable
11234  *  if the 'bBefore' and 'bAfter' blocks are in the exact same EH region.
11235  */
11236
11237 bool Compiler::fgEhAllowsMoveBlock(BasicBlock* bBefore, BasicBlock* bAfter)
11238 {
11239     return BasicBlock::sameEHRegion(bBefore, bAfter);
11240 }
11241
11242 /*****************************************************************************
11243  *
11244  *  Function called to move the range of blocks [bStart .. bEnd].
11245  *  The blocks are placed immediately after the insertAfterBlk.
11246  *  fgFirstFuncletBB is not updated; that is the responsibility of the caller, if necessary.
11247  */
11248
11249 void Compiler::fgMoveBlocksAfter(BasicBlock* bStart, BasicBlock* bEnd, BasicBlock* insertAfterBlk)
11250 {
11251     /* We have decided to insert the block(s) after 'insertAfterBlk' */
11252     CLANG_FORMAT_COMMENT_ANCHOR;
11253
11254 #ifdef DEBUG
11255     if (verbose)
11256     {
11257         printf("Relocated block%s [BB%02u..BB%02u] inserted after BB%02u%s\n", (bStart == bEnd) ? "" : "s",
11258                bStart->bbNum, bEnd->bbNum, insertAfterBlk->bbNum,
11259                (insertAfterBlk->bbNext == nullptr) ? " at the end of method" : "");
11260     }
11261 #endif // DEBUG
11262
11263     /* relink [bStart .. bEnd] into the flow graph */
11264
11265     bEnd->bbNext = insertAfterBlk->bbNext;
11266     if (insertAfterBlk->bbNext)
11267     {
11268         insertAfterBlk->bbNext->bbPrev = bEnd;
11269     }
11270     insertAfterBlk->setNext(bStart);
11271
11272     /* If insertAfterBlk was fgLastBB then update fgLastBB */
11273     if (insertAfterBlk == fgLastBB)
11274     {
11275         fgLastBB = bEnd;
11276         noway_assert(fgLastBB->bbNext == nullptr);
11277     }
11278 }
11279
11280 /*****************************************************************************
11281  *
11282  *  Function called to relocate a single range to the end of the method.
11283  *  Only an entire consecutive region can be moved and it will be kept together.
11284  *  Except for the first block, the range cannot have any blocks that jump into or out of the region.
11285  *  When successful we return the bLast block which is the last block that we relocated.
11286  *  When unsuccessful we return NULL.
11287
11288     =============================================================
11289     NOTE: This function can invalidate all pointers into the EH table, as well as change the size of the EH table!
11290     =============================================================
11291  */
11292
11293 BasicBlock* Compiler::fgRelocateEHRange(unsigned regionIndex, FG_RELOCATE_TYPE relocateType)
11294 {
11295     INDEBUG(const char* reason = "None";)
11296
11297     // Figure out the range of blocks we're going to move
11298
11299     unsigned    XTnum;
11300     EHblkDsc*   HBtab;
11301     BasicBlock* bStart  = nullptr;
11302     BasicBlock* bMiddle = nullptr;
11303     BasicBlock* bLast   = nullptr;
11304     BasicBlock* bPrev   = nullptr;
11305
11306 #if FEATURE_EH_FUNCLETS
11307     // We don't support moving try regions... yet?
11308     noway_assert(relocateType == FG_RELOCATE_HANDLER);
11309 #endif // FEATURE_EH_FUNCLETS
11310
11311     HBtab = ehGetDsc(regionIndex);
11312
11313     if (relocateType == FG_RELOCATE_TRY)
11314     {
11315         bStart = HBtab->ebdTryBeg;
11316         bLast  = HBtab->ebdTryLast;
11317     }
11318     else if (relocateType == FG_RELOCATE_HANDLER)
11319     {
11320         if (HBtab->HasFilter())
11321         {
11322             // The filter and handler funclets must be moved together, and remain contiguous.
11323             bStart  = HBtab->ebdFilter;
11324             bMiddle = HBtab->ebdHndBeg;
11325             bLast   = HBtab->ebdHndLast;
11326         }
11327         else
11328         {
11329             bStart = HBtab->ebdHndBeg;
11330             bLast  = HBtab->ebdHndLast;
11331         }
11332     }
11333
11334     // Our range must contain either all rarely run blocks or all non-rarely run blocks
11335     bool inTheRange = false;
11336     bool validRange = false;
11337
11338     BasicBlock* block;
11339
11340     noway_assert(bStart != nullptr && bLast != nullptr);
11341     if (bStart == fgFirstBB)
11342     {
11343         INDEBUG(reason = "can not relocate first block";)
11344         goto FAILURE;
11345     }
11346
11347 #if !FEATURE_EH_FUNCLETS
11348     // In the funclets case, we still need to set some information on the handler blocks
11349     if (bLast->bbNext == NULL)
11350     {
11351         INDEBUG(reason = "region is already at the end of the method";)
11352         goto FAILURE;
11353     }
11354 #endif // !FEATURE_EH_FUNCLETS
11355
11356     // Walk the block list for this purpose:
11357     // 1. Verify that all the blocks in the range are either all rarely run or not rarely run.
11358     // When creating funclets, we ignore the run rarely flag, as we need to be able to move any blocks
11359     // in the range.
11360     CLANG_FORMAT_COMMENT_ANCHOR;
11361
11362 #if !FEATURE_EH_FUNCLETS
11363     bool isRare;
11364     isRare = bStart->isRunRarely();
11365 #endif // !FEATURE_EH_FUNCLETS
11366     block = fgFirstBB;
11367     while (true)
11368     {
11369         if (block == bStart)
11370         {
11371             noway_assert(inTheRange == false);
11372             inTheRange = true;
11373         }
11374         else if (block == bLast->bbNext)
11375         {
11376             noway_assert(inTheRange == true);
11377             inTheRange = false;
11378             break; // we found the end, so we're done
11379         }
11380
11381         if (inTheRange)
11382         {
11383 #if !FEATURE_EH_FUNCLETS
11384             // Unless all blocks are (not) run rarely we must return false.
11385             if (isRare != block->isRunRarely())
11386             {
11387                 INDEBUG(reason = "this region contains both rarely run and non-rarely run blocks";)
11388                 goto FAILURE;
11389             }
11390 #endif // !FEATURE_EH_FUNCLETS
11391
11392             validRange = true;
11393         }
11394
11395         if (block == nullptr)
11396         {
11397             break;
11398         }
11399
11400         block = block->bbNext;
11401     }
11402     // Ensure that bStart .. bLast defined a valid range
11403     noway_assert((validRange == true) && (inTheRange == false));
11404
11405     bPrev = bStart->bbPrev;
11406     noway_assert(bPrev != nullptr); // Can't move a range that includes the first block of the function.
11407
11408     JITDUMP("Relocating %s range BB%02u..BB%02u (EH#%u) to end of BBlist\n",
11409             (relocateType == FG_RELOCATE_TRY) ? "try" : "handler", bStart->bbNum, bLast->bbNum, regionIndex);
11410
11411 #ifdef DEBUG
11412     if (verbose)
11413     {
11414         fgDispBasicBlocks();
11415         fgDispHandlerTab();
11416     }
11417
11418     if (!FEATURE_EH_FUNCLETS)
11419     {
11420         // This is really expensive, and quickly becomes O(n^n) with funclets
11421         // so only do it once after we've created them (see fgCreateFunclets)
11422         if (expensiveDebugCheckLevel >= 2)
11423         {
11424             fgDebugCheckBBlist();
11425         }
11426     }
11427 #endif // DEBUG
11428
11429 #if FEATURE_EH_FUNCLETS
11430
11431     bStart->bbFlags |= BBF_FUNCLET_BEG; // Mark the start block of the funclet
11432
11433     if (bMiddle != nullptr)
11434     {
11435         bMiddle->bbFlags |= BBF_FUNCLET_BEG; // Also mark the start block of a filter handler as a funclet
11436     }
11437
11438 #endif // FEATURE_EH_FUNCLETS
11439
11440     BasicBlock* bNext;
11441     bNext = bLast->bbNext;
11442
11443     /* Temporarily unlink [bStart .. bLast] from the flow graph */
11444     fgUnlinkRange(bStart, bLast);
11445
11446     BasicBlock* insertAfterBlk;
11447     insertAfterBlk = fgLastBB;
11448
11449 #if FEATURE_EH_FUNCLETS
11450
11451     // There are several cases we need to consider when moving an EH range.
11452     // If moving a range X, we must consider its relationship to every other EH
11453     // range A in the table. Note that each entry in the table represents both
11454     // a protected region and a handler region (possibly including a filter region
11455     // that must live before and adjacent to the handler region), so we must
11456     // consider try and handler regions independently. These are the cases:
11457     // 1. A is completely contained within X (where "completely contained" means
11458     //    that the 'begin' and 'last' parts of A are strictly between the 'begin'
11459     //    and 'end' parts of X, and aren't equal to either, for example, they don't
11460     //    share 'last' blocks). In this case, when we move X, A moves with it, and
11461     //    the EH table doesn't need to change.
11462     // 2. X is completely contained within A. In this case, X gets extracted from A,
11463     //    and the range of A shrinks, but because A is strictly within X, the EH
11464     //    table doesn't need to change.
11465     // 3. A and X have exactly the same range. In this case, A is moving with X and
11466     //    the EH table doesn't need to change.
11467     // 4. A and X share the 'last' block. There are two sub-cases:
11468     //    (a) A is a larger range than X (such that the beginning of A precedes the
11469     //        beginning of X): in this case, we are moving the tail of A. We set the
11470     //        'last' block of A to the the block preceding the beginning block of X.
11471     //    (b) A is a smaller range than X. Thus, we are moving the entirety of A along
11472     //        with X. In this case, nothing in the EH record for A needs to change.
11473     // 5. A and X share the 'beginning' block (but aren't the same range, as in #3).
11474     //    This can never happen here, because we are only moving handler ranges (we don't
11475     //    move try ranges), and handler regions cannot start at the beginning of a try
11476     //    range or handler range and be a subset.
11477     //
11478     // Note that A and X must properly nest for the table to be well-formed. For example,
11479     // the beginning of A can't be strictly within the range of X (that is, the beginning
11480     // of A isn't shared with the beginning of X) and the end of A outside the range.
11481
11482     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
11483     {
11484         if (XTnum != regionIndex) // we don't need to update our 'last' pointer
11485         {
11486             if (HBtab->ebdTryLast == bLast)
11487             {
11488                 // If we moved a set of blocks that were at the end of
11489                 // a different try region then we may need to update ebdTryLast
11490                 for (block = HBtab->ebdTryBeg; block != nullptr; block = block->bbNext)
11491                 {
11492                     if (block == bPrev)
11493                     {
11494                         // We were contained within it, so shrink its region by
11495                         // setting its 'last'
11496                         fgSetTryEnd(HBtab, bPrev);
11497                         break;
11498                     }
11499                     else if (block == HBtab->ebdTryLast->bbNext)
11500                     {
11501                         // bPrev does not come after the TryBeg, thus we are larger, and
11502                         // it is moving with us.
11503                         break;
11504                     }
11505                 }
11506             }
11507             if (HBtab->ebdHndLast == bLast)
11508             {
11509                 // If we moved a set of blocks that were at the end of
11510                 // a different handler region then we must update ebdHndLast
11511                 for (block = HBtab->ebdHndBeg; block != nullptr; block = block->bbNext)
11512                 {
11513                     if (block == bPrev)
11514                     {
11515                         fgSetHndEnd(HBtab, bPrev);
11516                         break;
11517                     }
11518                     else if (block == HBtab->ebdHndLast->bbNext)
11519                     {
11520                         // bPrev does not come after the HndBeg
11521                         break;
11522                     }
11523                 }
11524             }
11525         }
11526     } // end exception table iteration
11527
11528     // Insert the block(s) we are moving after fgLastBlock
11529     fgMoveBlocksAfter(bStart, bLast, insertAfterBlk);
11530
11531     if (fgFirstFuncletBB == nullptr) // The funclet region isn't set yet
11532     {
11533         fgFirstFuncletBB = bStart;
11534     }
11535     else
11536     {
11537         assert(fgFirstFuncletBB !=
11538                insertAfterBlk->bbNext); // We insert at the end, not at the beginning, of the funclet region.
11539     }
11540
11541     // These asserts assume we aren't moving try regions (which we might need to do). Only
11542     // try regions can have fall through into or out of the region.
11543
11544     noway_assert(!bPrev->bbFallsThrough()); // There can be no fall through into a filter or handler region
11545     noway_assert(!bLast->bbFallsThrough()); // There can be no fall through out of a handler region
11546
11547 #ifdef DEBUG
11548     if (verbose)
11549     {
11550         printf("Create funclets: moved region\n");
11551         fgDispHandlerTab();
11552     }
11553
11554     // We have to wait to do this until we've created all the additional regions
11555     // Because this relies on ebdEnclosingTryIndex and ebdEnclosingHndIndex
11556     if (!FEATURE_EH_FUNCLETS)
11557     {
11558         // This is really expensive, and quickly becomes O(n^n) with funclets
11559         // so only do it once after we've created them (see fgCreateFunclets)
11560         if (expensiveDebugCheckLevel >= 2)
11561         {
11562             fgDebugCheckBBlist();
11563         }
11564     }
11565 #endif // DEBUG
11566
11567 #else // FEATURE_EH_FUNCLETS
11568
11569         for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
11570         {
11571             if (XTnum == regionIndex)
11572             {
11573                 // Don't update our handler's Last info
11574                 continue;
11575             }
11576
11577             if (HBtab->ebdTryLast == bLast)
11578             {
11579                 // If we moved a set of blocks that were at the end of
11580                 // a different try region then we may need to update ebdTryLast
11581                 for (block = HBtab->ebdTryBeg; block != NULL; block = block->bbNext)
11582                 {
11583                     if (block == bPrev)
11584                     {
11585                         fgSetTryEnd(HBtab, bPrev);
11586                         break;
11587                     }
11588                     else if (block == HBtab->ebdTryLast->bbNext)
11589                     {
11590                         // bPrev does not come after the TryBeg
11591                         break;
11592                     }
11593                 }
11594             }
11595             if (HBtab->ebdHndLast == bLast)
11596             {
11597                 // If we moved a set of blocks that were at the end of
11598                 // a different handler region then we must update ebdHndLast
11599                 for (block = HBtab->ebdHndBeg; block != NULL; block = block->bbNext)
11600                 {
11601                     if (block == bPrev)
11602                     {
11603                         fgSetHndEnd(HBtab, bPrev);
11604                         break;
11605                     }
11606                     else if (block == HBtab->ebdHndLast->bbNext)
11607                     {
11608                         // bPrev does not come after the HndBeg
11609                         break;
11610                     }
11611                 }
11612             }
11613         } // end exception table iteration
11614
11615         // We have decided to insert the block(s) after fgLastBlock
11616         fgMoveBlocksAfter(bStart, bLast, insertAfterBlk);
11617
11618         // If bPrev falls through, we will insert a jump to block
11619         fgConnectFallThrough(bPrev, bStart);
11620
11621         // If bLast falls through, we will insert a jump to bNext
11622         fgConnectFallThrough(bLast, bNext);
11623
11624 #endif // FEATURE_EH_FUNCLETS
11625
11626     goto DONE;
11627
11628 FAILURE:
11629
11630 #ifdef DEBUG
11631     if (verbose)
11632     {
11633         printf("*************** Failed fgRelocateEHRange(BB%02u..BB%02u) because %s\n", bStart->bbNum, bLast->bbNum,
11634                reason);
11635     }
11636 #endif // DEBUG
11637
11638     bLast = nullptr;
11639
11640 DONE:
11641
11642     return bLast;
11643 }
11644
11645 #if FEATURE_EH_FUNCLETS
11646
11647 #if defined(_TARGET_ARM_)
11648
11649 /*****************************************************************************
11650  * We just removed a BBJ_CALLFINALLY/BBJ_ALWAYS pair. If this was the only such pair
11651  * targeting the BBJ_ALWAYS target, then we need to clear the BBF_FINALLY_TARGET bit
11652  * so that target can also be removed. 'block' is the finally target. Since we just
11653  * removed the BBJ_ALWAYS, it better have the BBF_FINALLY_TARGET bit set.
11654  */
11655
11656 void Compiler::fgClearFinallyTargetBit(BasicBlock* block)
11657 {
11658     assert((block->bbFlags & BBF_FINALLY_TARGET) != 0);
11659
11660     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
11661     {
11662         if (pred->flBlock->bbJumpKind == BBJ_ALWAYS && pred->flBlock->bbJumpDest == block)
11663         {
11664             BasicBlock* pPrev = pred->flBlock->bbPrev;
11665             if (pPrev != NULL)
11666             {
11667                 if (pPrev->bbJumpKind == BBJ_CALLFINALLY)
11668                 {
11669                     // We found a BBJ_CALLFINALLY / BBJ_ALWAYS that still points to this finally target
11670                     return;
11671                 }
11672             }
11673         }
11674     }
11675
11676     // Didn't find any BBJ_CALLFINALLY / BBJ_ALWAYS that still points here, so clear the bit
11677
11678     block->bbFlags &= ~BBF_FINALLY_TARGET;
11679 }
11680
11681 #endif // defined(_TARGET_ARM_)
11682
11683 /*****************************************************************************
11684  * Is this an intra-handler control flow edge?
11685  *
11686  * 'block' is the head block of a funclet/handler region, or .
11687  * 'predBlock' is a predecessor block of 'block' in the predecessor list.
11688  *
11689  * 'predBlock' can legally only be one of three things:
11690  * 1. in the same handler region (e.g., the source of a back-edge of a loop from
11691  *    'predBlock' to 'block'), including in nested regions within the handler,
11692  * 2. if 'block' begins a handler that is a filter-handler, 'predBlock' must be in the 'filter' region,
11693  * 3. for other handlers, 'predBlock' must be in the 'try' region corresponding to handler (or any
11694  *    region nested in the 'try' region).
11695  *
11696  * Note that on AMD64/ARM64, the BBJ_CALLFINALLY block that calls a finally handler is not
11697  * within the corresponding 'try' region: it is placed in the corresponding 'try' region's
11698  * parent (which might be the main function body). This is how it is represented to the VM
11699  * (with a special "cloned finally" EH table entry).
11700  *
11701  * Return 'true' for case #1, and 'false' otherwise.
11702  */
11703 bool Compiler::fgIsIntraHandlerPred(BasicBlock* predBlock, BasicBlock* block)
11704 {
11705     // Some simple preconditions (as stated above)
11706     assert(!fgFuncletsCreated);
11707     assert(fgGetPredForBlock(block, predBlock) != nullptr);
11708     assert(block->hasHndIndex());
11709
11710     EHblkDsc* xtab = ehGetDsc(block->getHndIndex());
11711
11712 #if FEATURE_EH_CALLFINALLY_THUNKS
11713     if (xtab->HasFinallyHandler())
11714     {
11715         assert((xtab->ebdHndBeg == block) || // The normal case
11716                ((xtab->ebdHndBeg->bbNext == block) &&
11717                 (xtab->ebdHndBeg->bbFlags & BBF_INTERNAL))); // After we've already inserted a header block, and we're
11718                                                              // trying to decide how to split up the predecessor edges.
11719         if (predBlock->bbJumpKind == BBJ_CALLFINALLY)
11720         {
11721             assert(predBlock->bbJumpDest == block);
11722
11723             // A BBJ_CALLFINALLY predecessor of the handler can only come from the corresponding try,
11724             // not from any EH clauses nested in this handler. However, we represent the BBJ_CALLFINALLY
11725             // as being in the 'try' region's parent EH region, which might be the main function body.
11726
11727             unsigned tryIndex = xtab->ebdEnclosingTryIndex;
11728             if (tryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
11729             {
11730                 assert(!predBlock->hasTryIndex());
11731             }
11732             else
11733             {
11734                 assert(predBlock->hasTryIndex());
11735                 assert(tryIndex == predBlock->getTryIndex());
11736                 assert(ehGetDsc(tryIndex)->InTryRegionBBRange(predBlock));
11737             }
11738             return false;
11739         }
11740     }
11741 #endif // FEATURE_EH_CALLFINALLY_THUNKS
11742
11743     assert(predBlock->hasHndIndex() || predBlock->hasTryIndex());
11744
11745     //   We could search the try region looking for predBlock by using bbInTryRegions
11746     // but that does a lexical search for the block, and then assumes funclets
11747     // have been created and does a lexical search of all funclets that were pulled
11748     // out of the parent try region.
11749     //   First, funclets haven't been created yet, and even if they had been, we shouldn't
11750     // have any funclet directly branching to another funclet (they have to return first).
11751     // So we can safely use CheckIsTryRegion instead of bbInTryRegions.
11752     //   Second, I believe the depth of any EH graph will on average be smaller than the
11753     // breadth of the blocks within a try body. Thus it is faster to get our answer by
11754     // looping outward over the region graph. However, I have added asserts, as a
11755     // precaution, to ensure both algorithms agree. The asserts also check that the only
11756     // way to reach the head of a funclet is from the corresponding try body or from
11757     // within the funclet (and *not* any nested funclets).
11758
11759     if (predBlock->hasTryIndex())
11760     {
11761         // Because the EH clauses are listed inside-out, any nested trys will be at a
11762         // lower index than the current try and if there's no enclosing try, tryIndex
11763         // will terminate at NO_ENCLOSING_INDEX
11764
11765         unsigned tryIndex = predBlock->getTryIndex();
11766         while (tryIndex < block->getHndIndex())
11767         {
11768             tryIndex = ehGetEnclosingTryIndex(tryIndex);
11769         }
11770         // tryIndex should enclose predBlock
11771         assert((tryIndex == EHblkDsc::NO_ENCLOSING_INDEX) || ehGetDsc(tryIndex)->InTryRegionBBRange(predBlock));
11772
11773         // At this point tryIndex is either block's handler's corresponding try body
11774         // or some outer try region that contains both predBlock & block or
11775         // NO_ENCLOSING_REGION (because there was no try body that encloses both).
11776         if (tryIndex == block->getHndIndex())
11777         {
11778             assert(xtab->InTryRegionBBRange(predBlock));
11779             assert(!xtab->InHndRegionBBRange(predBlock));
11780             return false;
11781         }
11782         // tryIndex should enclose block (and predBlock as previously asserted)
11783         assert((tryIndex == EHblkDsc::NO_ENCLOSING_INDEX) || ehGetDsc(tryIndex)->InTryRegionBBRange(block));
11784     }
11785     if (xtab->HasFilter())
11786     {
11787         // The block is a handler. Check if the pred block is from its filter. We only need to
11788         // check the end filter flag, as there is only a single filter for any handler, and we
11789         // already know predBlock is a predecessor of block.
11790         if (predBlock->bbJumpKind == BBJ_EHFILTERRET)
11791         {
11792             assert(!xtab->InHndRegionBBRange(predBlock));
11793             return false;
11794         }
11795     }
11796     // It is not in our try region (or filter), so it must be within this handler (or try bodies
11797     // within this handler)
11798     assert(!xtab->InTryRegionBBRange(predBlock));
11799     assert(xtab->InHndRegionBBRange(predBlock));
11800     return true;
11801 }
11802
11803 /*****************************************************************************
11804  * Does this block, first block of a handler region, have any predecessor edges
11805  * that are not from its corresponding try region?
11806  */
11807
11808 bool Compiler::fgAnyIntraHandlerPreds(BasicBlock* block)
11809 {
11810     assert(block->hasHndIndex());
11811     assert(fgFirstBlockOfHandler(block) == block); // this block is the first block of a handler
11812
11813     flowList* pred;
11814
11815     for (pred = block->bbPreds; pred; pred = pred->flNext)
11816     {
11817         BasicBlock* predBlock = pred->flBlock;
11818
11819         if (fgIsIntraHandlerPred(predBlock, block))
11820         {
11821             // We have a predecessor that is not from our try region
11822             return true;
11823         }
11824     }
11825
11826     return false;
11827 }
11828
11829 /*****************************************************************************
11830  * Introduce a new head block of the handler for the prolog to be put in, ahead
11831  * of the current handler head 'block'.
11832  * Note that this code has some similarities to fgCreateLoopPreHeader().
11833  */
11834
11835 void Compiler::fgInsertFuncletPrologBlock(BasicBlock* block)
11836 {
11837 #ifdef DEBUG
11838     if (verbose)
11839     {
11840         printf("\nCreating funclet prolog header for BB%02u\n", block->bbNum);
11841     }
11842 #endif
11843
11844     assert(block->hasHndIndex());
11845     assert(fgFirstBlockOfHandler(block) == block); // this block is the first block of a handler
11846
11847     /* Allocate a new basic block */
11848
11849     BasicBlock* newHead = bbNewBasicBlock(BBJ_NONE);
11850
11851     // In fgComputePreds() we set the BBF_JMP_TARGET and BBF_HAS_LABEL for all of the handler entry points
11852     //
11853     newHead->bbFlags |= (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL);
11854     newHead->inheritWeight(block);
11855     newHead->bbRefs = 0;
11856
11857     fgInsertBBbefore(block, newHead); // insert the new block in the block list
11858     fgExtendEHRegionBefore(block);    // Update the EH table to make the prolog block the first block in the block's EH
11859                                       // block.
11860
11861     // fgExtendEHRegionBefore mucks with the bbRefs without updating the pred list, which we will
11862     // do below for this block. So, undo that change.
11863     assert(newHead->bbRefs > 0);
11864     newHead->bbRefs--;
11865     block->bbRefs++;
11866
11867     // Distribute the pred list between newHead and block. Incoming edges coming from outside
11868     // the handler go to the prolog. Edges coming from with the handler are back-edges, and
11869     // go to the existing 'block'.
11870
11871     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
11872     {
11873         BasicBlock* predBlock = pred->flBlock;
11874         if (!fgIsIntraHandlerPred(predBlock, block))
11875         {
11876             // It's a jump from outside the handler; add it to the newHead preds list and remove
11877             // it from the block preds list.
11878
11879             switch (predBlock->bbJumpKind)
11880             {
11881                 case BBJ_CALLFINALLY:
11882                     noway_assert(predBlock->bbJumpDest == block);
11883                     predBlock->bbJumpDest = newHead;
11884                     fgRemoveRefPred(block, predBlock);
11885                     fgAddRefPred(newHead, predBlock);
11886                     break;
11887
11888                 default:
11889                     // The only way into the handler is via a BBJ_CALLFINALLY (to a finally handler), or
11890                     // via exception handling.
11891                     noway_assert(false);
11892                     break;
11893             }
11894         }
11895     }
11896
11897     assert(nullptr == fgGetPredForBlock(block, newHead));
11898     fgAddRefPred(block, newHead);
11899
11900     assert((newHead->bbFlags & (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL)) ==
11901            (BBF_INTERNAL | BBF_JMP_TARGET | BBF_HAS_LABEL));
11902 }
11903
11904 /*****************************************************************************
11905  *
11906  * Every funclet will have a prolog. That prolog will be inserted as the first instructions
11907  * in the first block of the funclet. If the prolog is also the head block of a loop, we
11908  * would end up with the prolog instructions being executed more than once.
11909  * Check for this by searching the predecessor list for loops, and create a new prolog header
11910  * block when needed. We detect a loop by looking for any predecessor that isn't in the
11911  * handler's try region, since the only way to get into a handler is via that try region.
11912  */
11913
11914 void Compiler::fgCreateFuncletPrologBlocks()
11915 {
11916     noway_assert(fgComputePredsDone);
11917     noway_assert(!fgDomsComputed); // this function doesn't maintain the dom sets
11918     assert(!fgFuncletsCreated);
11919
11920     bool      prologBlocksCreated = false;
11921     EHblkDsc* HBtabEnd;
11922     EHblkDsc* HBtab;
11923
11924     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
11925     {
11926         BasicBlock* head = HBtab->ebdHndBeg;
11927
11928         if (fgAnyIntraHandlerPreds(head))
11929         {
11930             // We need to create a new block in which to place the prolog, and split the existing
11931             // head block predecessor edges into those that should point to the prolog, and those
11932             // that shouldn't.
11933             //
11934             // It's arguable that we should just always do this, and not only when we "need to",
11935             // so there aren't two different code paths. However, it's unlikely to be necessary
11936             // for catch handlers because they have an incoming argument (the exception object)
11937             // that needs to get stored or saved, so back-arcs won't normally go to the head. It's
11938             // possible when writing in IL to generate a legal loop (e.g., push an Exception object
11939             // on the stack before jumping back to the catch head), but C# probably won't. This will
11940             // most commonly only be needed for finallys with a do/while loop at the top of the
11941             // finally.
11942             //
11943             // Note that we don't check filters. This might be a bug, but filters always have a filter
11944             // object live on entry, so it's at least unlikely (illegal?) that a loop edge targets the
11945             // filter head.
11946
11947             fgInsertFuncletPrologBlock(head);
11948             prologBlocksCreated = true;
11949         }
11950     }
11951
11952     if (prologBlocksCreated)
11953     {
11954         // If we've modified the graph, reset the 'modified' flag, since the dominators haven't
11955         // been computed.
11956         fgModified = false;
11957
11958 #if DEBUG
11959         if (verbose)
11960         {
11961             JITDUMP("\nAfter fgCreateFuncletPrologBlocks()");
11962             fgDispBasicBlocks();
11963             fgDispHandlerTab();
11964         }
11965
11966         fgVerifyHandlerTab();
11967         fgDebugCheckBBlist();
11968 #endif // DEBUG
11969     }
11970 }
11971
11972 /*****************************************************************************
11973  *
11974  *  Function to create funclets out of all EH catch/finally/fault blocks.
11975  *  We only move filter and handler blocks, not try blocks.
11976  */
11977
11978 void Compiler::fgCreateFunclets()
11979 {
11980     assert(!fgFuncletsCreated);
11981
11982 #ifdef DEBUG
11983     if (verbose)
11984     {
11985         printf("*************** In fgCreateFunclets()\n");
11986     }
11987 #endif
11988
11989     fgCreateFuncletPrologBlocks();
11990
11991     unsigned           XTnum;
11992     EHblkDsc*          HBtab;
11993     const unsigned int funcCnt = ehFuncletCount() + 1;
11994
11995     if (!FitsIn<unsigned short>(funcCnt))
11996     {
11997         IMPL_LIMITATION("Too many funclets");
11998     }
11999
12000     FuncInfoDsc* funcInfo = new (this, CMK_BasicBlock) FuncInfoDsc[funcCnt];
12001
12002     unsigned short funcIdx;
12003
12004     // Setup the root FuncInfoDsc and prepare to start associating
12005     // FuncInfoDsc's with their corresponding EH region
12006     memset((void*)funcInfo, 0, funcCnt * sizeof(FuncInfoDsc));
12007     assert(funcInfo[0].funKind == FUNC_ROOT);
12008     funcIdx = 1;
12009
12010     // Because we iterate from the top to the bottom of the compHndBBtab array, we are iterating
12011     // from most nested (innermost) to least nested (outermost) EH region. It would be reasonable
12012     // to iterate in the opposite order, but the order of funclets shouldn't matter.
12013     //
12014     // We move every handler region to the end of the function: each handler will become a funclet.
12015     //
12016     // Note that fgRelocateEHRange() can add new entries to the EH table. However, they will always
12017     // be added *after* the current index, so our iteration here is not invalidated.
12018     // It *can* invalidate the compHndBBtab pointer itself, though, if it gets reallocated!
12019
12020     for (XTnum = 0; XTnum < compHndBBtabCount; XTnum++)
12021     {
12022         HBtab = ehGetDsc(XTnum); // must re-compute this every loop, since fgRelocateEHRange changes the table
12023         if (HBtab->HasFilter())
12024         {
12025             assert(funcIdx < funcCnt);
12026             funcInfo[funcIdx].funKind    = FUNC_FILTER;
12027             funcInfo[funcIdx].funEHIndex = (unsigned short)XTnum;
12028             funcIdx++;
12029         }
12030         assert(funcIdx < funcCnt);
12031         funcInfo[funcIdx].funKind    = FUNC_HANDLER;
12032         funcInfo[funcIdx].funEHIndex = (unsigned short)XTnum;
12033         HBtab->ebdFuncIndex          = funcIdx;
12034         funcIdx++;
12035         fgRelocateEHRange(XTnum, FG_RELOCATE_HANDLER);
12036     }
12037
12038     // We better have populated all of them by now
12039     assert(funcIdx == funcCnt);
12040
12041     // Publish
12042     compCurrFuncIdx   = 0;
12043     compFuncInfos     = funcInfo;
12044     compFuncInfoCount = (unsigned short)funcCnt;
12045
12046     fgFuncletsCreated = true;
12047
12048 #if DEBUG
12049     if (verbose)
12050     {
12051         JITDUMP("\nAfter fgCreateFunclets()");
12052         fgDispBasicBlocks();
12053         fgDispHandlerTab();
12054     }
12055
12056     fgVerifyHandlerTab();
12057     fgDebugCheckBBlist();
12058 #endif // DEBUG
12059 }
12060
12061 #else // !FEATURE_EH_FUNCLETS
12062
12063     /*****************************************************************************
12064      *
12065      *  Function called to relocate any and all EH regions.
12066      *  Only entire consecutive EH regions will be moved and they will be kept together.
12067      *  Except for the first block, the range can not have any blocks that jump into or out of the region.
12068      */
12069
12070     bool Compiler::fgRelocateEHRegions()
12071     {
12072         bool result = false; // Our return value
12073
12074 #ifdef DEBUG
12075         if (verbose)
12076             printf("*************** In fgRelocateEHRegions()\n");
12077 #endif
12078
12079         if (fgCanRelocateEHRegions)
12080         {
12081             unsigned  XTnum;
12082             EHblkDsc* HBtab;
12083
12084             for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
12085             {
12086                 // Nested EH regions cannot be moved.
12087                 // Also we don't want to relocate an EH region that has a filter
12088                 if ((HBtab->ebdHandlerNestingLevel == 0) && !HBtab->HasFilter())
12089                 {
12090                     bool movedTry = false;
12091 #if DEBUG
12092                     bool movedHnd = false;
12093 #endif // DEBUG
12094
12095                     // Only try to move the outermost try region
12096                     if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
12097                     {
12098                         // Move the entire try region if it can be moved
12099                         if (HBtab->ebdTryBeg->isRunRarely())
12100                         {
12101                             BasicBlock* bTryLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_TRY);
12102                             if (bTryLastBB != NULL)
12103                             {
12104                                 result   = true;
12105                                 movedTry = true;
12106                             }
12107                         }
12108 #if DEBUG
12109                         if (verbose && movedTry)
12110                         {
12111                             printf("\nAfter relocating an EH try region");
12112                             fgDispBasicBlocks();
12113                             fgDispHandlerTab();
12114
12115                             // Make sure that the predecessor lists are accurate
12116                             if (expensiveDebugCheckLevel >= 2)
12117                             {
12118                                 fgDebugCheckBBlist();
12119                             }
12120                         }
12121 #endif // DEBUG
12122                     }
12123
12124                     // Currently it is not good to move the rarely run handler regions to the end of the method
12125                     // because fgDetermineFirstColdBlock() must put the start of any handler region in the hot section.
12126                     CLANG_FORMAT_COMMENT_ANCHOR;
12127
12128 #if 0
12129                 // Now try to move the entire handler region if it can be moved.
12130                 // Don't try to move a finally handler unless we already moved the try region.
12131                 if (HBtab->ebdHndBeg->isRunRarely() &&
12132                     !HBtab->ebdHndBeg->hasTryIndex() &&
12133                     (movedTry || !HBtab->HasFinallyHandler()))
12134                 {
12135                     BasicBlock* bHndLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_HANDLER);
12136                     if (bHndLastBB != NULL)
12137                     {
12138                         result   = true;
12139                         movedHnd = true;
12140                     }
12141                 }
12142 #endif // 0
12143
12144 #if DEBUG
12145                     if (verbose && movedHnd)
12146                     {
12147                         printf("\nAfter relocating an EH handler region");
12148                         fgDispBasicBlocks();
12149                         fgDispHandlerTab();
12150
12151                         // Make sure that the predecessor lists are accurate
12152                         if (expensiveDebugCheckLevel >= 2)
12153                         {
12154                             fgDebugCheckBBlist();
12155                         }
12156                     }
12157 #endif // DEBUG
12158                 }
12159             }
12160         }
12161
12162 #if DEBUG
12163         fgVerifyHandlerTab();
12164
12165         if (verbose && result)
12166         {
12167             printf("\nAfter fgRelocateEHRegions()");
12168             fgDispBasicBlocks();
12169             fgDispHandlerTab();
12170             // Make sure that the predecessor lists are accurate
12171             fgDebugCheckBBlist();
12172         }
12173 #endif // DEBUG
12174
12175         return result;
12176     }
12177
12178 #endif // !FEATURE_EH_FUNCLETS
12179
12180 bool flowList::setEdgeWeightMinChecked(BasicBlock::weight_t newWeight, BasicBlock::weight_t slop, bool* wbUsedSlop)
12181 {
12182     bool result = false;
12183     if ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin))
12184     {
12185         flEdgeWeightMin = newWeight;
12186         result          = true;
12187     }
12188     else if (slop > 0)
12189     {
12190         // We allow for a small amount of inaccuracy in block weight counts.
12191         if (flEdgeWeightMax < newWeight)
12192         {
12193             // We have already determined that this edge's weight
12194             // is less than newWeight, so we just allow for the slop
12195             if (newWeight <= (flEdgeWeightMax + slop))
12196             {
12197                 result = true;
12198
12199                 if (flEdgeWeightMax != 0)
12200                 {
12201                     // We will raise flEdgeWeightMin and Max towards newWeight
12202                     flEdgeWeightMin = flEdgeWeightMax;
12203                     flEdgeWeightMax = newWeight;
12204                 }
12205
12206                 if (wbUsedSlop != nullptr)
12207                 {
12208                     *wbUsedSlop = true;
12209                 }
12210             }
12211         }
12212         else
12213         {
12214             assert(flEdgeWeightMin > newWeight);
12215
12216             // We have already determined that this edge's weight
12217             // is more than newWeight, so we just allow for the slop
12218             if ((newWeight + slop) >= flEdgeWeightMin)
12219             {
12220                 result = true;
12221
12222                 assert(flEdgeWeightMax != 0);
12223
12224                 // We will lower flEdgeWeightMin towards newWeight
12225                 flEdgeWeightMin = newWeight;
12226
12227                 if (wbUsedSlop != nullptr)
12228                 {
12229                     *wbUsedSlop = true;
12230                 }
12231             }
12232         }
12233
12234         // If we are returning true then we should have adjusted the range so that
12235         // the newWeight is in new range [Min..Max] or fgEdjeWeightMax is zero.
12236         // Also we should have set wbUsedSlop to true.
12237         if (result == true)
12238         {
12239             assert((flEdgeWeightMax == 0) || ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin)));
12240
12241             if (wbUsedSlop != nullptr)
12242             {
12243                 assert(*wbUsedSlop == true);
12244             }
12245         }
12246     }
12247
12248 #if DEBUG
12249     if (result == false)
12250     {
12251         result = false; // break here
12252     }
12253 #endif // DEBUG
12254
12255     return result;
12256 }
12257
12258 bool flowList::setEdgeWeightMaxChecked(BasicBlock::weight_t newWeight, BasicBlock::weight_t slop, bool* wbUsedSlop)
12259 {
12260     bool result = false;
12261     if ((newWeight >= flEdgeWeightMin) && (newWeight <= flEdgeWeightMax))
12262     {
12263         flEdgeWeightMax = newWeight;
12264         result          = true;
12265     }
12266     else if (slop > 0)
12267     {
12268         // We allow for a small amount of inaccuracy in block weight counts.
12269         if (flEdgeWeightMax < newWeight)
12270         {
12271             // We have already determined that this edge's weight
12272             // is less than newWeight, so we just allow for the slop
12273             if (newWeight <= (flEdgeWeightMax + slop))
12274             {
12275                 result = true;
12276
12277                 if (flEdgeWeightMax != 0)
12278                 {
12279                     // We will allow this to raise flEdgeWeightMax towards newWeight
12280                     flEdgeWeightMax = newWeight;
12281                 }
12282
12283                 if (wbUsedSlop != nullptr)
12284                 {
12285                     *wbUsedSlop = true;
12286                 }
12287             }
12288         }
12289         else
12290         {
12291             assert(flEdgeWeightMin > newWeight);
12292
12293             // We have already determined that this edge's weight
12294             // is more than newWeight, so we just allow for the slop
12295             if ((newWeight + slop) >= flEdgeWeightMin)
12296             {
12297                 result = true;
12298
12299                 assert(flEdgeWeightMax != 0);
12300
12301                 // We will allow this to lower flEdgeWeightMin and Max towards newWeight
12302                 flEdgeWeightMax = flEdgeWeightMin;
12303                 flEdgeWeightMin = newWeight;
12304
12305                 if (wbUsedSlop != nullptr)
12306                 {
12307                     *wbUsedSlop = true;
12308                 }
12309             }
12310         }
12311
12312         // If we are returning true then we should have adjusted the range so that
12313         // the newWeight is in new range [Min..Max] or fgEdjeWeightMax is zero
12314         // Also we should have set wbUsedSlop to true, unless it is NULL
12315         if (result == true)
12316         {
12317             assert((flEdgeWeightMax == 0) || ((newWeight <= flEdgeWeightMax) && (newWeight >= flEdgeWeightMin)));
12318
12319             assert((wbUsedSlop == nullptr) || (*wbUsedSlop == true));
12320         }
12321     }
12322
12323 #if DEBUG
12324     if (result == false)
12325     {
12326         result = false; // break here
12327     }
12328 #endif // DEBUG
12329
12330     return result;
12331 }
12332
12333 #ifdef DEBUG
12334 void Compiler::fgPrintEdgeWeights()
12335 {
12336     BasicBlock* bSrc;
12337     BasicBlock* bDst;
12338     flowList*   edge;
12339
12340     // Print out all of the edge weights
12341     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12342     {
12343         if (bDst->bbPreds != nullptr)
12344         {
12345             printf("    Edge weights into BB%02u :", bDst->bbNum);
12346             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
12347             {
12348                 bSrc = edge->flBlock;
12349                 // This is the control flow edge (bSrc -> bDst)
12350
12351                 printf("BB%02u ", bSrc->bbNum);
12352
12353                 if (edge->flEdgeWeightMin < BB_MAX_WEIGHT)
12354                 {
12355                     printf("(%s", refCntWtd2str(edge->flEdgeWeightMin));
12356                 }
12357                 else
12358                 {
12359                     printf("(MAX");
12360                 }
12361                 if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
12362                 {
12363                     if (edge->flEdgeWeightMax < BB_MAX_WEIGHT)
12364                     {
12365                         printf("..%s", refCntWtd2str(edge->flEdgeWeightMax));
12366                     }
12367                     else
12368                     {
12369                         printf("..MAX");
12370                     }
12371                 }
12372                 printf(")");
12373                 if (edge->flNext != nullptr)
12374                 {
12375                     printf(", ");
12376                 }
12377             }
12378             printf("\n");
12379         }
12380     }
12381 }
12382 #endif // DEBUG
12383
12384 // return true if there is a possibility that the method has a loop (a backedge is present)
12385 bool Compiler::fgMightHaveLoop()
12386 {
12387     // Don't use a BlockSet for this temporary bitset of blocks: we don't want to have to call EnsureBasicBlockEpoch()
12388     // and potentially change the block epoch.
12389
12390     BitVecTraits blockVecTraits(fgBBNumMax + 1, this);
12391     BitVec       BLOCKSET_INIT_NOCOPY(blocksSeen, BitVecOps::MakeEmpty(&blockVecTraits));
12392
12393     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
12394     {
12395         BitVecOps::AddElemD(&blockVecTraits, blocksSeen, block->bbNum);
12396
12397         AllSuccessorIter succsEnd = block->GetAllSuccs(this).end();
12398         for (AllSuccessorIter succs = block->GetAllSuccs(this).begin(); succs != succsEnd; ++succs)
12399         {
12400             BasicBlock* succ = (*succs);
12401             if (BitVecOps::IsMember(&blockVecTraits, blocksSeen, succ->bbNum))
12402             {
12403                 return true;
12404             }
12405         }
12406     }
12407     return false;
12408 }
12409
12410 void Compiler::fgComputeEdgeWeights()
12411 {
12412 #ifdef DEBUG
12413     if (verbose)
12414     {
12415         printf("*************** In fgComputeEdgeWeights()\n");
12416     }
12417 #endif // DEBUG
12418
12419     if (fgIsUsingProfileWeights() == false)
12420     {
12421 #ifdef DEBUG
12422         if (verbose)
12423         {
12424             printf("fgComputeEdgeWeights() we do not have any profile data so we are not using the edge weights\n");
12425         }
12426 #endif // DEBUG
12427         fgHaveValidEdgeWeights = false;
12428         fgCalledWeight         = BB_UNITY_WEIGHT;
12429     }
12430
12431 #if DEBUG
12432     if (verbose)
12433     {
12434         fgDispBasicBlocks();
12435         printf("\n");
12436     }
12437 #endif // DEBUG
12438
12439     BasicBlock* bSrc;
12440     BasicBlock* bDst;
12441     flowList*   edge;
12442     unsigned    iterations               = 0;
12443     unsigned    goodEdgeCountCurrent     = 0;
12444     unsigned    goodEdgeCountPrevious    = 0;
12445     bool        inconsistentProfileData  = false;
12446     bool        hasIncompleteEdgeWeights = false;
12447     unsigned    numEdges                 = 0;
12448     bool        usedSlop                 = false;
12449     bool        changed;
12450     bool        modified;
12451
12452     BasicBlock::weight_t returnWeight;
12453     BasicBlock::weight_t slop;
12454
12455     // If we have any blocks that did not have profile derived weight
12456     // we will try to fix their weight up here
12457     //
12458     modified = false;
12459     do // while (changed)
12460     {
12461         changed      = false;
12462         returnWeight = 0;
12463         iterations++;
12464
12465         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12466         {
12467             if (((bDst->bbFlags & BBF_PROF_WEIGHT) == 0) && (bDst->bbPreds != nullptr))
12468             {
12469                 BasicBlock* bOnlyNext;
12470
12471                 // This block does not have a profile derived weight
12472                 //
12473                 BasicBlock::weight_t newWeight = BB_MAX_WEIGHT;
12474
12475                 if (bDst->countOfInEdges() == 1)
12476                 {
12477                     // Only one block flows into bDst
12478                     bSrc = bDst->bbPreds->flBlock;
12479
12480                     // Does this block flow into only one other block
12481                     if (bSrc->bbJumpKind == BBJ_NONE)
12482                     {
12483                         bOnlyNext = bSrc->bbNext;
12484                     }
12485                     else if (bSrc->bbJumpKind == BBJ_ALWAYS)
12486                     {
12487                         bOnlyNext = bSrc->bbJumpDest;
12488                     }
12489                     else
12490                     {
12491                         bOnlyNext = nullptr;
12492                     }
12493
12494                     if ((bOnlyNext == bDst) && ((bSrc->bbFlags & BBF_PROF_WEIGHT) != 0))
12495                     {
12496                         // We know the exact weight of bDst
12497                         newWeight = bSrc->bbWeight;
12498                     }
12499                 }
12500
12501                 // Does this block flow into only one other block
12502                 if (bDst->bbJumpKind == BBJ_NONE)
12503                 {
12504                     bOnlyNext = bDst->bbNext;
12505                 }
12506                 else if (bDst->bbJumpKind == BBJ_ALWAYS)
12507                 {
12508                     bOnlyNext = bDst->bbJumpDest;
12509                 }
12510                 else
12511                 {
12512                     bOnlyNext = nullptr;
12513                 }
12514
12515                 if ((bOnlyNext != nullptr) && (bOnlyNext->bbPreds != nullptr))
12516                 {
12517                     // Does only one block flow into bOnlyNext
12518                     if (bOnlyNext->countOfInEdges() == 1)
12519                     {
12520                         noway_assert(bOnlyNext->bbPreds->flBlock == bDst);
12521
12522                         // We know the exact weight of bDst
12523                         newWeight = bOnlyNext->bbWeight;
12524                     }
12525                 }
12526
12527                 if ((newWeight != BB_MAX_WEIGHT) && (bDst->bbWeight != newWeight))
12528                 {
12529                     changed        = true;
12530                     modified       = true;
12531                     bDst->bbWeight = newWeight;
12532                     if (newWeight == 0)
12533                     {
12534                         bDst->bbFlags |= BBF_RUN_RARELY;
12535                     }
12536                     else
12537                     {
12538                         bDst->bbFlags &= ~BBF_RUN_RARELY;
12539                     }
12540                 }
12541             }
12542
12543             // Sum up the weights of all of the return blocks and throw blocks
12544             // This is used when we have a back-edge into block 1
12545             //
12546             if (((bDst->bbFlags & BBF_PROF_WEIGHT) != 0) &&
12547                 ((bDst->bbJumpKind == BBJ_RETURN) || (bDst->bbJumpKind == BBJ_THROW)))
12548             {
12549                 returnWeight += bDst->bbWeight;
12550             }
12551         }
12552     }
12553     // Generally when we synthesize profile estimates we do it in a way where this algorithm will converge
12554     // but downstream opts that remove conditional branches may create a situation where this is not the case.
12555     // For instance a loop that becomes unreachable creates a sort of 'ring oscillator' (See test b539509)
12556     while (changed && iterations < 10);
12557
12558 #if DEBUG
12559     if (verbose && modified)
12560     {
12561         printf("fgComputeEdgeWeights() adjusted the weight of some blocks\n");
12562         fgDispBasicBlocks();
12563         printf("\n");
12564     }
12565 #endif
12566
12567     // When we are not using profile data we have already setup fgCalledWeight
12568     // only set it here if we are using profile data
12569     //
12570     if (fgIsUsingProfileWeights())
12571     {
12572         // If the first block has one ref then it's weight is the fgCalledWeight
12573         // otherwise we have backedge's into the first block so instead
12574         // we use the sum of the return block weights.
12575         // If the profile data has a 0 for the returnWeoght
12576         // then just use the first block weight rather than the 0
12577         //
12578         if ((fgFirstBB->countOfInEdges() == 1) || (returnWeight == 0))
12579         {
12580             fgCalledWeight = fgFirstBB->bbWeight;
12581         }
12582         else
12583         {
12584             fgCalledWeight = returnWeight;
12585         }
12586     }
12587
12588     // Now we will compute the initial flEdgeWeightMin and flEdgeWeightMax values
12589     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12590     {
12591         BasicBlock::weight_t bDstWeight = bDst->bbWeight;
12592
12593         // We subtract out the called count so that bDstWeight is
12594         // the sum of all edges that go into this block from this method.
12595         //
12596         if (bDst == fgFirstBB)
12597         {
12598             bDstWeight -= fgCalledWeight;
12599         }
12600
12601         for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
12602         {
12603             bool assignOK = true;
12604
12605             bSrc = edge->flBlock;
12606             // We are processing the control flow edge (bSrc -> bDst)
12607
12608             numEdges++;
12609
12610             //
12611             // If the bSrc or bDst blocks do not have exact profile weights
12612             // then we must reset any values that they currently have
12613             //
12614
12615             if (((bSrc->bbFlags & BBF_PROF_WEIGHT) == 0) || ((bDst->bbFlags & BBF_PROF_WEIGHT) == 0))
12616             {
12617                 edge->flEdgeWeightMin = BB_ZERO_WEIGHT;
12618                 edge->flEdgeWeightMax = BB_MAX_WEIGHT;
12619             }
12620
12621             slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
12622             switch (bSrc->bbJumpKind)
12623             {
12624                 case BBJ_ALWAYS:
12625                 case BBJ_EHCATCHRET:
12626                 case BBJ_NONE:
12627                 case BBJ_CALLFINALLY:
12628                     // We know the exact edge weight
12629                     assignOK &= edge->setEdgeWeightMinChecked(bSrc->bbWeight, slop, &usedSlop);
12630                     assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, slop, &usedSlop);
12631                     break;
12632
12633                 case BBJ_COND:
12634                 case BBJ_SWITCH:
12635                 case BBJ_EHFINALLYRET:
12636                 case BBJ_EHFILTERRET:
12637                     if (edge->flEdgeWeightMax > bSrc->bbWeight)
12638                     {
12639                         // The maximum edge weight to block can't be greater than the weight of bSrc
12640                         assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, slop, &usedSlop);
12641                     }
12642                     break;
12643
12644                 default:
12645                     // We should never have an edge that starts from one of these jump kinds
12646                     noway_assert(!"Unexpected bbJumpKind");
12647                     break;
12648             }
12649
12650             // The maximum edge weight to block can't be greater than the weight of bDst
12651             if (edge->flEdgeWeightMax > bDstWeight)
12652             {
12653                 assignOK &= edge->setEdgeWeightMaxChecked(bDstWeight, slop, &usedSlop);
12654             }
12655
12656             if (!assignOK)
12657             {
12658                 // Here we have inconsistent profile data
12659                 inconsistentProfileData = true;
12660                 // No point in continuing
12661                 goto EARLY_EXIT;
12662             }
12663         }
12664     }
12665
12666     fgEdgeCount = numEdges;
12667
12668     iterations = 0;
12669
12670     do
12671     {
12672         iterations++;
12673         goodEdgeCountPrevious    = goodEdgeCountCurrent;
12674         goodEdgeCountCurrent     = 0;
12675         hasIncompleteEdgeWeights = false;
12676
12677         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12678         {
12679             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
12680             {
12681                 bool assignOK = true;
12682
12683                 // We are processing the control flow edge (bSrc -> bDst)
12684                 bSrc = edge->flBlock;
12685
12686                 slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
12687                 if (bSrc->bbJumpKind == BBJ_COND)
12688                 {
12689                     int       diff;
12690                     flowList* otherEdge;
12691                     if (bSrc->bbNext == bDst)
12692                     {
12693                         otherEdge = fgGetPredForBlock(bSrc->bbJumpDest, bSrc);
12694                     }
12695                     else
12696                     {
12697                         otherEdge = fgGetPredForBlock(bSrc->bbNext, bSrc);
12698                     }
12699                     noway_assert(edge->flEdgeWeightMin <= edge->flEdgeWeightMax);
12700                     noway_assert(otherEdge->flEdgeWeightMin <= otherEdge->flEdgeWeightMax);
12701
12702                     // Adjust edge->flEdgeWeightMin up or adjust otherEdge->flEdgeWeightMax down
12703                     diff = ((int)bSrc->bbWeight) - ((int)edge->flEdgeWeightMin + (int)otherEdge->flEdgeWeightMax);
12704                     if (diff > 0)
12705                     {
12706                         assignOK &= edge->setEdgeWeightMinChecked(edge->flEdgeWeightMin + diff, slop, &usedSlop);
12707                     }
12708                     else if (diff < 0)
12709                     {
12710                         assignOK &=
12711                             otherEdge->setEdgeWeightMaxChecked(otherEdge->flEdgeWeightMax + diff, slop, &usedSlop);
12712                     }
12713
12714                     // Adjust otherEdge->flEdgeWeightMin up or adjust edge->flEdgeWeightMax down
12715                     diff = ((int)bSrc->bbWeight) - ((int)otherEdge->flEdgeWeightMin + (int)edge->flEdgeWeightMax);
12716                     if (diff > 0)
12717                     {
12718                         assignOK &=
12719                             otherEdge->setEdgeWeightMinChecked(otherEdge->flEdgeWeightMin + diff, slop, &usedSlop);
12720                     }
12721                     else if (diff < 0)
12722                     {
12723                         assignOK &= edge->setEdgeWeightMaxChecked(edge->flEdgeWeightMax + diff, slop, &usedSlop);
12724                     }
12725
12726                     if (!assignOK)
12727                     {
12728                         // Here we have inconsistent profile data
12729                         inconsistentProfileData = true;
12730                         // No point in continuing
12731                         goto EARLY_EXIT;
12732                     }
12733 #ifdef DEBUG
12734                     // Now edge->flEdgeWeightMin and otherEdge->flEdgeWeightMax) should add up to bSrc->bbWeight
12735                     diff = ((int)bSrc->bbWeight) - ((int)edge->flEdgeWeightMin + (int)otherEdge->flEdgeWeightMax);
12736                     noway_assert((-((int)slop) <= diff) && (diff <= ((int)slop)));
12737
12738                     // Now otherEdge->flEdgeWeightMin and edge->flEdgeWeightMax) should add up to bSrc->bbWeight
12739                     diff = ((int)bSrc->bbWeight) - ((int)otherEdge->flEdgeWeightMin + (int)edge->flEdgeWeightMax);
12740                     noway_assert((-((int)slop) <= diff) && (diff <= ((int)slop)));
12741 #endif // DEBUG
12742                 }
12743             }
12744         }
12745
12746         for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12747         {
12748             BasicBlock::weight_t bDstWeight = bDst->bbWeight;
12749
12750             if (bDstWeight == BB_MAX_WEIGHT)
12751             {
12752                 inconsistentProfileData = true;
12753                 // No point in continuing
12754                 goto EARLY_EXIT;
12755             }
12756             else
12757             {
12758                 // We subtract out the called count so that bDstWeight is
12759                 // the sum of all edges that go into this block from this method.
12760                 //
12761                 if (bDst == fgFirstBB)
12762                 {
12763                     bDstWeight -= fgCalledWeight;
12764                 }
12765
12766                 UINT64 minEdgeWeightSum = 0;
12767                 UINT64 maxEdgeWeightSum = 0;
12768
12769                 // Calculate the sums of the minimum and maximum edge weights
12770                 for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
12771                 {
12772                     // We are processing the control flow edge (bSrc -> bDst)
12773                     bSrc = edge->flBlock;
12774
12775                     maxEdgeWeightSum += edge->flEdgeWeightMax;
12776                     minEdgeWeightSum += edge->flEdgeWeightMin;
12777                 }
12778
12779                 // maxEdgeWeightSum is the sum of all flEdgeWeightMax values into bDst
12780                 // minEdgeWeightSum is the sum of all flEdgeWeightMin values into bDst
12781
12782                 for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
12783                 {
12784                     bool assignOK = true;
12785
12786                     // We are processing the control flow edge (bSrc -> bDst)
12787                     bSrc = edge->flBlock;
12788                     slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1;
12789
12790                     // otherMaxEdgesWeightSum is the sum of all of the other edges flEdgeWeightMax values
12791                     // This can be used to compute a lower bound for our minimum edge weight
12792                     noway_assert(maxEdgeWeightSum >= edge->flEdgeWeightMax);
12793                     UINT64 otherMaxEdgesWeightSum = maxEdgeWeightSum - edge->flEdgeWeightMax;
12794
12795                     // otherMinEdgesWeightSum is the sum of all of the other edges flEdgeWeightMin values
12796                     // This can be used to compute an upper bound for our maximum edge weight
12797                     noway_assert(minEdgeWeightSum >= edge->flEdgeWeightMin);
12798                     UINT64 otherMinEdgesWeightSum = minEdgeWeightSum - edge->flEdgeWeightMin;
12799
12800                     if (bDstWeight >= otherMaxEdgesWeightSum)
12801                     {
12802                         // minWeightCalc is our minWeight when every other path to bDst takes it's flEdgeWeightMax value
12803                         BasicBlock::weight_t minWeightCalc =
12804                             (BasicBlock::weight_t)(bDstWeight - otherMaxEdgesWeightSum);
12805                         if (minWeightCalc > edge->flEdgeWeightMin)
12806                         {
12807                             assignOK &= edge->setEdgeWeightMinChecked(minWeightCalc, slop, &usedSlop);
12808                         }
12809                     }
12810
12811                     if (bDstWeight >= otherMinEdgesWeightSum)
12812                     {
12813                         // maxWeightCalc is our maxWeight when every other path to bDst takes it's flEdgeWeightMin value
12814                         BasicBlock::weight_t maxWeightCalc =
12815                             (BasicBlock::weight_t)(bDstWeight - otherMinEdgesWeightSum);
12816                         if (maxWeightCalc < edge->flEdgeWeightMax)
12817                         {
12818                             assignOK &= edge->setEdgeWeightMaxChecked(maxWeightCalc, slop, &usedSlop);
12819                         }
12820                     }
12821
12822                     if (!assignOK)
12823                     {
12824                         // Here we have inconsistent profile data
12825                         inconsistentProfileData = true;
12826                         // No point in continuing
12827                         goto EARLY_EXIT;
12828                     }
12829
12830                     // When flEdgeWeightMin equals flEdgeWeightMax we have a "good" edge weight
12831                     if (edge->flEdgeWeightMin == edge->flEdgeWeightMax)
12832                     {
12833                         // Count how many "good" edge weights we have
12834                         // Each time through we should have more "good" weights
12835                         // We exit the while loop when no longer find any new "good" edges
12836                         goodEdgeCountCurrent++;
12837                     }
12838                     else
12839                     {
12840                         // Remember that we have seen at least one "Bad" edge weight
12841                         // so that we will repeat the while loop again
12842                         hasIncompleteEdgeWeights = true;
12843                     }
12844                 }
12845             }
12846         }
12847
12848         if (inconsistentProfileData)
12849         {
12850             hasIncompleteEdgeWeights = true;
12851             break;
12852         }
12853
12854         if (numEdges == goodEdgeCountCurrent)
12855         {
12856             noway_assert(hasIncompleteEdgeWeights == false);
12857             break;
12858         }
12859
12860     } while (hasIncompleteEdgeWeights && (goodEdgeCountCurrent > goodEdgeCountPrevious) && (iterations < 8));
12861
12862 EARLY_EXIT:;
12863
12864 #ifdef DEBUG
12865     if (verbose)
12866     {
12867         if (inconsistentProfileData)
12868         {
12869             printf("fgComputeEdgeWeights() found inconsistent profile data, not using the edge weights\n");
12870         }
12871         else
12872         {
12873             if (hasIncompleteEdgeWeights)
12874             {
12875                 printf("fgComputeEdgeWeights() was able to compute exact edge weights for %3d of the %3d edges, using "
12876                        "%d passes.\n",
12877                        goodEdgeCountCurrent, numEdges, iterations);
12878             }
12879             else
12880             {
12881                 printf("fgComputeEdgeWeights() was able to compute exact edge weights for all of the %3d edges, using "
12882                        "%d passes.\n",
12883                        numEdges, iterations);
12884             }
12885
12886             fgPrintEdgeWeights();
12887         }
12888     }
12889 #endif // DEBUG
12890
12891     fgSlopUsedInEdgeWeights  = usedSlop;
12892     fgRangeUsedInEdgeWeights = false;
12893
12894     // See if any edge weight are expressed in [min..max] form
12895
12896     for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext)
12897     {
12898         if (bDst->bbPreds != nullptr)
12899         {
12900             for (edge = bDst->bbPreds; edge != nullptr; edge = edge->flNext)
12901             {
12902                 bSrc = edge->flBlock;
12903                 // This is the control flow edge (bSrc -> bDst)
12904
12905                 if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
12906                 {
12907                     fgRangeUsedInEdgeWeights = true;
12908                     break;
12909                 }
12910             }
12911             if (fgRangeUsedInEdgeWeights)
12912             {
12913                 break;
12914             }
12915         }
12916     }
12917
12918     fgHaveValidEdgeWeights = !inconsistentProfileData;
12919     fgEdgeWeightsComputed  = true;
12920 }
12921
12922 // fgOptimizeBranchToEmptyUnconditional:
12923 //    optimize a jump to an empty block which ends in an unconditional branch.
12924 //  Args:
12925 //      block: source block
12926 //      bDest: destination
12927 //  Returns: true if we changed the code
12928 //
12929 bool Compiler::fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBlock* bDest)
12930 {
12931     bool optimizeJump = true;
12932
12933     assert(bDest->isEmpty());
12934     assert(bDest->bbJumpKind == BBJ_ALWAYS);
12935
12936     // We do not optimize jumps between two different try regions.
12937     // However jumping to a block that is not in any try region is OK
12938     //
12939     if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
12940     {
12941         optimizeJump = false;
12942     }
12943
12944     // Don't optimize a jump to a removed block
12945     if (bDest->bbJumpDest->bbFlags & BBF_REMOVED)
12946     {
12947         optimizeJump = false;
12948     }
12949
12950 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
12951     // Don't optimize a jump to a finally target. For BB1->BB2->BB3, where
12952     // BB2 is a finally target, if we changed BB1 to jump directly to BB3,
12953     // it would skip the finally target. BB1 might be a BBJ_ALWAYS block part
12954     // of a BBJ_CALLFINALLY/BBJ_ALWAYS pair, so changing the finally target
12955     // would change the unwind behavior.
12956     if (bDest->bbFlags & BBF_FINALLY_TARGET)
12957     {
12958         optimizeJump = false;
12959     }
12960 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
12961
12962     // Must optimize jump if bDest has been removed
12963     //
12964     if (bDest->bbFlags & BBF_REMOVED)
12965     {
12966         optimizeJump = true;
12967     }
12968
12969     // If we are optimizing using real profile weights
12970     // then don't optimize a conditional jump to an unconditional jump
12971     // until after we have computed the edge weights
12972     //
12973     if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed)
12974     {
12975         fgNeedsUpdateFlowGraph = true;
12976         optimizeJump           = false;
12977     }
12978
12979     if (optimizeJump)
12980     {
12981 #ifdef DEBUG
12982         if (verbose)
12983         {
12984             printf("\nOptimizing a jump to an unconditional jump (BB%02u -> BB%02u -> BB%02u)\n", block->bbNum,
12985                    bDest->bbNum, bDest->bbJumpDest->bbNum);
12986         }
12987 #endif // DEBUG
12988
12989         //
12990         // When we optimize a branch to branch we need to update the profile weight
12991         // of bDest by subtracting out the block/edge weight of the path that is being optimized.
12992         //
12993         if (fgHaveValidEdgeWeights && ((bDest->bbFlags & BBF_PROF_WEIGHT) != 0))
12994         {
12995             flowList* edge1 = fgGetPredForBlock(bDest, block);
12996             noway_assert(edge1 != nullptr);
12997
12998             BasicBlock::weight_t edgeWeight;
12999
13000             if (edge1->flEdgeWeightMin != edge1->flEdgeWeightMax)
13001             {
13002                 //
13003                 // We only have an estimate for the edge weight
13004                 //
13005                 edgeWeight = (edge1->flEdgeWeightMin + edge1->flEdgeWeightMax) / 2;
13006                 //
13007                 //  Clear the profile weight flag
13008                 //
13009                 bDest->bbFlags &= ~BBF_PROF_WEIGHT;
13010             }
13011             else
13012             {
13013                 //
13014                 // We only have the exact edge weight
13015                 //
13016                 edgeWeight = edge1->flEdgeWeightMin;
13017             }
13018
13019             //
13020             // Update the bDest->bbWeight
13021             //
13022             if (bDest->bbWeight > edgeWeight)
13023             {
13024                 bDest->bbWeight -= edgeWeight;
13025             }
13026             else
13027             {
13028                 bDest->bbWeight = BB_ZERO_WEIGHT;
13029                 bDest->bbFlags |= BBF_RUN_RARELY; // Set the RarelyRun flag
13030             }
13031
13032             flowList* edge2 = fgGetPredForBlock(bDest->bbJumpDest, bDest);
13033
13034             if (edge2 != nullptr)
13035             {
13036                 //
13037                 // Update the edge2 min/max weights
13038                 //
13039                 if (edge2->flEdgeWeightMin > edge1->flEdgeWeightMin)
13040                 {
13041                     edge2->flEdgeWeightMin -= edge1->flEdgeWeightMin;
13042                 }
13043                 else
13044                 {
13045                     edge2->flEdgeWeightMin = BB_ZERO_WEIGHT;
13046                 }
13047
13048                 if (edge2->flEdgeWeightMax > edge1->flEdgeWeightMin)
13049                 {
13050                     edge2->flEdgeWeightMax -= edge1->flEdgeWeightMin;
13051                 }
13052                 else
13053                 {
13054                     edge2->flEdgeWeightMax = BB_ZERO_WEIGHT;
13055                 }
13056             }
13057         }
13058
13059         // Optimize the JUMP to empty unconditional JUMP to go to the new target
13060         block->bbJumpDest = bDest->bbJumpDest;
13061
13062         fgAddRefPred(bDest->bbJumpDest, block, fgRemoveRefPred(bDest, block));
13063
13064         return true;
13065     }
13066     return false;
13067 }
13068
13069 // fgOptimizeEmptyBlock:
13070 //   Does flow optimization of an empty block (can remove it in some cases)
13071 //
13072 //  Args:
13073 //      block: an empty block
13074 //  Returns: true if we changed the code
13075
13076 bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block)
13077 {
13078     assert(block->isEmpty());
13079
13080     BasicBlock* bPrev = block->bbPrev;
13081
13082     switch (block->bbJumpKind)
13083     {
13084         case BBJ_COND:
13085         case BBJ_SWITCH:
13086         case BBJ_THROW:
13087
13088             /* can never happen */
13089             noway_assert(!"Conditional, switch, or throw block with empty body!");
13090             break;
13091
13092         case BBJ_CALLFINALLY:
13093         case BBJ_RETURN:
13094         case BBJ_EHCATCHRET:
13095         case BBJ_EHFINALLYRET:
13096         case BBJ_EHFILTERRET:
13097
13098             /* leave them as is */
13099             /* some compilers generate multiple returns and put all of them at the end -
13100              * to solve that we need the predecessor list */
13101
13102             break;
13103
13104         case BBJ_ALWAYS:
13105
13106             // A GOTO cannot be to the next block since that
13107             // should have been fixed by the  optimization above
13108             // An exception is made for a jump from Hot to Cold
13109             noway_assert(block->bbJumpDest != block->bbNext || ((bPrev != nullptr) && bPrev->isBBCallAlwaysPair()) ||
13110                          fgInDifferentRegions(block, block->bbNext));
13111
13112             /* Cannot remove the first BB */
13113             if (!bPrev)
13114             {
13115                 break;
13116             }
13117
13118             /* Do not remove a block that jumps to itself - used for while (true){} */
13119             if (block->bbJumpDest == block)
13120             {
13121                 break;
13122             }
13123
13124             /* Empty GOTO can be removed iff bPrev is BBJ_NONE */
13125             if (bPrev->bbJumpKind != BBJ_NONE)
13126             {
13127                 break;
13128             }
13129
13130             // can't allow fall through into cold code
13131             if (block->bbNext == fgFirstColdBlock)
13132             {
13133                 break;
13134             }
13135
13136             /* Can fall through since this is similar with removing
13137              * a BBJ_NONE block, only the successor is different */
13138
13139             __fallthrough;
13140
13141         case BBJ_NONE:
13142
13143             /* special case if this is the first BB */
13144             if (!bPrev)
13145             {
13146                 assert(block == fgFirstBB);
13147             }
13148             else
13149             {
13150                 /* If this block follows a BBJ_CALLFINALLY do not remove it
13151                  * (because we don't know who may jump to it) */
13152                 if (bPrev->bbJumpKind == BBJ_CALLFINALLY)
13153                 {
13154                     break;
13155                 }
13156             }
13157
13158 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13159             /* Don't remove finally targets */
13160             if (block->bbFlags & BBF_FINALLY_TARGET)
13161                 break;
13162 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
13163
13164 #if FEATURE_EH_FUNCLETS
13165             /* Don't remove an empty block that is in a different EH region
13166              * from its successor block, if the block is the target of a
13167              * catch return. It is required that the return address of a
13168              * catch be in the correct EH region, for re-raise of thread
13169              * abort exceptions to work. Insert a NOP in the empty block
13170              * to ensure we generate code for the block, if we keep it.
13171              */
13172             {
13173                 BasicBlock* succBlock;
13174
13175                 if (block->bbJumpKind == BBJ_ALWAYS)
13176                 {
13177                     succBlock = block->bbJumpDest;
13178                 }
13179                 else
13180                 {
13181                     succBlock = block->bbNext;
13182                 }
13183
13184                 if ((succBlock != nullptr) && !BasicBlock::sameEHRegion(block, succBlock))
13185                 {
13186                     // The empty block and the block that follows it are in different
13187                     // EH regions. Is this a case where they can't be merged?
13188
13189                     bool okToMerge = true; // assume it's ok
13190                     for (flowList* pred = block->bbPreds; pred; pred = pred->flNext)
13191                     {
13192                         if (pred->flBlock->bbJumpKind == BBJ_EHCATCHRET)
13193                         {
13194                             assert(pred->flBlock->bbJumpDest == block);
13195                             okToMerge = false; // we can't get rid of the empty block
13196                             break;
13197                         }
13198                     }
13199
13200                     if (!okToMerge)
13201                     {
13202                         // Insert a NOP in the empty block to ensure we generate code
13203                         // for the catchret target in the right EH region.
13204                         GenTree* nop = new (this, GT_NO_OP) GenTree(GT_NO_OP, TYP_VOID);
13205
13206                         if (block->IsLIR())
13207                         {
13208                             LIR::AsRange(block).InsertAtEnd(nop);
13209                         }
13210                         else
13211                         {
13212                             GenTreePtr nopStmt = fgInsertStmtAtEnd(block, nop);
13213                             fgSetStmtSeq(nopStmt);
13214                             gtSetStmtInfo(nopStmt);
13215                         }
13216
13217 #ifdef DEBUG
13218                         if (verbose)
13219                         {
13220                             printf("\nKeeping empty block BB%02u - it is the target of a catch return\n", block->bbNum);
13221                         }
13222 #endif // DEBUG
13223
13224                         break; // go to the next block
13225                     }
13226                 }
13227             }
13228 #endif // FEATURE_EH_FUNCLETS
13229
13230             if (!ehCanDeleteEmptyBlock(block))
13231             {
13232                 // We're not allowed to remove this block due to reasons related to the EH table.
13233                 break;
13234             }
13235
13236             /* special case if this is the last BB */
13237             if (block == fgLastBB)
13238             {
13239                 if (!bPrev)
13240                 {
13241                     break;
13242                 }
13243                 fgLastBB = bPrev;
13244             }
13245
13246             /* Remove the block */
13247             compCurBB = block;
13248             fgRemoveBlock(block, false);
13249             return true;
13250
13251         default:
13252             noway_assert(!"Unexpected bbJumpKind");
13253             break;
13254     }
13255     return false;
13256 }
13257
13258 // fgOptimizeSwitchBranches:
13259 //   Does flow optimization for a switch - bypasses jumps to empty unconditional branches,
13260 //      and transforms degenerate switch cases like those with 1 or 2 targets
13261 //
13262 //  Args:
13263 //      block: BasicBlock that contains the switch
13264 //  Returns: true if we changed the code
13265 //
13266 bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block)
13267 {
13268     assert(block->bbJumpKind == BBJ_SWITCH);
13269
13270     unsigned     jmpCnt = block->bbJumpSwt->bbsCount;
13271     BasicBlock** jmpTab = block->bbJumpSwt->bbsDstTab;
13272     BasicBlock*  bNewDest; // the new jump target for the current switch case
13273     BasicBlock*  bDest;
13274     bool         returnvalue = false;
13275
13276     do
13277     {
13278     REPEAT_SWITCH:;
13279         bDest    = *jmpTab;
13280         bNewDest = bDest;
13281
13282         // Do we have a JUMP to an empty unconditional JUMP block?
13283         if (bDest->isEmpty() && (bDest->bbJumpKind == BBJ_ALWAYS) &&
13284             (bDest != bDest->bbJumpDest)) // special case for self jumps
13285         {
13286             bool optimizeJump = true;
13287
13288             // We do not optimize jumps between two different try regions.
13289             // However jumping to a block that is not in any try region is OK
13290             //
13291             if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
13292             {
13293                 optimizeJump = false;
13294             }
13295
13296             // If we are optimize using real profile weights
13297             // then don't optimize a switch jump to an unconditional jump
13298             // until after we have computed the edge weights
13299             //
13300             if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed)
13301             {
13302                 fgNeedsUpdateFlowGraph = true;
13303                 optimizeJump           = false;
13304             }
13305
13306             if (optimizeJump)
13307             {
13308                 bNewDest = bDest->bbJumpDest;
13309 #ifdef DEBUG
13310                 if (verbose)
13311                 {
13312                     printf("\nOptimizing a switch jump to an empty block with an unconditional jump (BB%02u -> BB%02u "
13313                            "-> BB%02u)\n",
13314                            block->bbNum, bDest->bbNum, bNewDest->bbNum);
13315                 }
13316 #endif // DEBUG
13317             }
13318         }
13319
13320         if (bNewDest != bDest)
13321         {
13322             //
13323             // When we optimize a branch to branch we need to update the profile weight
13324             // of bDest by subtracting out the block/edge weight of the path that is being optimized.
13325             //
13326             if (fgIsUsingProfileWeights() && ((bDest->bbFlags & BBF_PROF_WEIGHT) != 0))
13327             {
13328                 if (fgHaveValidEdgeWeights)
13329                 {
13330                     flowList*            edge                = fgGetPredForBlock(bDest, block);
13331                     BasicBlock::weight_t branchThroughWeight = edge->flEdgeWeightMin;
13332
13333                     if (bDest->bbWeight > branchThroughWeight)
13334                     {
13335                         bDest->bbWeight -= branchThroughWeight;
13336                     }
13337                     else
13338                     {
13339                         bDest->bbWeight = BB_ZERO_WEIGHT;
13340                         bDest->bbFlags |= BBF_RUN_RARELY;
13341                     }
13342                 }
13343             }
13344
13345             // Update the switch jump table
13346             *jmpTab = bNewDest;
13347
13348             // Maintain, if necessary, the set of unique targets of "block."
13349             UpdateSwitchTableTarget(block, bDest, bNewDest);
13350
13351             fgAddRefPred(bNewDest, block, fgRemoveRefPred(bDest, block));
13352
13353             // we optimized a Switch label - goto REPEAT_SWITCH to follow this new jump
13354             returnvalue = true;
13355
13356             goto REPEAT_SWITCH;
13357         }
13358     } while (++jmpTab, --jmpCnt);
13359
13360     GenTreeStmt* switchStmt = nullptr;
13361     LIR::Range*  blockRange = nullptr;
13362
13363     GenTree* switchTree;
13364     if (block->IsLIR())
13365     {
13366         blockRange = &LIR::AsRange(block);
13367         switchTree = blockRange->LastNode();
13368
13369         assert(switchTree->OperGet() == GT_SWITCH_TABLE);
13370     }
13371     else
13372     {
13373         switchStmt = block->lastStmt();
13374         switchTree = switchStmt->gtStmtExpr;
13375
13376         assert(switchTree->OperGet() == GT_SWITCH);
13377     }
13378
13379     noway_assert(switchTree->gtType == TYP_VOID);
13380
13381     // At this point all of the case jump targets have been updated such
13382     // that none of them go to block that is an empty unconditional block
13383     //
13384     jmpTab = block->bbJumpSwt->bbsDstTab;
13385     jmpCnt = block->bbJumpSwt->bbsCount;
13386     // Now check for two trivial switch jumps.
13387     //
13388     if (block->NumSucc(this) == 1)
13389     {
13390         // Use BBJ_ALWAYS for a switch with only a default clause, or with only one unique successor.
13391         BasicBlock* uniqueSucc = jmpTab[0];
13392
13393 #ifdef DEBUG
13394         if (verbose)
13395         {
13396             printf("\nRemoving a switch jump with a single target (BB%02u)\n", block->bbNum);
13397             printf("BEFORE:\n");
13398         }
13399 #endif // DEBUG
13400
13401         if (block->IsLIR())
13402         {
13403             bool               isClosed;
13404             unsigned           sideEffects;
13405             LIR::ReadOnlyRange switchTreeRange = blockRange->GetTreeRange(switchTree, &isClosed, &sideEffects);
13406
13407             // The switch tree should form a contiguous, side-effect free range by construction. See
13408             // Lowering::LowerSwitch for details.
13409             assert(isClosed);
13410             assert((sideEffects & GTF_ALL_EFFECT) == 0);
13411
13412             blockRange->Delete(this, block, std::move(switchTreeRange));
13413         }
13414         else
13415         {
13416             /* check for SIDE_EFFECTS */
13417             if (switchTree->gtFlags & GTF_SIDE_EFFECT)
13418             {
13419                 /* Extract the side effects from the conditional */
13420                 GenTreePtr sideEffList = nullptr;
13421
13422                 gtExtractSideEffList(switchTree, &sideEffList);
13423
13424                 if (sideEffList == nullptr)
13425                 {
13426                     goto NO_SWITCH_SIDE_EFFECT;
13427                 }
13428
13429                 noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
13430
13431 #ifdef DEBUG
13432                 if (verbose)
13433                 {
13434                     printf("\nSwitch expression has side effects! Extracting side effects...\n");
13435                     gtDispTree(switchTree);
13436                     printf("\n");
13437                     gtDispTree(sideEffList);
13438                     printf("\n");
13439                 }
13440 #endif // DEBUG
13441
13442                 /* Replace the conditional statement with the list of side effects */
13443                 noway_assert(sideEffList->gtOper != GT_STMT);
13444                 noway_assert(sideEffList->gtOper != GT_SWITCH);
13445
13446                 switchStmt->gtStmtExpr = sideEffList;
13447
13448                 if (fgStmtListThreaded)
13449                 {
13450                     /* Update the lclvar ref counts */
13451                     compCurBB = block;
13452                     fgUpdateRefCntForExtract(switchTree, sideEffList);
13453
13454                     /* Update ordering, costs, FP levels, etc. */
13455                     gtSetStmtInfo(switchStmt);
13456
13457                     /* Re-link the nodes for this statement */
13458                     fgSetStmtSeq(switchStmt);
13459                 }
13460             }
13461             else
13462             {
13463
13464             NO_SWITCH_SIDE_EFFECT:
13465
13466                 /* conditional has NO side effect - remove it */
13467                 fgRemoveStmt(block, switchStmt);
13468             }
13469         }
13470
13471         // Change the switch jump into a BBJ_ALWAYS
13472         block->bbJumpDest = block->bbJumpSwt->bbsDstTab[0];
13473         block->bbJumpKind = BBJ_ALWAYS;
13474         if (jmpCnt > 1)
13475         {
13476             for (unsigned i = 1; i < jmpCnt; ++i)
13477             {
13478                 (void)fgRemoveRefPred(jmpTab[i], block);
13479             }
13480         }
13481
13482         return true;
13483     }
13484     else if (block->bbJumpSwt->bbsCount == 2 && block->bbJumpSwt->bbsDstTab[1] == block->bbNext)
13485     {
13486         /* Use a BBJ_COND(switchVal==0) for a switch with only one
13487            significant clause besides the default clause, if the
13488            default clause is bbNext */
13489         GenTree* switchVal = switchTree->gtOp.gtOp1;
13490         noway_assert(genActualTypeIsIntOrI(switchVal->TypeGet()));
13491
13492         // If we are in LIR, remove the jump table from the block.
13493         if (block->IsLIR())
13494         {
13495             GenTree* jumpTable = switchTree->gtOp.gtOp2;
13496             assert(jumpTable->OperGet() == GT_JMPTABLE);
13497             blockRange->Remove(jumpTable);
13498         }
13499
13500         // Change the GT_SWITCH(switchVal) into GT_JTRUE(GT_EQ(switchVal==0)).
13501         // Also mark the node as GTF_DONT_CSE as further down JIT is not capable of handling it.
13502         // For example CSE could determine that the expression rooted at GT_EQ is a candidate cse and
13503         // replace it with a COMMA node.  In such a case we will end up with GT_JTRUE node pointing to
13504         // a COMMA node which results in noway asserts in fgMorphSmpOp(), optAssertionGen() and rpPredictTreeRegUse().
13505         // For the same reason fgMorphSmpOp() marks GT_JTRUE nodes with RELOP children as GTF_DONT_CSE.
13506         CLANG_FORMAT_COMMENT_ANCHOR;
13507
13508 #ifdef DEBUG
13509         if (verbose)
13510         {
13511             printf("\nConverting a switch (BB%02u) with only one significant clause besides a default target to a "
13512                    "conditional branch\n",
13513                    block->bbNum);
13514         }
13515 #endif // DEBUG
13516
13517         switchTree->ChangeOper(GT_JTRUE);
13518         GenTree* zeroConstNode = gtNewZeroConNode(genActualType(switchVal->TypeGet()));
13519         GenTree* condNode      = gtNewOperNode(GT_EQ, TYP_INT, switchVal, zeroConstNode);
13520         switchTree->gtOp.gtOp1 = condNode;
13521         switchTree->gtOp.gtOp1->gtFlags |= (GTF_RELOP_JMP_USED | GTF_DONT_CSE);
13522
13523         if (block->IsLIR())
13524         {
13525             blockRange->InsertAfter(switchVal, zeroConstNode, condNode);
13526         }
13527         else
13528         {
13529             // Re-link the nodes for this statement.
13530             fgSetStmtSeq(switchStmt);
13531         }
13532
13533         block->bbJumpDest = block->bbJumpSwt->bbsDstTab[0];
13534         block->bbJumpKind = BBJ_COND;
13535
13536         return true;
13537     }
13538     return returnvalue;
13539 }
13540
13541 // fgBlockEndFavorsTailDuplication:
13542 //     Heuristic function that returns true if this block ends in a statement that looks favorable
13543 //     for tail-duplicating its successor (such as assigning a constant to a local).
13544 //  Args:
13545 //      block: BasicBlock we are considering duplicating the successor of
13546 //  Returns:
13547 //      true if it seems like a good idea
13548 //
13549 bool Compiler::fgBlockEndFavorsTailDuplication(BasicBlock* block)
13550 {
13551     if (block->isRunRarely())
13552     {
13553         return false;
13554     }
13555
13556     if (!block->lastStmt())
13557     {
13558         return false;
13559     }
13560     else
13561     {
13562         // Tail duplication tends to pay off when the last statement
13563         // is an assignment of a constant, arraylength, or a relop.
13564         // This is because these statements produce information about values
13565         // that would otherwise be lost at the upcoming merge point.
13566
13567         GenTreeStmt* lastStmt = block->lastStmt();
13568         GenTree*     tree     = lastStmt->gtStmtExpr;
13569         if (tree->gtOper != GT_ASG)
13570         {
13571             return false;
13572         }
13573
13574         GenTree* op2 = tree->gtOp.gtOp2;
13575         if (op2->gtOper != GT_ARR_LENGTH && !op2->OperIsConst() && ((op2->OperKind() & GTK_RELOP) == 0))
13576         {
13577             return false;
13578         }
13579     }
13580     return true;
13581 }
13582
13583 // fgBlockIsGoodTailDuplicationCandidate:
13584 //     Heuristic function that examines a block (presumably one that is a merge point) to determine
13585 //     if it should be duplicated.
13586 // args:
13587 //     target - the tail block (candidate for duplication)
13588 // returns:
13589 //     true if this block seems like a good candidate for duplication
13590 //
13591 bool Compiler::fgBlockIsGoodTailDuplicationCandidate(BasicBlock* target)
13592 {
13593     GenTreeStmt* stmt = target->FirstNonPhiDef();
13594
13595     // Here we are looking for blocks with a single statement feeding a conditional branch.
13596     // These blocks are small, and when duplicated onto the tail of blocks that end in
13597     // assignments, there is a high probability of the branch completely going away.
13598
13599     // This is by no means the only kind of tail that it is beneficial to duplicate,
13600     // just the only one we recognize for now.
13601
13602     if (stmt != target->lastStmt())
13603     {
13604         return false;
13605     }
13606
13607     if (target->bbJumpKind != BBJ_COND)
13608     {
13609         return false;
13610     }
13611
13612     GenTree* tree = stmt->gtStmtExpr;
13613
13614     if (tree->gtOper != GT_JTRUE)
13615     {
13616         return false;
13617     }
13618
13619     // must be some kind of relational operator
13620     GenTree* cond = tree->gtOp.gtOp1;
13621     if (!(cond->OperKind() & GTK_RELOP))
13622     {
13623         return false;
13624     }
13625
13626     // op1 must be some combinations of casts of local or constant
13627     GenTree* op1 = cond->gtOp.gtOp1;
13628     while (op1->gtOper == GT_CAST)
13629     {
13630         op1 = op1->gtOp.gtOp1;
13631     }
13632     if (!op1->IsLocal() && !op1->OperIsConst())
13633     {
13634         return false;
13635     }
13636
13637     // op2 must be some combinations of casts of local or constant
13638     GenTree* op2 = cond->gtOp.gtOp2;
13639     while (op2->gtOper == GT_CAST)
13640     {
13641         op2 = op2->gtOp.gtOp1;
13642     }
13643     if (!op2->IsLocal() && !op2->OperIsConst())
13644     {
13645         return false;
13646     }
13647
13648     return true;
13649 }
13650
13651 // fgOptimizeUncondBranchToSimpleCond:
13652 //    For a block which has an unconditional branch, look to see if its target block
13653 //    is a good candidate for tail duplication, and if so do that duplication.
13654 //
13655 // Args:
13656 //    block  - block with uncond branch
13657 //    target - block which is target of first block
13658 //
13659 // returns: true if changes were made
13660
13661 bool Compiler::fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock* target)
13662 {
13663     assert(block->bbJumpKind == BBJ_ALWAYS);
13664     assert(block->bbJumpDest == target);
13665
13666     // TODO-Review: OK if they are in the same region?
13667     if (compHndBBtabCount > 0)
13668     {
13669         return false;
13670     }
13671
13672     if (!fgBlockIsGoodTailDuplicationCandidate(target))
13673     {
13674         return false;
13675     }
13676
13677     if (!fgBlockEndFavorsTailDuplication(block))
13678     {
13679         return false;
13680     }
13681
13682     // NOTE: we do not currently hit this assert because this function is only called when
13683     // `fgUpdateFlowGraph` has been called with `doTailDuplication` set to true, and the
13684     // backend always calls `fgUpdateFlowGraph` with `doTailDuplication` set to false.
13685     assert(!block->IsLIR());
13686
13687     GenTreeStmt* stmt = target->FirstNonPhiDef();
13688     assert(stmt == target->lastStmt());
13689
13690     // Duplicate the target block at the end of this block
13691
13692     GenTree* cloned = gtCloneExpr(stmt->gtStmtExpr);
13693     noway_assert(cloned);
13694     GenTree* jmpStmt = gtNewStmt(cloned);
13695
13696     block->bbJumpKind = BBJ_COND;
13697     block->bbJumpDest = target->bbJumpDest;
13698     fgAddRefPred(block->bbJumpDest, block);
13699     fgRemoveRefPred(target, block);
13700
13701     // add an unconditional block after this block to jump to the target block's fallthrough block
13702
13703     BasicBlock* next = fgNewBBafter(BBJ_ALWAYS, block, true);
13704     next->bbFlags    = block->bbFlags | BBF_INTERNAL;
13705     next->bbFlags &= ~(BBF_TRY_BEG | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1 | BBF_HAS_LABEL | BBF_JMP_TARGET |
13706                        BBF_FUNCLET_BEG | BBF_LOOP_PREHEADER | BBF_KEEP_BBJ_ALWAYS);
13707
13708     next->bbJumpDest = target->bbNext;
13709     target->bbNext->bbFlags |= BBF_JMP_TARGET;
13710     fgAddRefPred(next, block);
13711     fgAddRefPred(next->bbJumpDest, next);
13712
13713 #ifdef DEBUG
13714     if (verbose)
13715     {
13716         printf("fgOptimizeUncondBranchToSimpleCond(from BB%02u to cond BB%02u), created new uncond BB%02u\n",
13717                block->bbNum, target->bbNum, next->bbNum);
13718     }
13719 #endif // DEBUG
13720
13721     if (fgStmtListThreaded)
13722     {
13723         gtSetStmtInfo(jmpStmt);
13724     }
13725
13726     fgInsertStmtAtEnd(block, jmpStmt);
13727
13728     return true;
13729 }
13730
13731 // fgOptimizeBranchToNext:
13732 //    Optimize a block which has a branch to the following block
13733 // Args:
13734 //    block - block with a branch
13735 //    bNext - block which is both next and the target of the first block
13736 //    bPrev - block which is prior to the first block
13737 //
13738 // returns: true if changes were made
13739 //
13740 bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev)
13741 {
13742     assert(block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS);
13743     assert(block->bbJumpDest == bNext);
13744     assert(block->bbNext = bNext);
13745     assert(block->bbPrev == bPrev);
13746
13747     if (block->bbJumpKind == BBJ_ALWAYS)
13748     {
13749         // We can't remove it if it is a branch from hot => cold
13750         if (!fgInDifferentRegions(block, bNext))
13751         {
13752             // We can't remove if it is marked as BBF_KEEP_BBJ_ALWAYS
13753             if (!(block->bbFlags & BBF_KEEP_BBJ_ALWAYS))
13754             {
13755                 // We can't remove if the BBJ_ALWAYS is part of a BBJ_CALLFINALLY pair
13756                 if ((bPrev == nullptr) || !bPrev->isBBCallAlwaysPair())
13757                 {
13758                     /* the unconditional jump is to the next BB  */
13759                     block->bbJumpKind = BBJ_NONE;
13760                     block->bbFlags &= ~BBF_NEEDS_GCPOLL;
13761 #ifdef DEBUG
13762                     if (verbose)
13763                     {
13764                         printf("\nRemoving unconditional jump to next block (BB%02u -> BB%02u) (converted BB%02u to "
13765                                "fall-through)\n",
13766                                block->bbNum, bNext->bbNum, block->bbNum);
13767                     }
13768 #endif // DEBUG
13769                     return true;
13770                 }
13771             }
13772         }
13773     }
13774     else
13775     {
13776         /* remove the conditional statement at the end of block */
13777         noway_assert(block->bbJumpKind == BBJ_COND);
13778         noway_assert(block->bbTreeList);
13779
13780 #ifdef DEBUG
13781         if (verbose)
13782         {
13783             printf("\nRemoving conditional jump to next block (BB%02u -> BB%02u)\n", block->bbNum, bNext->bbNum);
13784         }
13785 #endif // DEBUG
13786
13787         if (block->IsLIR())
13788         {
13789             LIR::Range& blockRange = LIR::AsRange(block);
13790             GenTree*    jmp        = blockRange.LastNode();
13791             assert(jmp->OperGet() == GT_JTRUE);
13792
13793             bool               isClosed;
13794             unsigned           sideEffects;
13795             LIR::ReadOnlyRange jmpRange = blockRange.GetTreeRange(jmp, &isClosed, &sideEffects);
13796
13797             // TODO-LIR: this should really be checking GTF_ALL_EFFECT, but that produces unacceptable
13798             //            diffs compared to the existing backend.
13799             if (isClosed && ((sideEffects & GTF_SIDE_EFFECT) == 0))
13800             {
13801                 // If the jump and its operands form a contiguous, side-effect-free range,
13802                 // remove them.
13803                 blockRange.Delete(this, block, std::move(jmpRange));
13804             }
13805             else
13806             {
13807                 // Otherwise, just remove the jump node itself.
13808                 blockRange.Remove(jmp);
13809             }
13810         }
13811         else
13812         {
13813             GenTreeStmt* cond = block->lastStmt();
13814             noway_assert(cond->gtStmtExpr->gtOper == GT_JTRUE);
13815
13816             /* check for SIDE_EFFECTS */
13817             if (cond->gtStmtExpr->gtFlags & GTF_SIDE_EFFECT)
13818             {
13819                 /* Extract the side effects from the conditional */
13820                 GenTreePtr sideEffList = nullptr;
13821
13822                 gtExtractSideEffList(cond->gtStmtExpr, &sideEffList);
13823
13824                 if (sideEffList == nullptr)
13825                 {
13826                     compCurBB = block;
13827                     fgRemoveStmt(block, cond);
13828                 }
13829                 else
13830                 {
13831                     noway_assert(sideEffList->gtFlags & GTF_SIDE_EFFECT);
13832 #ifdef DEBUG
13833                     if (verbose)
13834                     {
13835                         printf("\nConditional has side effects! Extracting side effects...\n");
13836                         gtDispTree(cond);
13837                         printf("\n");
13838                         gtDispTree(sideEffList);
13839                         printf("\n");
13840                     }
13841 #endif // DEBUG
13842
13843                     /* Replace the conditional statement with the list of side effects */
13844                     noway_assert(sideEffList->gtOper != GT_STMT);
13845                     noway_assert(sideEffList->gtOper != GT_JTRUE);
13846
13847                     cond->gtStmtExpr = sideEffList;
13848
13849                     if (fgStmtListThreaded)
13850                     {
13851                         /* Update the lclvar ref counts */
13852                         compCurBB = block;
13853                         fgUpdateRefCntForExtract(cond->gtStmtExpr, sideEffList);
13854
13855                         /* Update ordering, costs, FP levels, etc. */
13856                         gtSetStmtInfo(cond);
13857
13858                         /* Re-link the nodes for this statement */
13859                         fgSetStmtSeq(cond);
13860                     }
13861                 }
13862             }
13863             else
13864             {
13865                 compCurBB = block;
13866                 /* conditional has NO side effect - remove it */
13867                 fgRemoveStmt(block, cond);
13868             }
13869         }
13870
13871         /* Conditional is gone - simply fall into the next block */
13872
13873         block->bbJumpKind = BBJ_NONE;
13874         block->bbFlags &= ~BBF_NEEDS_GCPOLL;
13875
13876         /* Update bbRefs and bbNum - Conditional predecessors to the same
13877          * block are counted twice so we have to remove one of them */
13878
13879         noway_assert(bNext->countOfInEdges() > 1);
13880         fgRemoveRefPred(bNext, block);
13881
13882         return true;
13883     }
13884     return false;
13885 }
13886
13887 /*****************************************************************************
13888  *
13889  *  Function called to optimize an unconditional branch that branches
13890  *  to a conditional branch.
13891  *  Currently we require that the conditional branch jump back to the
13892  *  block that follows the unconditional branch.
13893  *
13894  *  We can improve the code execution and layout by concatenating a copy
13895  *  of the conditional branch block at the end of the conditional branch
13896  *  and reversing the sense of the branch.
13897  *
13898  *  This is only done when the amount of code to be copied is smaller than
13899  *  our calculated threshold in maxDupCostSz.
13900  *
13901  */
13902
13903 bool Compiler::fgOptimizeBranch(BasicBlock* bJump)
13904 {
13905     if (opts.MinOpts())
13906     {
13907         return false;
13908     }
13909
13910     if (bJump->bbJumpKind != BBJ_ALWAYS)
13911     {
13912         return false;
13913     }
13914
13915     if (bJump->bbFlags & BBF_KEEP_BBJ_ALWAYS)
13916     {
13917         return false;
13918     }
13919
13920     // Don't hoist a conditional branch into the scratch block; we'd prefer it stay
13921     // either BBJ_NONE or BBJ_ALWAYS.
13922     if (fgBBisScratch(bJump))
13923     {
13924         return false;
13925     }
13926
13927     BasicBlock* bDest = bJump->bbJumpDest;
13928
13929     if (bDest->bbJumpKind != BBJ_COND)
13930     {
13931         return false;
13932     }
13933
13934     if (bDest->bbJumpDest != bJump->bbNext)
13935     {
13936         return false;
13937     }
13938
13939     // 'bJump' must be in the same try region as the condition, since we're going to insert
13940     // a duplicated condition in 'bJump', and the condition might include exception throwing code.
13941     if (!BasicBlock::sameTryRegion(bJump, bDest))
13942     {
13943         return false;
13944     }
13945
13946     // do not jump into another try region
13947     BasicBlock* bDestNext = bDest->bbNext;
13948     if (bDestNext->hasTryIndex() && !BasicBlock::sameTryRegion(bJump, bDestNext))
13949     {
13950         return false;
13951     }
13952
13953     // This function is only called by fgReorderBlocks, which we do not run in the backend.
13954     // If we wanted to run block reordering in the backend, we would need to be able to
13955     // calculate cost information for LIR on a per-node basis in order for this function
13956     // to work.
13957     assert(!bJump->IsLIR());
13958     assert(!bDest->IsLIR());
13959
13960     GenTreeStmt* stmt;
13961     unsigned     estDupCostSz = 0;
13962     for (stmt = bDest->firstStmt(); stmt; stmt = stmt->gtNextStmt)
13963     {
13964         GenTreePtr expr = stmt->gtStmtExpr;
13965
13966         /* We call gtPrepareCost to measure the cost of duplicating this tree */
13967         gtPrepareCost(expr);
13968
13969         estDupCostSz += expr->gtCostSz;
13970     }
13971
13972     bool                 allProfileWeightsAreValid = false;
13973     BasicBlock::weight_t weightJump                = bJump->bbWeight;
13974     BasicBlock::weight_t weightDest                = bDest->bbWeight;
13975     BasicBlock::weight_t weightNext                = bJump->bbNext->bbWeight;
13976     bool                 rareJump                  = bJump->isRunRarely();
13977     bool                 rareDest                  = bDest->isRunRarely();
13978     bool                 rareNext                  = bJump->bbNext->isRunRarely();
13979
13980     // If we have profile data then we calculate the number of time
13981     // the loop will iterate into loopIterations
13982     if (fgIsUsingProfileWeights())
13983     {
13984         // Only rely upon the profile weight when all three of these blocks
13985         // have either good profile weights or are rarelyRun
13986         //
13987         if ((bJump->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)) &&
13988             (bDest->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)) &&
13989             (bJump->bbNext->bbFlags & (BBF_PROF_WEIGHT | BBF_RUN_RARELY)))
13990         {
13991             allProfileWeightsAreValid = true;
13992
13993             if ((weightJump * 100) < weightDest)
13994             {
13995                 rareJump = true;
13996             }
13997
13998             if ((weightNext * 100) < weightDest)
13999             {
14000                 rareNext = true;
14001             }
14002
14003             if (((weightDest * 100) < weightJump) && ((weightDest * 100) < weightNext))
14004             {
14005                 rareDest = true;
14006             }
14007         }
14008     }
14009
14010     unsigned maxDupCostSz = 6;
14011
14012     //
14013     // Branches between the hot and rarely run regions
14014     // should be minimized.  So we allow a larger size
14015     //
14016     if (rareDest != rareJump)
14017     {
14018         maxDupCostSz += 6;
14019     }
14020
14021     if (rareDest != rareNext)
14022     {
14023         maxDupCostSz += 6;
14024     }
14025
14026     //
14027     // We we are ngen-ing:
14028     // If the uncondional branch is a rarely run block then
14029     // we are willing to have more code expansion since we
14030     // won't be running code from this page
14031     //
14032     if (opts.eeFlags & CORJIT_FLG_PREJIT)
14033     {
14034         if (rareJump)
14035         {
14036             maxDupCostSz *= 2;
14037         }
14038     }
14039
14040     // If the compare has too high cost then we don't want to dup
14041
14042     bool costIsTooHigh = (estDupCostSz > maxDupCostSz);
14043
14044 #ifdef DEBUG
14045     if (verbose)
14046     {
14047         printf("\nDuplication of the conditional block BB%02u (always branch from BB%02u) %s, because the cost of "
14048                "duplication (%i) is %s than %i,"
14049                " validProfileWeights = %s\n",
14050                bDest->bbNum, bJump->bbNum, costIsTooHigh ? "not done" : "performed", estDupCostSz,
14051                costIsTooHigh ? "greater" : "less or equal", maxDupCostSz, allProfileWeightsAreValid ? "true" : "false");
14052     }
14053 #endif // DEBUG
14054
14055     if (costIsTooHigh)
14056     {
14057         return false;
14058     }
14059
14060     /* Looks good - duplicate the conditional block */
14061
14062     GenTree* newStmtList     = nullptr; // new stmt list to be added to bJump
14063     GenTree* newStmtLast     = nullptr;
14064     bool     cloneExprFailed = false;
14065
14066     /* Visit all the statements in bDest */
14067
14068     for (GenTree* curStmt = bDest->bbTreeList; curStmt; curStmt = curStmt->gtNext)
14069     {
14070         /* Clone/substitute the expression */
14071
14072         stmt = gtCloneExpr(curStmt)->AsStmt();
14073
14074         // cloneExpr doesn't handle everything
14075
14076         if (stmt == nullptr)
14077         {
14078             cloneExprFailed = true;
14079             break;
14080         }
14081
14082         /* Append the expression to our list */
14083
14084         if (newStmtList != nullptr)
14085         {
14086             newStmtLast->gtNext = stmt;
14087         }
14088         else
14089         {
14090             newStmtList = stmt;
14091         }
14092
14093         stmt->gtPrev = newStmtLast;
14094         newStmtLast  = stmt;
14095     }
14096
14097     if (cloneExprFailed)
14098     {
14099         return false;
14100     }
14101
14102     noway_assert(newStmtLast != nullptr);
14103     noway_assert(stmt != nullptr);
14104     noway_assert(stmt->gtOper == GT_STMT);
14105
14106     if ((newStmtLast == nullptr) || (stmt == nullptr) || (stmt->gtOper != GT_STMT))
14107     {
14108         return false;
14109     }
14110
14111     /* Get to the condition node from the statement tree */
14112
14113     GenTreePtr condTree = stmt->gtStmtExpr;
14114     noway_assert(condTree->gtOper == GT_JTRUE);
14115
14116     if (condTree->gtOper != GT_JTRUE)
14117     {
14118         return false;
14119     }
14120
14121     //
14122     // Set condTree to the operand to the GT_JTRUE
14123     //
14124     condTree = condTree->gtOp.gtOp1;
14125
14126     //
14127     // This condTree has to be a RelOp comparison
14128     //
14129     if (condTree->OperIsCompare() == false)
14130     {
14131         return false;
14132     }
14133
14134     // Bump up the ref-counts of any variables in 'stmt'
14135     fgUpdateRefCntForClone(bJump, stmt->gtStmtExpr);
14136
14137     //
14138     // Find the last statement in the bJump block
14139     //
14140     GenTreeStmt* lastStmt = nullptr;
14141     for (stmt = bJump->firstStmt(); stmt; stmt = stmt->gtNextStmt)
14142     {
14143         lastStmt = stmt;
14144     }
14145     stmt = bJump->firstStmt();
14146
14147     /* Join the two linked lists */
14148     newStmtLast->gtNext = nullptr;
14149
14150     if (lastStmt != nullptr)
14151     {
14152         stmt->gtPrev        = newStmtLast;
14153         lastStmt->gtNext    = newStmtList;
14154         newStmtList->gtPrev = lastStmt;
14155     }
14156     else
14157     {
14158         bJump->bbTreeList   = newStmtList;
14159         newStmtList->gtPrev = newStmtLast;
14160     }
14161
14162     //
14163     // Reverse the sense of the compare
14164     //
14165     gtReverseCond(condTree);
14166
14167     bJump->bbJumpKind = BBJ_COND;
14168     bJump->bbJumpDest = bDest->bbNext;
14169
14170     /* Mark the jump dest block as being a jump target */
14171     bJump->bbJumpDest->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
14172
14173     // We need to update the following flags of the bJump block if they were set in the bbJumpDest block
14174     bJump->bbFlags |= (bJump->bbJumpDest->bbFlags
14175                     & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_VTABREF));
14176
14177     /* Update bbRefs and bbPreds */
14178
14179     // bJump now falls through into the next block
14180     //
14181     fgAddRefPred(bJump->bbNext, bJump);
14182
14183     // bJump no longer jumps to bDest
14184     //
14185     fgRemoveRefPred(bDest, bJump);
14186
14187     // bJump now jumps to bDest->bbNext
14188     //
14189     fgAddRefPred(bDest->bbNext, bJump);
14190
14191     if (weightJump > 0)
14192     {
14193         if (allProfileWeightsAreValid)
14194         {
14195             if (weightDest > weightJump)
14196             {
14197                 bDest->bbWeight = (weightDest - weightJump);
14198             }
14199             else if (!bDest->isRunRarely())
14200             {
14201                 bDest->bbWeight = BB_UNITY_WEIGHT;
14202             }
14203         }
14204         else
14205         {
14206             BasicBlock::weight_t newWeightDest    = 0;
14207             BasicBlock::weight_t unloopWeightDest = 0;
14208
14209             if (weightDest > weightJump)
14210             {
14211                 newWeightDest = (weightDest - weightJump);
14212             }
14213             if (weightDest >= (BB_LOOP_WEIGHT * BB_UNITY_WEIGHT) / 2)
14214             {
14215                 newWeightDest = (weightDest * 2) / (BB_LOOP_WEIGHT * BB_UNITY_WEIGHT);
14216             }
14217             if ((newWeightDest > 0) || (unloopWeightDest > 0))
14218             {
14219                 bDest->bbWeight = Max(newWeightDest, unloopWeightDest);
14220             }
14221         }
14222     }
14223
14224 #if DEBUG
14225     if (verbose)
14226     {
14227         printf("\nAfter this change in fgOptimizeBranch");
14228         fgDispBasicBlocks(verboseTrees);
14229         printf("\n");
14230     }
14231 #endif // DEBUG
14232
14233     return true;
14234 }
14235
14236 /*****************************************************************************
14237  *
14238  *  Function called to optimize switch statements
14239  */
14240
14241 bool Compiler::fgOptimizeSwitchJumps()
14242 {
14243     bool result = false; // Our return value
14244
14245 #if 0
14246     // TODO-CQ: Add switch jump optimizations?
14247     if (!fgHasSwitch)
14248         return false;
14249
14250     if (!fgHaveValidEdgeWeights)
14251         return false;
14252
14253     for (BasicBlock* bSrc = fgFirstBB; bSrc != NULL; bSrc = bSrc->bbNext)
14254     {
14255         if (bSrc->bbJumpKind == BBJ_SWITCH)
14256         {
14257             unsigned        jumpCnt; jumpCnt = bSrc->bbJumpSwt->bbsCount;
14258             BasicBlock**    jumpTab; jumpTab = bSrc->bbJumpSwt->bbsDstTab;
14259
14260             do
14261             {
14262                 BasicBlock*   bDst       = *jumpTab;
14263                 flowList*     edgeToDst  = fgGetPredForBlock(bDst, bSrc);
14264                 double        outRatio   = (double) edgeToDst->flEdgeWeightMin  / (double) bSrc->bbWeight;
14265
14266                 if (outRatio >= 0.60)
14267                 {
14268                     // straighten switch here...
14269                 }
14270             }
14271             while (++jumpTab, --jumpCnt);
14272         }
14273     }
14274 #endif
14275
14276     return result;
14277 }
14278
14279 #ifdef _PREFAST_
14280 #pragma warning(push)
14281 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
14282 #endif
14283 /*****************************************************************************
14284  *
14285  *  Function called to reorder the flowgraph of BasicBlocks such that any
14286  *  rarely run blocks are placed at the end of the block list.
14287  *  If we have profile information we also use that information to reverse
14288  *  all conditional jumps that would benefit.
14289  */
14290
14291 void Compiler::fgReorderBlocks()
14292 {
14293     noway_assert(opts.compDbgCode == false);
14294
14295 #if FEATURE_EH_FUNCLETS
14296     assert(fgFuncletsCreated);
14297 #endif // FEATURE_EH_FUNCLETS
14298
14299     // We can't relocate anything if we only have one block
14300     if (fgFirstBB->bbNext == nullptr)
14301     {
14302         return;
14303     }
14304
14305     bool newRarelyRun      = false;
14306     bool movedBlocks       = false;
14307     bool optimizedSwitches = false;
14308
14309     // First let us expand the set of run rarely blocks
14310     newRarelyRun |= fgExpandRarelyRunBlocks();
14311
14312 #if !FEATURE_EH_FUNCLETS
14313     movedBlocks |= fgRelocateEHRegions();
14314 #endif // !FEATURE_EH_FUNCLETS
14315
14316     //
14317     // If we are using profile weights we can change some
14318     // switch jumps into conditional test and jump
14319     //
14320     if (fgIsUsingProfileWeights())
14321     {
14322         //
14323         // Note that this is currently not yet implemented
14324         //
14325         optimizedSwitches = fgOptimizeSwitchJumps();
14326         if (optimizedSwitches)
14327         {
14328             fgUpdateFlowGraph();
14329         }
14330     }
14331
14332 #ifdef DEBUG
14333     if (verbose)
14334     {
14335         printf("*************** In fgReorderBlocks()\n");
14336
14337         printf("\nInitial BasicBlocks");
14338         fgDispBasicBlocks(verboseTrees);
14339         printf("\n");
14340     }
14341 #endif // DEBUG
14342
14343     BasicBlock* bNext;
14344     BasicBlock* bPrev;
14345     BasicBlock* block;
14346     unsigned    XTnum;
14347     EHblkDsc*   HBtab;
14348
14349     // Iterate over every block, remembering our previous block in bPrev
14350     for (bPrev = fgFirstBB, block = bPrev->bbNext; block != nullptr; bPrev = block, block = block->bbNext)
14351     {
14352         //
14353         // Consider relocating the rarely run blocks such that they are at the end of the method.
14354         // We also consider reversing conditional branches so that they become a not taken forwards branch.
14355         //
14356
14357         // If block is marked with a BBF_KEEP_BBJ_ALWAYS flag then we don't move the block
14358         if ((block->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0)
14359         {
14360             continue;
14361         }
14362
14363         // Finally and handlers blocks are to be kept contiguous.
14364         // TODO-CQ: Allow reordering within the handler region
14365         if (block->hasHndIndex() == true)
14366         {
14367             continue;
14368         }
14369
14370         bool        reorderBlock   = true; // This is set to false if we decide not to reorder 'block'
14371         bool        isRare         = block->isRunRarely();
14372         BasicBlock* bDest          = nullptr;
14373         bool        forwardBranch  = false;
14374         bool        backwardBranch = false;
14375
14376         // Setup bDest
14377         if ((bPrev->bbJumpKind == BBJ_COND) || (bPrev->bbJumpKind == BBJ_ALWAYS))
14378         {
14379             bDest          = bPrev->bbJumpDest;
14380             forwardBranch  = fgIsForwardBranch(bPrev);
14381             backwardBranch = !forwardBranch;
14382         }
14383
14384         // We will look for bPrev as a non rarely run block followed by block as a rarely run block
14385         //
14386         if (bPrev->isRunRarely())
14387         {
14388             reorderBlock = false;
14389         }
14390
14391         // If the weights of the bPrev, block and bDest were all obtained from a profile run
14392         // then we can use them to decide if it is useful to reverse this conditional branch
14393
14394         BasicBlock::weight_t profHotWeight = -1;
14395
14396         if ((bPrev->bbFlags & BBF_PROF_WEIGHT) && (block->bbFlags & BBF_PROF_WEIGHT) &&
14397             ((bDest == nullptr) || (bDest->bbFlags & BBF_PROF_WEIGHT)))
14398         {
14399             //
14400             // All blocks have profile information
14401             //
14402             if (forwardBranch)
14403             {
14404                 if (bPrev->bbJumpKind == BBJ_ALWAYS)
14405                 {
14406                     // We can pull up the blocks that the unconditional jump branches to
14407                     // if the weight of bDest is greater or equal to the weight of block
14408                     // also the weight of bDest can't be zero.
14409                     //
14410                     if ((bDest->bbWeight < block->bbWeight) || (bDest->bbWeight == 0))
14411                     {
14412                         reorderBlock = false;
14413                     }
14414                     else
14415                     {
14416                         //
14417                         // If this remains true then we will try to pull up bDest to succeed bPrev
14418                         //
14419                         bool moveDestUp = true;
14420
14421                         if (fgHaveValidEdgeWeights)
14422                         {
14423                             //
14424                             // The edge bPrev -> bDest must have a higher minimum weight
14425                             // than every other edge into bDest
14426                             //
14427                             flowList* edgeFromPrev = fgGetPredForBlock(bDest, bPrev);
14428                             noway_assert(edgeFromPrev != nullptr);
14429
14430                             // Examine all of the other edges into bDest
14431                             for (flowList* edge = bDest->bbPreds; edge != nullptr; edge = edge->flNext)
14432                             {
14433                                 if (edge != edgeFromPrev)
14434                                 {
14435                                     if (edge->flEdgeWeightMax >= edgeFromPrev->flEdgeWeightMin)
14436                                     {
14437                                         moveDestUp = false;
14438                                         break;
14439                                     }
14440                                 }
14441                             }
14442                         }
14443                         else
14444                         {
14445                             //
14446                             // The block bPrev must have a higher weight
14447                             // than every other block that goes into bDest
14448                             //
14449
14450                             // Examine all of the other edges into bDest
14451                             for (flowList* edge = bDest->bbPreds; edge != nullptr; edge = edge->flNext)
14452                             {
14453                                 BasicBlock* bTemp = edge->flBlock;
14454
14455                                 if ((bTemp != bPrev) && (bTemp->bbWeight >= bPrev->bbWeight))
14456                                 {
14457                                     moveDestUp = false;
14458                                     break;
14459                                 }
14460                             }
14461                         }
14462
14463                         // Are we still good to move bDest up to bPrev?
14464                         if (moveDestUp)
14465                         {
14466                             //
14467                             // We will consider all blocks that have less weight than profHotWeight to be
14468                             // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest
14469                             //
14470                             profHotWeight = bDest->bbWeight - 1;
14471                         }
14472                         else
14473                         {
14474                             if (block->isRunRarely())
14475                             {
14476                                 // We will move any rarely run blocks blocks
14477                                 profHotWeight = 0;
14478                             }
14479                             else
14480                             {
14481                                 // We will move all blocks that have a weight less or equal to our fall through block
14482                                 profHotWeight = block->bbWeight + 1;
14483                             }
14484                             // But we won't try to connect with bDest
14485                             bDest = nullptr;
14486                         }
14487                     }
14488                 }
14489                 else // (bPrev->bbJumpKind == BBJ_COND)
14490                 {
14491                     noway_assert(bPrev->bbJumpKind == BBJ_COND);
14492                     //
14493                     // We will reverse branch if the taken-jump to bDest ratio (i.e. 'takenRatio')
14494                     // is more than 51%
14495                     //
14496                     // We will setup profHotWeight to be maximum bbWeight that a block
14497                     // could have for us not to want to reverse the conditional branch
14498                     //
14499                     // We will consider all blocks that have less weight than profHotWeight to be
14500                     // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest
14501                     //
14502                     if (fgHaveValidEdgeWeights)
14503                     {
14504                         // We have valid edge weights, however even with valid edge weights
14505                         // we may have a minimum and maximum range for each edges value
14506                         //
14507                         // We will check that the min weight of the bPrev to bDest edge
14508                         //  is more than twice the max weight of the bPrev to block edge.
14509                         //
14510                         //                  bPrev -->   [BB04, weight 31]
14511                         //                                     |         \
14512                         //          edgeToBlock -------------> O          \
14513                         //          [min=8,max=10]             V           \
14514                         //                  block -->   [BB05, weight 10]   \
14515                         //                                                   \
14516                         //          edgeToDest ----------------------------> O
14517                         //          [min=21,max=23]                          |
14518                         //                                                   V
14519                         //                  bDest --------------->   [BB08, weight 21]
14520                         //
14521                         flowList* edgeToDest  = fgGetPredForBlock(bDest, bPrev);
14522                         flowList* edgeToBlock = fgGetPredForBlock(block, bPrev);
14523                         noway_assert(edgeToDest != nullptr);
14524                         noway_assert(edgeToBlock != nullptr);
14525                         //
14526                         // Calculate the taken ratio
14527                         //   A takenRation of 0.10 means taken 10% of the time, not taken 90% of the time
14528                         //   A takenRation of 0.50 means taken 50% of the time, not taken 50% of the time
14529                         //   A takenRation of 0.90 means taken 90% of the time, not taken 10% of the time
14530                         //
14531                         double takenCount =
14532                             ((double)edgeToDest->flEdgeWeightMin + (double)edgeToDest->flEdgeWeightMax) / 2.0;
14533                         double notTakenCount =
14534                             ((double)edgeToBlock->flEdgeWeightMin + (double)edgeToBlock->flEdgeWeightMax) / 2.0;
14535                         double totalCount = takenCount + notTakenCount;
14536                         double takenRatio = takenCount / totalCount;
14537
14538                         // If the takenRatio is greater or equal to 51% then we will reverse the branch
14539                         if (takenRatio < 0.51)
14540                         {
14541                             reorderBlock = false;
14542                         }
14543                         else
14544                         {
14545                             // set profHotWeight
14546                             profHotWeight = (edgeToBlock->flEdgeWeightMin + edgeToBlock->flEdgeWeightMax) / 2 - 1;
14547                         }
14548                     }
14549                     else
14550                     {
14551                         // We don't have valid edge weight so we will be more conservative
14552                         // We could have bPrev, block or bDest as part of a loop and thus have extra weight
14553                         //
14554                         // We will do two checks:
14555                         //   1. Check that the weight of bDest is at least two times more than block
14556                         //   2. Check that the weight of bPrev is at least three times more than block
14557                         //
14558                         //                  bPrev -->   [BB04, weight 31]
14559                         //                                     |         \
14560                         //                                     V          \
14561                         //                  block -->   [BB05, weight 10]  \
14562                         //                                                  \
14563                         //                                                  |
14564                         //                                                  V
14565                         //                  bDest --------------->   [BB08, weight 21]
14566                         //
14567                         //  For this case weightDest is calculated as (21+1)/2  or 11
14568                         //            and weightPrev is calculated as (31+2)/3  also 11
14569                         //
14570                         //  Generally both weightDest and weightPrev should calculate
14571                         //  the same value unless bPrev or bDest are part of a loop
14572                         //
14573                         BasicBlock::weight_t weightDest =
14574                             bDest->isMaxBBWeight() ? bDest->bbWeight : (bDest->bbWeight + 1) / 2;
14575                         BasicBlock::weight_t weightPrev =
14576                             bPrev->isMaxBBWeight() ? bPrev->bbWeight : (bPrev->bbWeight + 2) / 3;
14577
14578                         // select the lower of weightDest and weightPrev
14579                         profHotWeight = (weightDest < weightPrev) ? weightDest : weightPrev;
14580
14581                         // if the weight of block is greater (or equal) to profHotWeight then we don't reverse the cond
14582                         if (block->bbWeight >= profHotWeight)
14583                         {
14584                             reorderBlock = false;
14585                         }
14586                     }
14587                 }
14588             }
14589             else // not a forwardBranch
14590             {
14591                 if (bPrev->bbFallsThrough())
14592                 {
14593                     goto CHECK_FOR_RARE;
14594                 }
14595
14596                 // Here we should pull up the highest weight block remaining
14597                 // and place it here since bPrev does not fall through.
14598
14599                 BasicBlock::weight_t highestWeight           = 0;
14600                 BasicBlock*          candidateBlock          = nullptr;
14601                 BasicBlock*          lastNonFallThroughBlock = bPrev;
14602                 BasicBlock*          bTmp                    = bPrev->bbNext;
14603
14604                 while (bTmp != nullptr)
14605                 {
14606                     // Don't try to split a Call/Always pair
14607                     //
14608                     if (bTmp->isBBCallAlwaysPair())
14609                     {
14610                         // Move bTmp forward
14611                         bTmp = bTmp->bbNext;
14612                     }
14613
14614                     //
14615                     // Check for loop exit condition
14616                     //
14617                     if (bTmp == nullptr)
14618                     {
14619                         break;
14620                     }
14621
14622                     //
14623                     // if its weight is the highest one we've seen and
14624                     //  the EH regions allow for us to place bTmp after bPrev
14625                     //
14626                     if ((bTmp->bbWeight > highestWeight) && fgEhAllowsMoveBlock(bPrev, bTmp))
14627                     {
14628                         // When we have a current candidateBlock that is a conditional (or unconditional) jump
14629                         // to bTmp (which is a higher weighted block) then it is better to keep out current
14630                         // candidateBlock and have it fall into bTmp
14631                         //
14632                         if ((candidateBlock == nullptr) ||
14633                             ((candidateBlock->bbJumpKind != BBJ_COND) && (candidateBlock->bbJumpKind != BBJ_ALWAYS)) ||
14634                             (candidateBlock->bbJumpDest != bTmp))
14635                         {
14636                             // otherwise we have a new candidateBlock
14637                             //
14638                             highestWeight  = bTmp->bbWeight;
14639                             candidateBlock = lastNonFallThroughBlock->bbNext;
14640                         }
14641                     }
14642
14643                     if ((bTmp->bbFallsThrough() == false) || (bTmp->bbWeight == 0))
14644                     {
14645                         lastNonFallThroughBlock = bTmp;
14646                     }
14647
14648                     bTmp = bTmp->bbNext;
14649                 }
14650
14651                 // If we didn't find a suitable block then skip this
14652                 if (highestWeight == 0)
14653                 {
14654                     reorderBlock = false;
14655                 }
14656                 else
14657                 {
14658                     noway_assert(candidateBlock != nullptr);
14659
14660                     // If the candidateBlock is the same a block then skip this
14661                     if (candidateBlock == block)
14662                     {
14663                         reorderBlock = false;
14664                     }
14665                     else
14666                     {
14667                         // Set bDest to the block that we want to come after bPrev
14668                         bDest = candidateBlock;
14669
14670                         // set profHotWeight
14671                         profHotWeight = highestWeight - 1;
14672                     }
14673                 }
14674             }
14675         }
14676         else // we don't have good profile info (or we are falling through)
14677         {
14678
14679         CHECK_FOR_RARE:;
14680
14681             /* We only want to reorder when we have a rarely run   */
14682             /* block right after a normal block,                   */
14683             /* (bPrev is known to be a normal block at this point) */
14684             if (!isRare)
14685             {
14686                 reorderBlock = false;
14687             }
14688             else
14689             {
14690                 /* If the jump target bDest is also a rarely run block then we don't want to do the reversal */
14691                 if (bDest && bDest->isRunRarely())
14692                 {
14693                     reorderBlock = false; /* Both block and bDest are rarely run */
14694                 }
14695                 else
14696                 {
14697                     // We will move any rarely run blocks blocks
14698                     profHotWeight = 0;
14699                 }
14700             }
14701         }
14702
14703         if (reorderBlock == false)
14704         {
14705             //
14706             // Check for an unconditional branch to a conditional branch
14707             // which also branches back to our next block
14708             //
14709             if (fgOptimizeBranch(bPrev))
14710             {
14711                 noway_assert(bPrev->bbJumpKind == BBJ_COND);
14712             }
14713             continue;
14714         }
14715
14716         //  Now we need to determine which blocks should be moved
14717         //
14718         //  We consider one of two choices:
14719         //
14720         //  1. Moving the fall-through blocks (or rarely run blocks) down to
14721         //     later in the method and hopefully connecting the jump dest block
14722         //     so that it becomes the fall through block
14723         //
14724         //  And when bDest in not NULL, we also consider:
14725         //
14726         //  2. Moving the bDest block (or blocks) up to bPrev
14727         //     so that it could be used as a fall through block
14728         //
14729         //  We will prefer option #1 if we are able to connect the jump dest
14730         //  block as the fall though block otherwise will we try to use option #2
14731         //
14732
14733         //
14734         //  Consider option #1: relocating blocks starting at 'block'
14735         //    to later in flowgraph
14736         //
14737         // We set bStart to the first block that will be relocated
14738         // and bEnd to the last block that will be relocated
14739
14740         BasicBlock* bStart   = block;
14741         BasicBlock* bEnd     = bStart;
14742         bNext                = bEnd->bbNext;
14743         bool connected_bDest = false;
14744
14745         if ((backwardBranch && !isRare) ||
14746             ((block->bbFlags & BBF_DONT_REMOVE) != 0)) // Don't choose option #1 when block is the start of a try region
14747         {
14748             bStart = nullptr;
14749             bEnd   = nullptr;
14750         }
14751         else
14752         {
14753             while (true)
14754             {
14755                 // Don't try to split a Call/Always pair
14756                 //
14757                 if (bEnd->isBBCallAlwaysPair())
14758                 {
14759                     // Move bEnd and bNext forward
14760                     bEnd  = bNext;
14761                     bNext = bNext->bbNext;
14762                 }
14763
14764                 //
14765                 // Check for loop exit condition
14766                 //
14767                 if (bNext == nullptr)
14768                 {
14769                     break;
14770                 }
14771
14772 #if FEATURE_EH_FUNCLETS
14773                 // Check if we've reached the funclets region, at the end of the function
14774                 if (fgFirstFuncletBB == bEnd->bbNext)
14775                 {
14776                     break;
14777                 }
14778 #endif // FEATURE_EH_FUNCLETS
14779
14780                 if (bNext == bDest)
14781                 {
14782                     connected_bDest = true;
14783                     break;
14784                 }
14785
14786                 // All the blocks must have the same try index
14787                 // and must not have the BBF_DONT_REMOVE flag set
14788
14789                 if (!BasicBlock::sameTryRegion(bStart, bNext) || ((bNext->bbFlags & BBF_DONT_REMOVE) != 0))
14790                 {
14791                     // exit the loop, bEnd is now set to the
14792                     // last block that we want to relocate
14793                     break;
14794                 }
14795
14796                 // If we are relocating rarely run blocks..
14797                 if (isRare)
14798                 {
14799                     // ... then all blocks must be rarely run
14800                     if (!bNext->isRunRarely())
14801                     {
14802                         // exit the loop, bEnd is now set to the
14803                         // last block that we want to relocate
14804                         break;
14805                     }
14806                 }
14807                 else
14808                 {
14809                     // If we are moving blocks that are hot then all
14810                     // of the blocks moved must be less than profHotWeight */
14811                     if (bNext->bbWeight >= profHotWeight)
14812                     {
14813                         // exit the loop, bEnd is now set to the
14814                         // last block that we would relocate
14815                         break;
14816                     }
14817                 }
14818
14819                 // Move bEnd and bNext forward
14820                 bEnd  = bNext;
14821                 bNext = bNext->bbNext;
14822             }
14823
14824             // Set connected_bDest to true if moving blocks [bStart .. bEnd]
14825             //  connects with the the jump dest of bPrev (i.e bDest) and
14826             // thus allows bPrev fall through instead of jump.
14827             if (bNext == bDest)
14828             {
14829                 connected_bDest = true;
14830             }
14831         }
14832
14833         //  Now consider option #2: Moving the jump dest block (or blocks)
14834         //    up to bPrev
14835         //
14836         // The variables bStart2, bEnd2 and bPrev2 are used for option #2
14837         //
14838         // We will setup bStart2 to the first block that will be relocated
14839         // and bEnd2 to the last block that will be relocated
14840         // and bPrev2 to be the lexical pred of bDest
14841         //
14842         // If after this calculation bStart2 is NULL we cannot use option #2,
14843         // otherwise bStart2, bEnd2 and bPrev2 are all non-NULL and we will use option #2
14844
14845         BasicBlock* bStart2 = nullptr;
14846         BasicBlock* bEnd2   = nullptr;
14847         BasicBlock* bPrev2  = nullptr;
14848
14849         // If option #1 didn't connect bDest and bDest isn't NULL
14850         if ((connected_bDest == false) && (bDest != nullptr) &&
14851             //  The jump target cannot be moved if it has the BBF_DONT_REMOVE flag set
14852             ((bDest->bbFlags & BBF_DONT_REMOVE) == 0))
14853         {
14854             // We will consider option #2: relocating blocks starting at 'bDest' to succeed bPrev
14855             //
14856             // setup bPrev2 to be the lexical pred of bDest
14857
14858             bPrev2 = block;
14859             while (bPrev2 != nullptr)
14860             {
14861                 if (bPrev2->bbNext == bDest)
14862                 {
14863                     break;
14864                 }
14865
14866                 bPrev2 = bPrev2->bbNext;
14867             }
14868
14869             if ((bPrev2 != nullptr) && fgEhAllowsMoveBlock(bPrev, bDest))
14870             {
14871                 // We have decided that relocating bDest to be after bPrev is best
14872                 // Set bStart2 to the first block that will be relocated
14873                 // and bEnd2 to the last block that will be relocated
14874                 //
14875                 // Assigning to bStart2 selects option #2
14876                 //
14877                 bStart2 = bDest;
14878                 bEnd2   = bStart2;
14879                 bNext   = bEnd2->bbNext;
14880
14881                 while (true)
14882                 {
14883                     // Don't try to split a Call/Always pair
14884                     //
14885                     if (bEnd2->isBBCallAlwaysPair())
14886                     {
14887                         noway_assert(bNext->bbJumpKind == BBJ_ALWAYS);
14888                         // Move bEnd2 and bNext forward
14889                         bEnd2 = bNext;
14890                         bNext = bNext->bbNext;
14891                     }
14892
14893                     // Check for the Loop exit conditions
14894
14895                     if (bNext == nullptr)
14896                     {
14897                         break;
14898                     }
14899
14900                     if (bEnd2->bbFallsThrough() == false)
14901                     {
14902                         break;
14903                     }
14904
14905                     // If we are relocating rarely run blocks..
14906                     // All the blocks must have the same try index,
14907                     // and must not have the BBF_DONT_REMOVE flag set
14908
14909                     if (!BasicBlock::sameTryRegion(bStart2, bNext) || ((bNext->bbFlags & BBF_DONT_REMOVE) != 0))
14910                     {
14911                         // exit the loop, bEnd2 is now set to the
14912                         // last block that we want to relocate
14913                         break;
14914                     }
14915
14916                     if (isRare)
14917                     {
14918                         /* ... then all blocks must not be rarely run */
14919                         if (bNext->isRunRarely())
14920                         {
14921                             // exit the loop, bEnd2 is now set to the
14922                             // last block that we want to relocate
14923                             break;
14924                         }
14925                     }
14926                     else
14927                     {
14928                         // If we are relocating hot blocks
14929                         // all blocks moved must be greater than profHotWeight
14930                         if (bNext->bbWeight <= profHotWeight)
14931                         {
14932                             // exit the loop, bEnd2 is now set to the
14933                             // last block that we want to relocate
14934                             break;
14935                         }
14936                     }
14937
14938                     // Move bEnd2 and bNext forward
14939                     bEnd2 = bNext;
14940                     bNext = bNext->bbNext;
14941                 }
14942             }
14943         }
14944
14945         // If we are using option #1 then ...
14946         if (bStart2 == nullptr)
14947         {
14948             // Don't use option #1 for a backwards branch
14949             if (bStart == nullptr)
14950             {
14951                 continue;
14952             }
14953
14954             // .... Don't move a set of blocks that are already at the end of the main method
14955             if (bEnd == fgLastBBInMainFunction())
14956             {
14957                 continue;
14958             }
14959         }
14960
14961 #ifdef DEBUG
14962         if (verbose)
14963         {
14964             if (bDest != nullptr)
14965             {
14966                 if (bPrev->bbJumpKind == BBJ_COND)
14967                 {
14968                     printf("Decided to reverse conditional branch at block BB%02u branch to BB%02u ", bPrev->bbNum,
14969                            bDest->bbNum);
14970                 }
14971                 else if (bPrev->bbJumpKind == BBJ_ALWAYS)
14972                 {
14973                     printf("Decided to straighten unconditional branch at block BB%02u branch to BB%02u ", bPrev->bbNum,
14974                            bDest->bbNum);
14975                 }
14976                 else
14977                 {
14978                     printf("Decided to place hot code after BB%02u, placed BB%02u after this block ", bPrev->bbNum,
14979                            bDest->bbNum);
14980                 }
14981
14982                 if (profHotWeight > 0)
14983                 {
14984                     printf("because of IBC profile data\n");
14985                 }
14986                 else
14987                 {
14988                     if (bPrev->bbFallsThrough())
14989                     {
14990                         printf("since it falls into a rarely run block\n");
14991                     }
14992                     else
14993                     {
14994                         printf("since it is succeeded by a rarely run block\n");
14995                     }
14996                 }
14997             }
14998             else
14999             {
15000                 printf("Decided to relocate block(s) after block BB%02u since they are %s block(s)\n", bPrev->bbNum,
15001                        block->isRunRarely() ? "rarely run" : "uncommonly run");
15002             }
15003         }
15004 #endif // DEBUG
15005
15006         // We will set insertAfterBlk to the block the precedes our insertion range
15007         // We will set bStartPrev to be the block that precedes the set of blocks that we are moving
15008         BasicBlock* insertAfterBlk;
15009         BasicBlock* bStartPrev;
15010
15011         if (bStart2 != nullptr)
15012         {
15013             // Option #2: relocating blocks starting at 'bDest' to follow bPrev
15014
15015             // Update bStart and bEnd so that we can use these two for all later operations
15016             bStart = bStart2;
15017             bEnd   = bEnd2;
15018
15019             // Set bStartPrev to be the block that comes before bStart
15020             bStartPrev = bPrev2;
15021
15022             // We will move [bStart..bEnd] to immediately after bPrev
15023             insertAfterBlk = bPrev;
15024         }
15025         else
15026         {
15027             // option #1: Moving the fall-through blocks (or rarely run blocks) down to later in the method
15028
15029             // Set bStartPrev to be the block that come before bStart
15030             bStartPrev = bPrev;
15031
15032             // We will move [bStart..bEnd] but we will pick the insert location later
15033             insertAfterBlk = nullptr;
15034         }
15035
15036         // We are going to move [bStart..bEnd] so they can't be NULL
15037         noway_assert(bStart != nullptr);
15038         noway_assert(bEnd != nullptr);
15039
15040         // bEnd can't be a BBJ_CALLFINALLY unless it is a RETLESS call
15041         noway_assert((bEnd->bbJumpKind != BBJ_CALLFINALLY) || (bEnd->bbFlags & BBF_RETLESS_CALL));
15042
15043         // bStartPrev must be set to the block that precedes bStart
15044         noway_assert(bStartPrev->bbNext == bStart);
15045
15046         // Since we will be unlinking [bStart..bEnd],
15047         // we need to compute and remember if bStart is in each of
15048         // the try and handler regions
15049         //
15050         bool* fStartIsInTry = nullptr;
15051         bool* fStartIsInHnd = nullptr;
15052
15053         if (compHndBBtabCount > 0)
15054         {
15055             fStartIsInTry = new (this, CMK_Unknown) bool[compHndBBtabCount];
15056             fStartIsInHnd = new (this, CMK_Unknown) bool[compHndBBtabCount];
15057
15058             for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
15059             {
15060                 fStartIsInTry[XTnum] = HBtab->InTryRegionBBRange(bStart);
15061                 fStartIsInHnd[XTnum] = HBtab->InHndRegionBBRange(bStart);
15062             }
15063         }
15064
15065         /* Temporarily unlink [bStart..bEnd] from the flow graph */
15066         fgUnlinkRange(bStart, bEnd);
15067
15068         if (insertAfterBlk == nullptr)
15069         {
15070             // Find new location for the unlinked block(s)
15071             // Set insertAfterBlk to the block which will precede the insertion point
15072
15073             if (!bStart->hasTryIndex() && isRare)
15074             {
15075                 // We'll just insert the blocks at the end of the method. If the method
15076                 // has funclets, we will insert at the end of the main method but before
15077                 // any of the funclets. Note that we create funclets before we call
15078                 // fgReorderBlocks().
15079
15080                 insertAfterBlk = fgLastBBInMainFunction();
15081                 noway_assert(insertAfterBlk != bPrev);
15082             }
15083             else
15084             {
15085                 BasicBlock* startBlk;
15086                 BasicBlock* lastBlk;
15087                 EHblkDsc*   ehDsc = ehInitTryBlockRange(bStart, &startBlk, &lastBlk);
15088
15089                 BasicBlock* endBlk;
15090
15091                 /* Setup startBlk and endBlk as the range to search */
15092
15093                 if (ehDsc != nullptr)
15094                 {
15095                     endBlk = lastBlk->bbNext;
15096
15097                     /*
15098                        Multiple (nested) try regions might start from the same BB.
15099                        For example,
15100
15101                        try3   try2   try1
15102                        |---   |---   |---   BB01
15103                        |      |      |      BB02
15104                        |      |      |---   BB03
15105                        |      |             BB04
15106                        |      |------------ BB05
15107                        |                    BB06
15108                        |------------------- BB07
15109
15110                        Now if we want to insert in try2 region, we will start with startBlk=BB01.
15111                        The following loop will allow us to start from startBlk==BB04.
15112                     */
15113                     while (!BasicBlock::sameTryRegion(startBlk, bStart) && (startBlk != endBlk))
15114                     {
15115                         startBlk = startBlk->bbNext;
15116                     }
15117
15118                     // startBlk cannot equal endBlk as it must come before endBlk
15119                     if (startBlk == endBlk)
15120                     {
15121                         goto CANNOT_MOVE;
15122                     }
15123
15124                     // we also can't start searching the try region at bStart
15125                     if (startBlk == bStart)
15126                     {
15127                         // if bEnd is the last block in the method or
15128                         // or if bEnd->bbNext is in a different try region
15129                         // then we cannot move the blocks
15130                         //
15131                         if ((bEnd->bbNext == nullptr) || !BasicBlock::sameTryRegion(startBlk, bEnd->bbNext))
15132                         {
15133                             goto CANNOT_MOVE;
15134                         }
15135
15136                         startBlk = bEnd->bbNext;
15137
15138                         // Check that the new startBlk still comes before endBlk
15139
15140                         // startBlk cannot equal endBlk as it must come before endBlk
15141                         if (startBlk == endBlk)
15142                         {
15143                             goto CANNOT_MOVE;
15144                         }
15145
15146                         BasicBlock* tmpBlk = startBlk;
15147                         while ((tmpBlk != endBlk) && (tmpBlk != nullptr))
15148                         {
15149                             tmpBlk = tmpBlk->bbNext;
15150                         }
15151
15152                         // when tmpBlk is NULL that means startBlk is after endBlk
15153                         // so there is no way to move bStart..bEnd within the try region
15154                         if (tmpBlk == nullptr)
15155                         {
15156                             goto CANNOT_MOVE;
15157                         }
15158                     }
15159                 }
15160                 else
15161                 {
15162                     noway_assert(isRare == false);
15163
15164                     /* We'll search through the entire main method */
15165                     startBlk = fgFirstBB;
15166                     endBlk   = fgEndBBAfterMainFunction();
15167                 }
15168
15169                 // Calculate nearBlk and jumpBlk and then call fgFindInsertPoint()
15170                 // to find our insertion block
15171                 //
15172                 {
15173                     // If the set of blocks that we are moving ends with a BBJ_ALWAYS to
15174                     // another [rarely run] block that comes after bPrev (forward branch)
15175                     // then we can set up nearBlk to eliminate this jump sometimes
15176                     //
15177                     BasicBlock* nearBlk = nullptr;
15178                     BasicBlock* jumpBlk = nullptr;
15179
15180                     if ((bEnd->bbJumpKind == BBJ_ALWAYS) && (!isRare || bEnd->bbJumpDest->isRunRarely()) &&
15181                         fgIsForwardBranch(bEnd, bPrev))
15182                     {
15183                         // Set nearBlk to be the block in [startBlk..endBlk]
15184                         // such that nearBlk->bbNext == bEnd->JumpDest
15185                         // if no such block exists then set nearBlk to NULL
15186                         nearBlk = startBlk;
15187                         jumpBlk = bEnd;
15188                         do
15189                         {
15190                             // We do not want to set nearBlk to bPrev
15191                             // since then we will not move [bStart..bEnd]
15192                             //
15193                             if (nearBlk != bPrev)
15194                             {
15195                                 // Check if nearBlk satisfies our requirement
15196                                 if (nearBlk->bbNext == bEnd->bbJumpDest)
15197                                 {
15198                                     break;
15199                                 }
15200                             }
15201
15202                             // Did we reach the endBlk?
15203                             if (nearBlk == endBlk)
15204                             {
15205                                 nearBlk = nullptr;
15206                                 break;
15207                             }
15208
15209                             // advance nearBlk to the next block
15210                             nearBlk = nearBlk->bbNext;
15211
15212                         } while (nearBlk != nullptr);
15213                     }
15214
15215                     // if nearBlk is NULL then we set nearBlk to be the
15216                     // first block that we want to insert after.
15217                     if (nearBlk == nullptr)
15218                     {
15219                         if (bDest != nullptr)
15220                         {
15221                             // we want to insert after bDest
15222                             nearBlk = bDest;
15223                         }
15224                         else
15225                         {
15226                             // we want to insert after bPrev
15227                             nearBlk = bPrev;
15228                         }
15229                     }
15230
15231                     /* Set insertAfterBlk to the block which we will insert after. */
15232
15233                     insertAfterBlk =
15234                         fgFindInsertPoint(bStart->bbTryIndex,
15235                                           true, // Insert in the try region.
15236                                           startBlk, endBlk, nearBlk, jumpBlk, bStart->bbWeight == BB_ZERO_WEIGHT);
15237                 }
15238
15239                 /* See if insertAfterBlk is the same as where we started, */
15240                 /*  or if we could not find any insertion point     */
15241
15242                 if ((insertAfterBlk == bPrev) || (insertAfterBlk == nullptr))
15243                 {
15244                 CANNOT_MOVE:;
15245                     /* We couldn't move the blocks, so put everything back */
15246                     /* relink [bStart .. bEnd] into the flow graph */
15247
15248                     bPrev->setNext(bStart);
15249                     if (bEnd->bbNext)
15250                     {
15251                         bEnd->bbNext->bbPrev = bEnd;
15252                     }
15253 #ifdef DEBUG
15254                     if (verbose)
15255                     {
15256                         if (bStart != bEnd)
15257                         {
15258                             printf("Could not relocate blocks (BB%02u .. BB%02u)\n", bStart->bbNum, bEnd->bbNum);
15259                         }
15260                         else
15261                         {
15262                             printf("Could not relocate block BB%02u\n", bStart->bbNum);
15263                         }
15264                     }
15265 #endif // DEBUG
15266                     continue;
15267                 }
15268             }
15269         }
15270
15271         noway_assert(insertAfterBlk != nullptr);
15272         noway_assert(bStartPrev != nullptr);
15273         noway_assert(bStartPrev != insertAfterBlk);
15274
15275 #ifdef DEBUG
15276         movedBlocks = true;
15277
15278         if (verbose)
15279         {
15280             const char* msg;
15281             if (bStart2 != nullptr)
15282             {
15283                 msg = "hot";
15284             }
15285             else
15286             {
15287                 if (isRare)
15288                 {
15289                     msg = "rarely run";
15290                 }
15291                 else
15292                 {
15293                     msg = "uncommon";
15294                 }
15295             }
15296
15297             printf("Relocated %s ", msg);
15298             if (bStart != bEnd)
15299             {
15300                 printf("blocks (BB%02u .. BB%02u)", bStart->bbNum, bEnd->bbNum);
15301             }
15302             else
15303             {
15304                 printf("block BB%02u", bStart->bbNum);
15305             }
15306
15307             if (bPrev->bbJumpKind == BBJ_COND)
15308             {
15309                 printf(" by reversing conditional jump at BB%02u\n", bPrev->bbNum);
15310             }
15311             else
15312             {
15313                 printf("\n", bPrev->bbNum);
15314             }
15315         }
15316 #endif // DEBUG
15317
15318         if (bPrev->bbJumpKind == BBJ_COND)
15319         {
15320             /* Reverse the bPrev jump condition */
15321             GenTree* condTest = bPrev->lastStmt();
15322
15323             condTest = condTest->gtStmt.gtStmtExpr;
15324             noway_assert(condTest->gtOper == GT_JTRUE);
15325
15326             condTest->gtOp.gtOp1 = gtReverseCond(condTest->gtOp.gtOp1);
15327
15328             if (bStart2 == nullptr)
15329             {
15330                 /* Set the new jump dest for bPrev to the rarely run or uncommon block(s) */
15331                 bPrev->bbJumpDest = bStart;
15332                 bStart->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
15333             }
15334             else
15335             {
15336                 noway_assert(insertAfterBlk == bPrev);
15337                 noway_assert(insertAfterBlk->bbNext == block);
15338
15339                 /* Set the new jump dest for bPrev to the rarely run or uncommon block(s) */
15340                 bPrev->bbJumpDest = block;
15341                 block->bbFlags |= (BBF_JMP_TARGET | BBF_HAS_LABEL);
15342             }
15343         }
15344
15345         // If we are moving blocks that are at the end of a try or handler
15346         // we will need to shorten ebdTryLast or ebdHndLast
15347         //
15348         ehUpdateLastBlocks(bEnd, bStartPrev);
15349
15350         // If we are moving blocks into the end of a try region or handler region
15351         // we will need to extend ebdTryLast or ebdHndLast so the blocks that we
15352         // are moving are part of this try or handler region.
15353         //
15354         for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
15355         {
15356             // Are we moving blocks to the end of a try region?
15357             if (HBtab->ebdTryLast == insertAfterBlk)
15358             {
15359                 if (fStartIsInTry[XTnum])
15360                 {
15361                     // bStart..bEnd is in the try, so extend the try region
15362                     fgSetTryEnd(HBtab, bEnd);
15363                 }
15364             }
15365
15366             // Are we moving blocks to the end of a handler region?
15367             if (HBtab->ebdHndLast == insertAfterBlk)
15368             {
15369                 if (fStartIsInHnd[XTnum])
15370                 {
15371                     // bStart..bEnd is in the handler, so extend the handler region
15372                     fgSetHndEnd(HBtab, bEnd);
15373                 }
15374             }
15375         }
15376
15377         /* We have decided to insert the block(s) after 'insertAfterBlk' */
15378         fgMoveBlocksAfter(bStart, bEnd, insertAfterBlk);
15379
15380         if (bDest)
15381         {
15382             /* We may need to insert an unconditional branch after bPrev to bDest */
15383             fgConnectFallThrough(bPrev, bDest);
15384         }
15385         else
15386         {
15387             /* If bPrev falls through, we must insert a jump to block */
15388             fgConnectFallThrough(bPrev, block);
15389         }
15390
15391         BasicBlock* bSkip = bEnd->bbNext;
15392
15393         /* If bEnd falls through, we must insert a jump to bNext */
15394         fgConnectFallThrough(bEnd, bNext);
15395
15396         if (bStart2 == nullptr)
15397         {
15398             /* If insertAfterBlk falls through, we are forced to     */
15399             /* add a jump around the block(s) we just inserted */
15400             fgConnectFallThrough(insertAfterBlk, bSkip);
15401         }
15402         else
15403         {
15404             /* We may need to insert an unconditional branch after bPrev2 to bStart */
15405             fgConnectFallThrough(bPrev2, bStart);
15406         }
15407
15408 #if DEBUG
15409         if (verbose)
15410         {
15411             printf("\nAfter this change in fgReorderBlocks");
15412             fgDispBasicBlocks(verboseTrees);
15413             printf("\n");
15414         }
15415         fgVerifyHandlerTab();
15416
15417         // Make sure that the predecessor lists are accurate
15418         if (expensiveDebugCheckLevel >= 2)
15419         {
15420             fgDebugCheckBBlist();
15421         }
15422 #endif // DEBUG
15423
15424         // Set our iteration point 'block' to be the new bPrev->bbNext
15425         //  It will be used as the next bPrev
15426         block = bPrev->bbNext;
15427
15428     } // end of for loop(bPrev,block)
15429
15430     bool changed = movedBlocks || newRarelyRun || optimizedSwitches;
15431
15432     if (changed)
15433     {
15434         fgNeedsUpdateFlowGraph = true;
15435 #if DEBUG
15436         // Make sure that the predecessor lists are accurate
15437         if (expensiveDebugCheckLevel >= 2)
15438         {
15439             fgDebugCheckBBlist();
15440         }
15441 #endif // DEBUG
15442     }
15443 }
15444 #ifdef _PREFAST_
15445 #pragma warning(pop)
15446 #endif
15447
15448 /*-------------------------------------------------------------------------
15449  *
15450  * Walk the basic blocks list to determine the first block to place in the
15451  * cold section.  This would be the first of a series of rarely executed blocks
15452  * such that no succeeding blocks are in a try region or an exception handler
15453  * or are rarely executed.
15454  */
15455
15456 void Compiler::fgDetermineFirstColdBlock()
15457 {
15458 #ifdef DEBUG
15459     if (verbose)
15460     {
15461         printf("\n*************** In fgDetermineFirstColdBlock()\n");
15462     }
15463 #endif // DEBUG
15464
15465     // Since we may need to create a new transistion block
15466     // we assert that it is OK to create new blocks.
15467     //
15468     assert(fgSafeBasicBlockCreation);
15469
15470     fgFirstColdBlock = nullptr;
15471
15472 #if FEATURE_STACK_FP_X87
15473     if (compMayHaveTransitionBlocks)
15474     {
15475         opts.compProcedureSplitting = false;
15476
15477         // See comment above declaration of compMayHaveTransitionBlocks for comments on this
15478         JITDUMP("Turning off procedure splitting for this method, as it may end up having FP transition blocks\n");
15479     }
15480 #endif // FEATURE_STACK_FP_X87
15481
15482     if (!opts.compProcedureSplitting)
15483     {
15484         JITDUMP("No procedure splitting will be done for this method\n");
15485         return;
15486     }
15487
15488 #ifdef DEBUG
15489     if ((compHndBBtabCount > 0) && !opts.compProcedureSplittingEH)
15490     {
15491         JITDUMP("No procedure splitting will be done for this method with EH (by request)\n");
15492         return;
15493     }
15494 #endif // DEBUG
15495
15496 #if FEATURE_EH_FUNCLETS
15497     // TODO-CQ: handle hot/cold splitting in functions with EH (including synchronized methods
15498     // that create EH in methods without explicit EH clauses).
15499
15500     if (compHndBBtabCount > 0)
15501     {
15502         JITDUMP("No procedure splitting will be done for this method with EH (implementation limitation)\n");
15503         return;
15504     }
15505 #endif // FEATURE_EH_FUNCLETS
15506
15507     BasicBlock* firstColdBlock       = nullptr;
15508     BasicBlock* prevToFirstColdBlock = nullptr;
15509     BasicBlock* block;
15510     BasicBlock* lblk;
15511
15512     for (lblk = nullptr, block = fgFirstBB; block != nullptr; lblk = block, block = block->bbNext)
15513     {
15514         bool blockMustBeInHotSection = false;
15515
15516 #if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
15517         if (bbIsHandlerBeg(block))
15518         {
15519             blockMustBeInHotSection = true;
15520         }
15521 #endif // HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION
15522
15523         // Do we have a candidate for the first cold block?
15524         if (firstColdBlock != nullptr)
15525         {
15526             // We have a candidate for first cold block
15527
15528             // Is this a hot block?
15529             if (blockMustBeInHotSection || (block->isRunRarely() == false))
15530             {
15531                 // We have to restart the search for the first cold block
15532                 firstColdBlock       = nullptr;
15533                 prevToFirstColdBlock = nullptr;
15534             }
15535         }
15536         else // (firstColdBlock == NULL)
15537         {
15538             // We don't have a candidate for first cold block
15539
15540             // Is this a cold block?
15541             if (!blockMustBeInHotSection && (block->isRunRarely() == true))
15542             {
15543                 //
15544                 // If the last block that was hot was a BBJ_COND
15545                 // then we will have to add an unconditional jump
15546                 // so the code size for block needs be large
15547                 // enough to make it worth our while
15548                 //
15549                 if ((lblk == nullptr) || (lblk->bbJumpKind != BBJ_COND) || (fgGetCodeEstimate(block) >= 8))
15550                 {
15551                     // This block is now a candidate for first cold block
15552                     // Also remember the predecessor to this block
15553                     firstColdBlock       = block;
15554                     prevToFirstColdBlock = lblk;
15555                 }
15556             }
15557         }
15558     }
15559
15560     if (firstColdBlock == fgFirstBB)
15561     {
15562         // If the first block is Cold then we can't move any blocks
15563         // into the cold section
15564
15565         firstColdBlock = nullptr;
15566     }
15567
15568     if (firstColdBlock != nullptr)
15569     {
15570         noway_assert(prevToFirstColdBlock != nullptr);
15571
15572         if (prevToFirstColdBlock == nullptr)
15573         {
15574             return; // To keep Prefast happy
15575         }
15576
15577         // If we only have one cold block
15578         // then it may not be worth it to move it
15579         // into the Cold section as a jump to the
15580         // Cold section is 5 bytes in size.
15581         //
15582         if (firstColdBlock->bbNext == nullptr)
15583         {
15584             // If the size of the cold block is 7 or less
15585             // then we will keep it in the Hot section.
15586             //
15587             if (fgGetCodeEstimate(firstColdBlock) < 8)
15588             {
15589                 firstColdBlock = nullptr;
15590                 goto EXIT;
15591             }
15592         }
15593
15594         // When the last Hot block fall through into the Cold section
15595         // we may need to add a jump
15596         //
15597         if (prevToFirstColdBlock->bbFallsThrough())
15598         {
15599             switch (prevToFirstColdBlock->bbJumpKind)
15600             {
15601                 default:
15602                     noway_assert(!"Unhandled jumpkind in fgDetermineFirstColdBlock()");
15603
15604                 case BBJ_CALLFINALLY:
15605                     // A BBJ_CALLFINALLY that falls through is always followed
15606                     // by an empty BBJ_ALWAYS.
15607                     //
15608                     assert(prevToFirstColdBlock->isBBCallAlwaysPair());
15609                     firstColdBlock =
15610                         firstColdBlock->bbNext; // Note that this assignment could make firstColdBlock == nullptr
15611                     break;
15612
15613                 case BBJ_COND:
15614                     //
15615                     // This is a slightly more complicated case, because we will
15616                     // probably need to insert a block to jump to the cold section.
15617                     //
15618                     if (firstColdBlock->isEmpty() && (firstColdBlock->bbJumpKind == BBJ_ALWAYS))
15619                     {
15620                         // We can just use this block as the transitionBlock
15621                         firstColdBlock = firstColdBlock->bbNext;
15622                         // Note that this assignment could make firstColdBlock == NULL
15623                     }
15624                     else
15625                     {
15626                         BasicBlock* transitionBlock = fgNewBBafter(BBJ_ALWAYS, prevToFirstColdBlock, true);
15627                         transitionBlock->bbJumpDest = firstColdBlock;
15628                         transitionBlock->inheritWeight(firstColdBlock);
15629
15630                         noway_assert(fgComputePredsDone);
15631
15632                         // Update the predecessor list for firstColdBlock
15633                         fgReplacePred(firstColdBlock, prevToFirstColdBlock, transitionBlock);
15634
15635                         // Add prevToFirstColdBlock as a predecessor for transitionBlock
15636                         fgAddRefPred(transitionBlock, prevToFirstColdBlock);
15637                     }
15638                     break;
15639
15640                 case BBJ_NONE:
15641                     // If the block preceding the first cold block is BBJ_NONE,
15642                     // convert it to BBJ_ALWAYS to force an explicit jump.
15643
15644                     prevToFirstColdBlock->bbJumpDest = firstColdBlock;
15645                     prevToFirstColdBlock->bbJumpKind = BBJ_ALWAYS;
15646                     break;
15647             }
15648         }
15649     }
15650
15651     if (firstColdBlock != nullptr)
15652     {
15653         firstColdBlock->bbFlags |= BBF_JMP_TARGET;
15654
15655         for (block = firstColdBlock; block; block = block->bbNext)
15656         {
15657             block->bbFlags |= BBF_COLD;
15658         }
15659     }
15660
15661 EXIT:;
15662
15663 #ifdef DEBUG
15664     if (verbose)
15665     {
15666         if (firstColdBlock)
15667         {
15668             printf("fgFirstColdBlock is BB%02u.\n", firstColdBlock->bbNum);
15669         }
15670         else
15671         {
15672             printf("fgFirstColdBlock is NULL.\n");
15673         }
15674
15675         fgDispBasicBlocks();
15676     }
15677
15678     fgVerifyHandlerTab();
15679 #endif // DEBUG
15680
15681     fgFirstColdBlock = firstColdBlock;
15682 }
15683
15684 #ifdef _PREFAST_
15685 #pragma warning(push)
15686 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
15687 #endif
15688 /*****************************************************************************
15689  *
15690  *  Function called to "comb" the basic block list.
15691  *  Removes any empty blocks, unreachable blocks and redundant jumps.
15692  *  Most of those appear after dead store removal and folding of conditionals.
15693  *
15694  *  Returns: true if the flowgraph has been modified
15695  *
15696  *  It also compacts basic blocks
15697  *   (consecutive basic blocks that should in fact be one).
15698  *
15699  *  NOTE:
15700  *    Debuggable code and Min Optimization JIT also introduces basic blocks
15701  *    but we do not optimize those!
15702  */
15703
15704 bool Compiler::fgUpdateFlowGraph(bool doTailDuplication)
15705 {
15706 #ifdef DEBUG
15707     if (verbose)
15708     {
15709         printf("\n*************** In fgUpdateFlowGraph()");
15710     }
15711 #endif // DEBUG
15712
15713     /* This should never be called for debuggable code */
15714
15715     noway_assert(!opts.MinOpts() && !opts.compDbgCode);
15716
15717 #ifdef DEBUG
15718     if (verbose)
15719     {
15720         printf("\nBefore updating the flow graph:\n");
15721         fgDispBasicBlocks(verboseTrees);
15722         printf("\n");
15723     }
15724 #endif // DEBUG
15725
15726     /* Walk all the basic blocks - look for unconditional jumps, empty blocks, blocks to compact, etc...
15727      *
15728      * OBSERVATION:
15729      *      Once a block is removed the predecessors are not accurate (assuming they were at the beginning)
15730      *      For now we will only use the information in bbRefs because it is easier to be updated
15731      */
15732
15733     bool modified = false;
15734     bool change;
15735     do
15736     {
15737         change = false;
15738
15739         BasicBlock* block;           // the current block
15740         BasicBlock* bPrev = nullptr; // the previous non-worthless block
15741         BasicBlock* bNext;           // the successor of the current block
15742         BasicBlock* bDest;           // the jump target of the current block
15743
15744         for (block = fgFirstBB; block != nullptr; block = block->bbNext)
15745         {
15746             /*  Some blocks may be already marked removed by other optimizations
15747              *  (e.g worthless loop removal), without being explicitly removed
15748              *  from the list.
15749              */
15750
15751             if (block->bbFlags & BBF_REMOVED)
15752             {
15753                 if (bPrev)
15754                 {
15755                     bPrev->setNext(block->bbNext);
15756                 }
15757                 else
15758                 {
15759                     /* WEIRD first basic block is removed - should have an assert here */
15760                     noway_assert(!"First basic block marked as BBF_REMOVED???");
15761
15762                     fgFirstBB = block->bbNext;
15763                 }
15764                 continue;
15765             }
15766
15767         /*  We jump to the REPEAT label if we performed a change involving the current block
15768          *  This is in case there are other optimizations that can show up
15769          *  (e.g. - compact 3 blocks in a row)
15770          *  If nothing happens, we then finish the iteration and move to the next block
15771          */
15772
15773         REPEAT:;
15774
15775             bNext = block->bbNext;
15776             bDest = nullptr;
15777
15778             if (block->bbJumpKind == BBJ_ALWAYS)
15779             {
15780                 bDest = block->bbJumpDest;
15781                 if (doTailDuplication && fgOptimizeUncondBranchToSimpleCond(block, bDest))
15782                 {
15783                     change   = true;
15784                     modified = true;
15785                     bDest    = block->bbJumpDest;
15786                     bNext    = block->bbNext;
15787                 }
15788             }
15789
15790             // Remove JUMPS to the following block
15791             // and optimize any JUMPS to JUMPS
15792
15793             if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS)
15794             {
15795                 bDest = block->bbJumpDest;
15796                 if (bDest == bNext)
15797                 {
15798                     if (fgOptimizeBranchToNext(block, bNext, bPrev))
15799                     {
15800                         change   = true;
15801                         modified = true;
15802                         bDest    = nullptr;
15803                     }
15804                 }
15805             }
15806
15807             if (bDest != nullptr)
15808             {
15809                 // Do we have a JUMP to an empty unconditional JUMP block?
15810                 if (bDest->isEmpty() && (bDest->bbJumpKind == BBJ_ALWAYS) &&
15811                     (bDest != bDest->bbJumpDest)) // special case for self jumps
15812                 {
15813                     if (fgOptimizeBranchToEmptyUnconditional(block, bDest))
15814                     {
15815                         change   = true;
15816                         modified = true;
15817                         goto REPEAT;
15818                     }
15819                 }
15820
15821                 // Check for a conditional branch that just skips over an empty BBJ_ALWAYS block
15822
15823                 if ((block->bbJumpKind == BBJ_COND) &&   // block is a BBJ_COND block
15824                     (bNext != nullptr) &&                // block is not the last block
15825                     (bNext->bbRefs == 1) &&              // No other block jumps to bNext
15826                     (bNext->bbNext == bDest) &&          // The block after bNext is the BBJ_COND jump dest
15827                     (bNext->bbJumpKind == BBJ_ALWAYS) && // The next block is a BBJ_ALWAYS block
15828                     bNext->isEmpty() &&                  // and it is an an empty block
15829                     (bNext != bNext->bbJumpDest) &&      // special case for self jumps
15830                     (bDest != fgFirstColdBlock))
15831                 {
15832                     bool optimizeJump = true;
15833
15834                     // We do not optimize jumps between two different try regions.
15835                     // However jumping to a block that is not in any try region is OK
15836                     //
15837                     if (bDest->hasTryIndex() && !BasicBlock::sameTryRegion(block, bDest))
15838                     {
15839                         optimizeJump = false;
15840                     }
15841
15842                     // Also consider bNext's try region
15843                     //
15844                     if (bNext->hasTryIndex() && !BasicBlock::sameTryRegion(block, bNext))
15845                     {
15846                         optimizeJump = false;
15847                     }
15848
15849                     // If we are optimizing using real profile weights
15850                     // then don't optimize a conditional jump to an unconditional jump
15851                     // until after we have computed the edge weights
15852                     //
15853                     if (fgIsUsingProfileWeights())
15854                     {
15855                         // if block and bdest are in different hot/cold regions we can't do this this optimization
15856                         // because we can't allow fall-through into the cold region.
15857                         if (!fgEdgeWeightsComputed || fgInDifferentRegions(block, bDest))
15858                         {
15859                             fgNeedsUpdateFlowGraph = true;
15860                             optimizeJump           = false;
15861                         }
15862                     }
15863
15864                     if (optimizeJump)
15865                     {
15866 #ifdef DEBUG
15867                         if (verbose)
15868                         {
15869                             printf("\nReversing a conditional jump around an unconditional jump (BB%02u -> BB%02u -> "
15870                                    "BB%02u)\n",
15871                                    block->bbNum, bDest->bbNum, bNext->bbJumpDest->bbNum);
15872                         }
15873 #endif // DEBUG
15874                         /* Reverse the jump condition */
15875
15876                         GenTree* test = block->lastNode();
15877                         noway_assert(test->gtOper == GT_JTRUE);
15878
15879                         GenTree* cond = gtReverseCond(test->gtOp.gtOp1);
15880                         assert(cond == test->gtOp.gtOp1); // Ensure `gtReverseCond` did not create a new node.
15881                         test->gtOp.gtOp1 = cond;
15882
15883                         // Optimize the Conditional JUMP to go to the new target
15884                         block->bbJumpDest = bNext->bbJumpDest;
15885
15886                         fgAddRefPred(bNext->bbJumpDest, block, fgRemoveRefPred(bNext->bbJumpDest, bNext));
15887
15888                         /*
15889                           Unlink bNext from the BasicBlock list; note that we can
15890                           do this even though other blocks could jump to it - the
15891                           reason is that elsewhere in this function we always
15892                           redirect jumps to jumps to jump to the final label,
15893                           so even if another block jumps to bNext it won't matter
15894                           once we're done since any such jump will be redirected
15895                           to the final target by the time we're done here.
15896                         */
15897
15898                         fgRemoveRefPred(bNext, block);
15899                         fgUnlinkBlock(bNext);
15900
15901                         /* Mark the block as removed */
15902                         bNext->bbFlags |= BBF_REMOVED;
15903
15904                         // If this is the first Cold basic block update fgFirstColdBlock
15905                         if (bNext == fgFirstColdBlock)
15906                         {
15907                             fgFirstColdBlock = bNext->bbNext;
15908                         }
15909
15910                         //
15911                         // If we removed the end of a try region or handler region
15912                         // we will need to update ebdTryLast or ebdHndLast.
15913                         //
15914
15915                         EHblkDsc* HBtab;
15916                         EHblkDsc* HBtabEnd;
15917
15918                         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd;
15919                              HBtab++)
15920                         {
15921                             if ((HBtab->ebdTryLast == bNext) || (HBtab->ebdHndLast == bNext))
15922                             {
15923                                 fgSkipRmvdBlocks(HBtab);
15924                             }
15925                         }
15926
15927                         // we optimized this JUMP - goto REPEAT to catch similar cases
15928                         change   = true;
15929                         modified = true;
15930
15931 #ifdef DEBUG
15932                         if (verbose)
15933                         {
15934                             printf("\nAfter reversing the jump:\n");
15935                             fgDispBasicBlocks(verboseTrees);
15936                         }
15937 #endif // DEBUG
15938
15939                         /*
15940                            For a rare special case we cannot jump to REPEAT
15941                            as jumping to REPEAT will cause us to delete 'block'
15942                            because it currently appears to be unreachable.  As
15943                            it is a self loop that only has a single bbRef (itself)
15944                            However since the unlinked bNext has additional bbRefs
15945                            (that we will later connect to 'block'), it is not really
15946                            unreachable.
15947                         */
15948                         if ((bNext->bbRefs > 0) && (bNext->bbJumpDest == block) && (block->bbRefs == 1))
15949                         {
15950                             continue;
15951                         }
15952
15953                         goto REPEAT;
15954                     }
15955                 }
15956             }
15957
15958             //
15959             // Update the switch jump table such that it follows jumps to jumps:
15960             //
15961             if (block->bbJumpKind == BBJ_SWITCH)
15962             {
15963                 if (fgOptimizeSwitchBranches(block))
15964                 {
15965                     change   = true;
15966                     modified = true;
15967                     goto REPEAT;
15968                 }
15969             }
15970
15971             noway_assert(!(block->bbFlags & BBF_REMOVED));
15972
15973             /* COMPACT blocks if possible */
15974
15975             if (fgCanCompactBlocks(block, bNext))
15976             {
15977                 fgCompactBlocks(block, bNext);
15978
15979                 /* we compacted two blocks - goto REPEAT to catch similar cases */
15980                 change   = true;
15981                 modified = true;
15982                 goto REPEAT;
15983             }
15984
15985             /* Remove unreachable or empty blocks - do not consider blocks marked BBF_DONT_REMOVE or genReturnBB block
15986              * These include first and last block of a TRY, exception handlers and RANGE_CHECK_FAIL THROW blocks */
15987
15988             if ((block->bbFlags & BBF_DONT_REMOVE) == BBF_DONT_REMOVE || block == genReturnBB)
15989             {
15990                 bPrev = block;
15991                 continue;
15992             }
15993
15994 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
15995             // Don't remove the BBJ_ALWAYS block of a BBJ_CALLFINALLY/BBJ_ALWAYS pair.
15996             if (block->countOfInEdges() == 0 && bPrev->bbJumpKind == BBJ_CALLFINALLY)
15997             {
15998                 assert(bPrev->isBBCallAlwaysPair());
15999                 noway_assert(!(bPrev->bbFlags & BBF_RETLESS_CALL));
16000                 noway_assert(block->bbJumpKind == BBJ_ALWAYS);
16001                 bPrev = block;
16002                 continue;
16003             }
16004 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16005
16006             noway_assert(!block->bbCatchTyp);
16007             noway_assert(!(block->bbFlags & BBF_TRY_BEG));
16008
16009             /* Remove unreachable blocks
16010              *
16011              * We'll look for blocks that have countOfInEdges() = 0 (blocks may become
16012              * unreachable due to a BBJ_ALWAYS introduced by conditional folding for example)
16013              */
16014
16015             if (block->countOfInEdges() == 0)
16016             {
16017                 /* no references -> unreachable - remove it */
16018                 /* For now do not update the bbNum, do it at the end */
16019
16020                 fgRemoveBlock(block, true);
16021
16022                 change   = true;
16023                 modified = true;
16024
16025                 /* we removed the current block - the rest of the optimizations won't have a target
16026                  * continue with the next one */
16027
16028                 continue;
16029             }
16030             else if (block->countOfInEdges() == 1)
16031             {
16032                 switch (block->bbJumpKind)
16033                 {
16034                     case BBJ_COND:
16035                     case BBJ_ALWAYS:
16036                         if (block->bbJumpDest == block)
16037                         {
16038                             fgRemoveBlock(block, true);
16039
16040                             change   = true;
16041                             modified = true;
16042
16043                             /* we removed the current block - the rest of the optimizations
16044                              * won't have a target so continue with the next block */
16045
16046                             continue;
16047                         }
16048                         break;
16049
16050                     default:
16051                         break;
16052                 }
16053             }
16054
16055             noway_assert(!(block->bbFlags & BBF_REMOVED));
16056
16057             /* Remove EMPTY blocks */
16058
16059             if (block->isEmpty())
16060             {
16061                 assert(bPrev == block->bbPrev);
16062                 if (fgOptimizeEmptyBlock(block))
16063                 {
16064                     change   = true;
16065                     modified = true;
16066                 }
16067
16068                 /* Have we removed the block? */
16069
16070                 if (block->bbFlags & BBF_REMOVED)
16071                 {
16072                     /* block was removed - no change to bPrev */
16073                     continue;
16074                 }
16075             }
16076
16077             /* Set the predecessor of the last reachable block
16078              * If we removed the current block, the predecessor remains unchanged
16079              * otherwise, since the current block is ok, it becomes the predecessor */
16080
16081             noway_assert(!(block->bbFlags & BBF_REMOVED));
16082
16083             bPrev = block;
16084         }
16085     } while (change);
16086
16087     fgNeedsUpdateFlowGraph = false;
16088
16089 #ifdef DEBUG
16090     if (verbose && modified)
16091     {
16092         printf("\nAfter updating the flow graph:\n");
16093         fgDispBasicBlocks(verboseTrees);
16094         fgDispHandlerTab();
16095     }
16096
16097     if (compRationalIRForm)
16098     {
16099         for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
16100         {
16101             LIR::AsRange(block).CheckLIR(this);
16102         }
16103     }
16104
16105     fgVerifyHandlerTab();
16106     // Make sure that the predecessor lists are accurate
16107     fgDebugCheckBBlist();
16108     fgDebugCheckUpdate();
16109 #endif // DEBUG
16110
16111     return modified;
16112 }
16113 #ifdef _PREFAST_
16114 #pragma warning(pop)
16115 #endif
16116
16117 /*****************************************************************************
16118  *  Check that the flow graph is really updated
16119  */
16120
16121 #ifdef DEBUG
16122
16123 void Compiler::fgDebugCheckUpdate()
16124 {
16125     if (!compStressCompile(STRESS_CHK_FLOW_UPDATE, 30))
16126     {
16127         return;
16128     }
16129
16130     /* We check for these conditions:
16131      * no unreachable blocks  -> no blocks have countOfInEdges() = 0
16132      * no empty blocks        -> no blocks have bbTreeList = 0
16133      * no un-imported blocks  -> no blocks have BBF_IMPORTED not set (this is
16134      *                           kind of redundand with the above, but to make sure)
16135      * no un-compacted blocks -> BBJ_NONE followed by block with no jumps to it (countOfInEdges() = 1)
16136      */
16137
16138     BasicBlock* prev;
16139     BasicBlock* block;
16140     for (prev = nullptr, block = fgFirstBB; block != nullptr; prev = block, block = block->bbNext)
16141     {
16142         /* no unreachable blocks */
16143
16144         if ((block->countOfInEdges() == 0) && !(block->bbFlags & BBF_DONT_REMOVE)
16145 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
16146             // With funclets, we never get rid of the BBJ_ALWAYS part of a BBJ_CALLFINALLY/BBJ_ALWAYS pair,
16147             // even if we can prove that the finally block never returns.
16148             && (prev == NULL || block->bbJumpKind != BBJ_ALWAYS || !prev->isBBCallAlwaysPair())
16149 #endif // FEATURE_EH_FUNCLETS
16150                 )
16151         {
16152             noway_assert(!"Unreachable block not removed!");
16153         }
16154
16155         /* no empty blocks */
16156
16157         if (block->isEmpty() && !(block->bbFlags & BBF_DONT_REMOVE))
16158         {
16159             switch (block->bbJumpKind)
16160             {
16161                 case BBJ_CALLFINALLY:
16162                 case BBJ_EHFINALLYRET:
16163                 case BBJ_EHFILTERRET:
16164                 case BBJ_RETURN:
16165                 /* for BBJ_ALWAYS is probably just a GOTO, but will have to be treated */
16166                 case BBJ_ALWAYS:
16167                 case BBJ_EHCATCHRET:
16168                     /* These jump kinds are allowed to have empty tree lists */
16169                     break;
16170
16171                 default:
16172                     /* it may be the case that the block had more than one reference to it
16173                      * so we couldn't remove it */
16174
16175                     if (block->countOfInEdges() == 0)
16176                     {
16177                         noway_assert(!"Empty block not removed!");
16178                     }
16179                     break;
16180             }
16181         }
16182
16183         /* no un-imported blocks */
16184
16185         if (!(block->bbFlags & BBF_IMPORTED))
16186         {
16187             /* internal blocks do not count */
16188
16189             if (!(block->bbFlags & BBF_INTERNAL))
16190             {
16191                 noway_assert(!"Non IMPORTED block not removed!");
16192             }
16193         }
16194
16195         bool prevIsCallAlwaysPair = ((prev != nullptr) && prev->isBBCallAlwaysPair());
16196
16197         // Check for an unnecessary jumps to the next block
16198         bool doAssertOnJumpToNextBlock = false; // unless we have a BBJ_COND or BBJ_ALWAYS we can not assert
16199
16200         if (block->bbJumpKind == BBJ_COND)
16201         {
16202             // A conditional branch should never jump to the next block
16203             // as it can be folded into a BBJ_NONE;
16204             doAssertOnJumpToNextBlock = true;
16205         }
16206         else if (block->bbJumpKind == BBJ_ALWAYS)
16207         {
16208             // Generally we will want to assert if a BBJ_ALWAYS branches to the next block
16209             doAssertOnJumpToNextBlock = true;
16210
16211             // If the BBF_KEEP_BBJ_ALWAYS flag is set we allow it to jump to the next block
16212             if (block->bbFlags & BBF_KEEP_BBJ_ALWAYS)
16213             {
16214                 doAssertOnJumpToNextBlock = false;
16215             }
16216
16217             // A call/always pair is also allowed to jump to the next block
16218             if (prevIsCallAlwaysPair)
16219             {
16220                 doAssertOnJumpToNextBlock = false;
16221             }
16222
16223             // We are allowed to have a branch from a hot 'block' to a cold 'bbNext'
16224             //
16225             if ((block->bbNext != nullptr) && fgInDifferentRegions(block, block->bbNext))
16226             {
16227                 doAssertOnJumpToNextBlock = false;
16228             }
16229         }
16230
16231         if (doAssertOnJumpToNextBlock)
16232         {
16233             if (block->bbJumpDest == block->bbNext)
16234             {
16235                 noway_assert(!"Unnecessary jump to the next block!");
16236             }
16237         }
16238
16239         /* Make sure BBF_KEEP_BBJ_ALWAYS is set correctly */
16240
16241         if ((block->bbJumpKind == BBJ_ALWAYS) && prevIsCallAlwaysPair)
16242         {
16243             noway_assert(block->bbFlags & BBF_KEEP_BBJ_ALWAYS);
16244         }
16245
16246         /* For a BBJ_CALLFINALLY block we make sure that we are followed by */
16247         /* an BBJ_ALWAYS block with BBF_INTERNAL set */
16248         /* or that it's a BBF_RETLESS_CALL */
16249         if (block->bbJumpKind == BBJ_CALLFINALLY)
16250         {
16251             assert((block->bbFlags & BBF_RETLESS_CALL) || block->isBBCallAlwaysPair());
16252         }
16253
16254         /* no un-compacted blocks */
16255
16256         if (fgCanCompactBlocks(block, block->bbNext))
16257         {
16258             noway_assert(!"Found un-compacted blocks!");
16259         }
16260     }
16261 }
16262
16263 #endif // DEBUG
16264
16265 /*****************************************************************************
16266  * We've inserted a new block before 'block' that should be part of the same EH region as 'block'.
16267  * Update the EH table to make this so. Also, set the new block to have the right EH region data
16268  * (copy the bbTryIndex, bbHndIndex, and bbCatchTyp from 'block' to the new predecessor, and clear
16269  * 'bbCatchTyp' from 'block').
16270  */
16271 void Compiler::fgExtendEHRegionBefore(BasicBlock* block)
16272 {
16273     assert(block->bbPrev != nullptr);
16274
16275     BasicBlock* bPrev = block->bbPrev;
16276
16277     bPrev->copyEHRegion(block);
16278
16279     // The first block (and only the first block) of a handler has bbCatchTyp set
16280     bPrev->bbCatchTyp = block->bbCatchTyp;
16281     block->bbCatchTyp = BBCT_NONE;
16282
16283     EHblkDsc* HBtab;
16284     EHblkDsc* HBtabEnd;
16285
16286     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++)
16287     {
16288         /* Multiple pointers in EHblkDsc can point to same block. We can not early out after the first match. */
16289         if (HBtab->ebdTryBeg == block)
16290         {
16291 #ifdef DEBUG
16292             if (verbose)
16293             {
16294                 printf("EH#%u: New first block of try: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
16295             }
16296 #endif // DEBUG
16297             HBtab->ebdTryBeg = bPrev;
16298             bPrev->bbFlags |= BBF_TRY_BEG | BBF_DONT_REMOVE | BBF_HAS_LABEL;
16299             // clear the TryBeg flag unless it begins another try region
16300             if (!bbIsTryBeg(block))
16301             {
16302                 block->bbFlags &= ~BBF_TRY_BEG;
16303             }
16304         }
16305
16306         if (HBtab->ebdHndBeg == block)
16307         {
16308 #ifdef DEBUG
16309             if (verbose)
16310             {
16311                 printf("EH#%u: New first block of handler: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
16312             }
16313 #endif // DEBUG
16314
16315             // The first block of a handler has an artificial extra refcount. Transfer that to the new block.
16316             assert(block->bbRefs > 0);
16317             block->bbRefs--;
16318
16319             HBtab->ebdHndBeg = bPrev;
16320             bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL;
16321             bPrev->bbRefs++;
16322
16323             // If this is a handler for a filter, the last block of the filter will end with
16324             // a BBJ_EJFILTERRET block that has a bbJumpDest that jumps to the first block of
16325             // it's handler.  So we need to update it to keep things in sync.
16326             //
16327             if (HBtab->HasFilter())
16328             {
16329                 BasicBlock* bFilterLast = HBtab->BBFilterLast();
16330                 assert(bFilterLast != nullptr);
16331                 assert(bFilterLast->bbJumpKind == BBJ_EHFILTERRET);
16332                 assert(bFilterLast->bbJumpDest == block);
16333 #ifdef DEBUG
16334                 if (verbose)
16335                 {
16336                     printf("EH#%u: Updating bbJumpDest for filter ret block: BB%02u => BB%02u\n", ehGetIndex(HBtab),
16337                            bFilterLast->bbNum, bPrev->bbNum);
16338                 }
16339 #endif // DEBUG
16340                 // Change the bbJumpDest for bFilterLast from the old first 'block' to the new first 'bPrev'
16341                 bFilterLast->bbJumpDest = bPrev;
16342             }
16343         }
16344
16345         if (HBtab->HasFilter() && (HBtab->ebdFilter == block))
16346         {
16347 #ifdef DEBUG
16348             if (verbose)
16349             {
16350                 printf("EH#%u: New first block of filter: BB%02u\n", ehGetIndex(HBtab), bPrev->bbNum);
16351             }
16352 #endif // DEBUG
16353
16354             // The first block of a filter has an artificial extra refcount. Transfer that to the new block.
16355             assert(block->bbRefs > 0);
16356             block->bbRefs--;
16357
16358             HBtab->ebdFilter = bPrev;
16359             bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL;
16360             bPrev->bbRefs++;
16361         }
16362     }
16363 }
16364
16365 /*****************************************************************************
16366  * We've inserted a new block after 'block' that should be part of the same EH region as 'block'.
16367  * Update the EH table to make this so. Also, set the new block to have the right EH region data.
16368  */
16369
16370 void Compiler::fgExtendEHRegionAfter(BasicBlock* block)
16371 {
16372     BasicBlock* newBlk = block->bbNext;
16373     assert(newBlk != nullptr);
16374
16375     newBlk->copyEHRegion(block);
16376     newBlk->bbCatchTyp =
16377         BBCT_NONE; // Only the first block of a catch has this set, and 'newBlk' can't be the first block of a catch.
16378
16379     // TODO-Throughput: if the block is not in an EH region, then we don't need to walk the EH table looking for 'last'
16380     // block pointers to update.
16381     ehUpdateLastBlocks(block, newBlk);
16382 }
16383
16384 /*****************************************************************************
16385  *
16386  * Insert a BasicBlock before the given block.
16387  */
16388
16389 BasicBlock* Compiler::fgNewBBbefore(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion)
16390 {
16391     // Create a new BasicBlock and chain it in
16392
16393     BasicBlock* newBlk = bbNewBasicBlock(jumpKind);
16394     newBlk->bbFlags |= BBF_INTERNAL;
16395
16396     fgInsertBBbefore(block, newBlk);
16397
16398     newBlk->bbRefs = 0;
16399
16400     if (newBlk->bbFallsThrough() && block->isRunRarely())
16401     {
16402         newBlk->bbSetRunRarely();
16403     }
16404
16405     if (extendRegion)
16406     {
16407         fgExtendEHRegionBefore(block);
16408     }
16409     else
16410     {
16411         // When extendRegion is false the caller is responsible for setting these two values
16412         newBlk->setTryIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
16413         newBlk->setHndIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
16414     }
16415
16416     // We assume that if the block we are inserting before is in the cold region, then this new
16417     // block will also be in the cold region.
16418     newBlk->bbFlags |= (block->bbFlags & BBF_COLD);
16419
16420     return newBlk;
16421 }
16422
16423 /*****************************************************************************
16424  *
16425  * Insert a BasicBlock after the given block.
16426  */
16427
16428 BasicBlock* Compiler::fgNewBBafter(BBjumpKinds jumpKind, BasicBlock* block, bool extendRegion)
16429 {
16430     // Create a new BasicBlock and chain it in
16431
16432     BasicBlock* newBlk = bbNewBasicBlock(jumpKind);
16433     newBlk->bbFlags |= BBF_INTERNAL;
16434
16435     fgInsertBBafter(block, newBlk);
16436
16437     newBlk->bbRefs = 0;
16438
16439     if (block->bbFallsThrough() && block->isRunRarely())
16440     {
16441         newBlk->bbSetRunRarely();
16442     }
16443
16444     if (extendRegion)
16445     {
16446         fgExtendEHRegionAfter(block);
16447     }
16448     else
16449     {
16450         // When extendRegion is false the caller is responsible for setting these two values
16451         newBlk->setTryIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
16452         newBlk->setHndIndex(MAX_XCPTN_INDEX); // Note: this is still a legal index, just unlikely
16453     }
16454
16455     // If the new block is in the cold region (because the block we are inserting after
16456     // is in the cold region), mark it as such.
16457     newBlk->bbFlags |= (block->bbFlags & BBF_COLD);
16458
16459     return newBlk;
16460 }
16461
16462 /*****************************************************************************
16463  *  Inserts basic block before existing basic block.
16464  *
16465  *  If insertBeforeBlk is in the funclet region, then newBlk will be in the funclet region.
16466  *  (If insertBeforeBlk is the first block of the funclet region, then 'newBlk' will be the
16467  *  new first block of the funclet region.)
16468  */
16469 void Compiler::fgInsertBBbefore(BasicBlock* insertBeforeBlk, BasicBlock* newBlk)
16470 {
16471     if (insertBeforeBlk->bbPrev)
16472     {
16473         fgInsertBBafter(insertBeforeBlk->bbPrev, newBlk);
16474     }
16475     else
16476     {
16477         newBlk->setNext(fgFirstBB);
16478
16479         fgFirstBB      = newBlk;
16480         newBlk->bbPrev = nullptr;
16481     }
16482
16483 #if FEATURE_EH_FUNCLETS
16484
16485     /* Update fgFirstFuncletBB if insertBeforeBlk is the first block of the funclet region. */
16486
16487     if (fgFirstFuncletBB == insertBeforeBlk)
16488     {
16489         fgFirstFuncletBB = newBlk;
16490     }
16491
16492 #endif // FEATURE_EH_FUNCLETS
16493 }
16494
16495 /*****************************************************************************
16496  *  Inserts basic block after existing basic block.
16497  *
16498  *  If insertBeforeBlk is in the funclet region, then newBlk will be in the funclet region.
16499  *  (It can't be used to insert a block as the first block of the funclet region).
16500  */
16501 void Compiler::fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk)
16502 {
16503     newBlk->bbNext = insertAfterBlk->bbNext;
16504
16505     if (insertAfterBlk->bbNext)
16506     {
16507         insertAfterBlk->bbNext->bbPrev = newBlk;
16508     }
16509
16510     insertAfterBlk->bbNext = newBlk;
16511     newBlk->bbPrev         = insertAfterBlk;
16512
16513     if (fgLastBB == insertAfterBlk)
16514     {
16515         fgLastBB = newBlk;
16516         assert(fgLastBB->bbNext == nullptr);
16517     }
16518 }
16519
16520 // We have two edges (bAlt => bCur) and (bCur => bNext).
16521 //
16522 // Returns true if the weight of (bAlt => bCur)
16523 //  is greater than the weight of (bCur => bNext).
16524 // We compare the edge weights if we have valid edge weights
16525 //  otherwise we compare blocks weights.
16526 //
16527 bool Compiler::fgIsBetterFallThrough(BasicBlock* bCur, BasicBlock* bAlt)
16528 {
16529     // bCur can't be NULL and must be a fall through bbJumpKind
16530     noway_assert(bCur != nullptr);
16531     noway_assert(bCur->bbFallsThrough());
16532     noway_assert(bAlt != nullptr);
16533
16534     // We only handle the cases when bAlt is a BBJ_ALWAYS or a BBJ_COND
16535     if ((bAlt->bbJumpKind != BBJ_ALWAYS) && (bAlt->bbJumpKind != BBJ_COND))
16536     {
16537         return false;
16538     }
16539
16540     // if bAlt doesn't jump to bCur it can't be a better fall through than bCur
16541     if (bAlt->bbJumpDest != bCur)
16542     {
16543         return false;
16544     }
16545
16546     // Currently bNext is the fall through for bCur
16547     BasicBlock* bNext = bCur->bbNext;
16548     noway_assert(bNext != nullptr);
16549
16550     // We will set result to true if bAlt is a better fall through than bCur
16551     bool result;
16552     if (fgHaveValidEdgeWeights)
16553     {
16554         // We will compare the edge weight for our two choices
16555         flowList* edgeFromAlt = fgGetPredForBlock(bCur, bAlt);
16556         flowList* edgeFromCur = fgGetPredForBlock(bNext, bCur);
16557         noway_assert(edgeFromCur != nullptr);
16558         noway_assert(edgeFromAlt != nullptr);
16559
16560         result = (edgeFromAlt->flEdgeWeightMin > edgeFromCur->flEdgeWeightMax);
16561     }
16562     else
16563     {
16564         if (bAlt->bbJumpKind == BBJ_ALWAYS)
16565         {
16566             // Our result is true if bAlt's weight is more than bCur's weight
16567             result = (bAlt->bbWeight > bCur->bbWeight);
16568         }
16569         else
16570         {
16571             noway_assert(bAlt->bbJumpKind == BBJ_COND);
16572             // Our result is true if bAlt's weight is more than twice bCur's weight
16573             result = (bAlt->bbWeight > (2 * bCur->bbWeight));
16574         }
16575     }
16576     return result;
16577 }
16578
16579 //------------------------------------------------------------------------
16580 // fgCheckEHCanInsertAfterBlock: Determine if a block can be inserted after
16581 // 'blk' and legally be put in the EH region specified by 'regionIndex'. This
16582 // can be true if the most nested region the block is in is already 'regionIndex',
16583 // as we'll just extend the most nested region (and any region ending at the same block).
16584 // It can also be true if it is the end of (a set of) EH regions, such that
16585 // inserting the block and properly extending some EH regions (if necessary)
16586 // puts the block in the correct region. We only consider the case of extending
16587 // an EH region after 'blk' (that is, to include 'blk' and the newly insert block);
16588 // we don't consider inserting a block as the the first block of an EH region following 'blk'.
16589 //
16590 // Consider this example:
16591 //
16592 //      try3   try2   try1
16593 //      |---   |      |      BB01
16594 //      |      |---   |      BB02
16595 //      |      |      |---   BB03
16596 //      |      |      |      BB04
16597 //      |      |---   |---   BB05
16598 //      |                    BB06
16599 //      |-----------------   BB07
16600 //
16601 // Passing BB05 and try1/try2/try3 as the region to insert into (as well as putInTryRegion==true)
16602 // will all return 'true'. Here are the cases:
16603 // 1. Insert into try1: the most nested EH region BB05 is in is already try1, so we can insert after
16604 //    it and extend try1 (and try2).
16605 // 2. Insert into try2: we can extend try2, but leave try1 alone.
16606 // 3. Insert into try3: we can leave try1 and try2 alone, and put the new block just in try3. Note that
16607 //    in this case, after we "loop outwards" in the EH nesting, we get to a place where we're in the middle
16608 //    of the try3 region, not at the end of it.
16609 // In all cases, it is possible to put a block after BB05 and put it in any of these three 'try' regions legally.
16610 //
16611 // Filters are ignored; if 'blk' is in a filter, the answer will be false.
16612 //
16613 // Arguments:
16614 //    blk - the BasicBlock we are checking to see if we can insert after.
16615 //    regionIndex - the EH region we want to insert a block into. regionIndex is
16616 //          in the range [0..compHndBBtabCount]; 0 means "main method".
16617 //    putInTryRegion - 'true' if the new block should be inserted in the 'try' region of 'regionIndex'.
16618 //          For regionIndex 0 (the "main method"), this should be 'true'.
16619 //
16620 // Return Value:
16621 //    'true' if a block can be inserted after 'blk' and put in EH region 'regionIndex', else 'false'.
16622 //
16623 bool Compiler::fgCheckEHCanInsertAfterBlock(BasicBlock* blk, unsigned regionIndex, bool putInTryRegion)
16624 {
16625     assert(blk != nullptr);
16626     assert(regionIndex <= compHndBBtabCount);
16627
16628     if (regionIndex == 0)
16629     {
16630         assert(putInTryRegion);
16631     }
16632
16633     bool     inTryRegion;
16634     unsigned nestedRegionIndex = ehGetMostNestedRegionIndex(blk, &inTryRegion);
16635
16636     bool insertOK = true;
16637     for (;;)
16638     {
16639         if (nestedRegionIndex == regionIndex)
16640         {
16641             // This block is in the region we want to be in. We can insert here if it's the right type of region.
16642             // (If we want to be in the 'try' region, but the block is in the handler region, then inserting a
16643             // new block after 'blk' can't put it in the 'try' region, and vice-versa, since we only consider
16644             // extending regions after, not prepending to regions.)
16645             // This check will be 'true' if we are trying to put something in the main function (as putInTryRegion
16646             // must be 'true' if regionIndex is zero, and inTryRegion will also be 'true' if nestedRegionIndex is zero).
16647             insertOK = (putInTryRegion == inTryRegion);
16648             break;
16649         }
16650         else if (nestedRegionIndex == 0)
16651         {
16652             // The block is in the main function, but we want to put something in a nested region. We can't do that.
16653             insertOK = false;
16654             break;
16655         }
16656
16657         assert(nestedRegionIndex > 0);
16658         EHblkDsc* ehDsc = ehGetDsc(nestedRegionIndex - 1); // ehGetDsc uses [0..compHndBBtabCount) form.
16659
16660         if (inTryRegion)
16661         {
16662             if (blk != ehDsc->ebdTryLast)
16663             {
16664                 // Not the last block? Then it must be somewhere else within the try region, so we can't insert here.
16665                 insertOK = false;
16666                 break; // exit the 'for' loop
16667             }
16668         }
16669         else
16670         {
16671             // We ignore filters.
16672             if (blk != ehDsc->ebdHndLast)
16673             {
16674                 // Not the last block? Then it must be somewhere else within the handler region, so we can't insert
16675                 // here.
16676                 insertOK = false;
16677                 break; // exit the 'for' loop
16678             }
16679         }
16680
16681         // Things look good for this region; check the enclosing regions, if any.
16682
16683         nestedRegionIndex =
16684             ehGetEnclosingRegionIndex(nestedRegionIndex - 1,
16685                                       &inTryRegion); // ehGetEnclosingRegionIndex uses [0..compHndBBtabCount) form.
16686
16687         // Convert to [0..compHndBBtabCount] form.
16688         nestedRegionIndex = (nestedRegionIndex == EHblkDsc::NO_ENCLOSING_INDEX) ? 0 : nestedRegionIndex + 1;
16689     } // end of for(;;)
16690
16691     return insertOK;
16692 }
16693
16694 //------------------------------------------------------------------------
16695 // Finds the block closest to endBlk in the range [startBlk..endBlk) after which a block can be
16696 // inserted easily. Note that endBlk cannot be returned; its predecessor is the last block that can
16697 // be returned. The new block will be put in an EH region described by the arguments regionIndex,
16698 // putInTryRegion, startBlk, and endBlk (explained below), so it must be legal to place to put the
16699 // new block after the insertion location block, give it the specified EH region index, and not break
16700 // EH nesting rules. This function is careful to choose a block in the correct EH region. However,
16701 // it assumes that the new block can ALWAYS be placed at the end (just before endBlk). That means
16702 // that the caller must ensure that is true.
16703 //
16704 // Below are the possible cases for the arguments to this method:
16705 //      1. putInTryRegion == true and regionIndex > 0:
16706 //         Search in the try region indicated by regionIndex.
16707 //      2. putInTryRegion == false and regionIndex > 0:
16708 //         a. If startBlk is the first block of a filter and endBlk is the block after the end of the
16709 //            filter (that is, the startBlk and endBlk match a filter bounds exactly), then choose a
16710 //            location within this filter region. (Note that, due to IL rules, filters do not have any
16711 //            EH nested within them.) Otherwise, filters are skipped.
16712 //         b. Else, search in the handler region indicated by regionIndex.
16713 //      3. regionIndex = 0:
16714 //         Search in the entire main method, excluding all EH regions. In this case, putInTryRegion must be true.
16715 //
16716 // This method makes sure to find an insertion point which would not cause the inserted block to
16717 // be put inside any inner try/filter/handler regions.
16718 //
16719 // The actual insertion occurs after the returned block. Note that the returned insertion point might
16720 // be the last block of a more nested EH region, because the new block will be inserted after the insertion
16721 // point, and will not extend the more nested EH region. For example:
16722 //
16723 //      try3   try2   try1
16724 //      |---   |      |      BB01
16725 //      |      |---   |      BB02
16726 //      |      |      |---   BB03
16727 //      |      |      |      BB04
16728 //      |      |---   |---   BB05
16729 //      |                    BB06
16730 //      |-----------------   BB07
16731 //
16732 // for regionIndex==try3, putInTryRegion==true, we might return BB05, even though BB05 will have a try index
16733 // for try1 (the most nested 'try' region the block is in). That's because when we insert after BB05, the new
16734 // block will be in the correct, desired EH region, since try1 and try2 regions will not be extended to include
16735 // the inserted block. Furthermore, for regionIndex==try2, putInTryRegion==true, we can also return BB05. In this
16736 // case, when the new block is inserted, the try1 region remains the same, but we need extend region 'try2' to
16737 // include the inserted block. (We also need to check all parent regions as well, just in case any parent regions
16738 // also end on the same block, in which case we would also need to extend the parent regions. This is standard
16739 // procedure when inserting a block at the end of an EH region.)
16740 //
16741 // If nearBlk is non-nullptr then we return the closest block after nearBlk that will work best.
16742 //
16743 // We try to find a block in the appropriate region that is not a fallthrough block, so we can insert after it
16744 // without the need to insert a jump around the inserted block.
16745 //
16746 // Note that regionIndex is numbered the same as BasicBlock::bbTryIndex and BasicBlock::bbHndIndex, that is, "0" is
16747 // "main method" and otherwise is +1 from normal, so we can call, e.g., ehGetDsc(tryIndex - 1).
16748 //
16749 // Arguments:
16750 //    regionIndex - the region index where the new block will be inserted. Zero means entire method;
16751 //          non-zero means either a "try" or a "handler" region, depending on what putInTryRegion says.
16752 //    putInTryRegion - 'true' to put the block in the 'try' region corresponding to 'regionIndex', 'false'
16753 //          to put the block in the handler region. Should be 'true' if regionIndex==0.
16754 //    startBlk - start block of range to search.
16755 //    endBlk - end block of range to search (don't include this block in the range). Can be nullptr to indicate
16756 //          the end of the function.
16757 //    nearBlk - If non-nullptr, try to find an insertion location closely after this block. If nullptr, we insert
16758 //          at the best location found towards the end of the acceptable block range.
16759 //    jumpBlk - When nearBlk is set, this can be set to the block which jumps to bNext->bbNext (TODO: need to review
16760 //    this?)
16761 //    runRarely - true if the block being inserted is expected to be rarely run. This helps determine
16762 //          the best place to put the new block, by putting in a place that has the same 'rarely run' characteristic.
16763 //
16764 // Return Value:
16765 //    A block with the desired characteristics, so the new block will be inserted after this one.
16766 //    If there is no suitable location, return nullptr. This should basically never happen.
16767
16768 BasicBlock* Compiler::fgFindInsertPoint(unsigned    regionIndex,
16769                                         bool        putInTryRegion,
16770                                         BasicBlock* startBlk,
16771                                         BasicBlock* endBlk,
16772                                         BasicBlock* nearBlk,
16773                                         BasicBlock* jumpBlk,
16774                                         bool        runRarely)
16775 {
16776     noway_assert(startBlk != nullptr);
16777     noway_assert(startBlk != endBlk);
16778     noway_assert((regionIndex == 0 && putInTryRegion) || // Search in the main method
16779                  (putInTryRegion && regionIndex > 0 &&
16780                   startBlk->bbTryIndex == regionIndex) || // Search in the specified try     region
16781                  (!putInTryRegion && regionIndex > 0 &&
16782                   startBlk->bbHndIndex == regionIndex)); // Search in the specified handler region
16783
16784 #ifdef DEBUG
16785     // Assert that startBlk precedes endBlk in the block list.
16786     // We don't want to use bbNum to assert this condition, as we cannot depend on the block numbers being
16787     // sequential at all times.
16788     for (BasicBlock* b = startBlk; b != endBlk; b = b->bbNext)
16789     {
16790         assert(b != nullptr); // We reached the end of the block list, but never found endBlk.
16791     }
16792 #endif // DEBUG
16793
16794     JITDUMP("fgFindInsertPoint(regionIndex=%u, putInTryRegion=%s, startBlk=BB%02u, endBlk=BB%02u, nearBlk=BB%02u, "
16795             "jumpBlk=BB%02u, runRarely=%s)\n",
16796             regionIndex, dspBool(putInTryRegion), startBlk->bbNum, (endBlk == nullptr) ? 0 : endBlk->bbNum,
16797             (nearBlk == nullptr) ? 0 : nearBlk->bbNum, (jumpBlk == nullptr) ? 0 : jumpBlk->bbNum, dspBool(runRarely));
16798
16799     bool        reachedNear = false; // Have we reached 'nearBlk' in our search? If not, we'll keep searching.
16800     bool        inFilter    = false; // Are we in a filter region that we need to skip?
16801     BasicBlock* bestBlk =
16802         nullptr; // Set to the best insertion point we've found so far that meets all the EH requirements.
16803     BasicBlock* goodBlk =
16804         nullptr; // Set to an acceptable insertion point that we'll use if we don't find a 'best' option.
16805     BasicBlock* blk;
16806
16807     if (nearBlk != nullptr)
16808     {
16809         // Does the nearBlk precede the startBlk?
16810         for (blk = nearBlk; blk != nullptr; blk = blk->bbNext)
16811         {
16812             if (blk == startBlk)
16813             {
16814                 reachedNear = true;
16815                 break;
16816             }
16817             else if (blk == endBlk)
16818             {
16819                 break;
16820             }
16821         }
16822     }
16823
16824     for (blk = startBlk; blk != endBlk; blk = blk->bbNext)
16825     {
16826         // The only way (blk == nullptr) could be true is if the caller passed an endBlk that preceded startBlk in the
16827         // block list, or if endBlk isn't in the block list at all. In DEBUG, we'll instead hit the similar
16828         // well-formedness assert earlier in this function.
16829         noway_assert(blk != nullptr);
16830
16831         if (blk == nearBlk)
16832         {
16833             reachedNear = true;
16834         }
16835
16836         if (blk->bbCatchTyp == BBCT_FILTER)
16837         {
16838             // Record the fact that we entered a filter region, so we don't insert into filters...
16839             // Unless the caller actually wanted the block inserted in this exact filter region.
16840             // Detect this by the fact that startBlk and endBlk point to the filter begin and end.
16841             if (putInTryRegion || (blk != startBlk) || (startBlk != ehGetDsc(regionIndex - 1)->ebdFilter) ||
16842                 (endBlk != ehGetDsc(regionIndex - 1)->ebdHndBeg))
16843             {
16844                 inFilter = true;
16845             }
16846         }
16847         else if (blk->bbCatchTyp == BBCT_FILTER_HANDLER)
16848         {
16849             // Record the fact that we exited a filter region.
16850             inFilter = false;
16851         }
16852
16853         // Don't insert a block inside this filter region.
16854         if (inFilter)
16855         {
16856             continue;
16857         }
16858
16859         // Note that the new block will be inserted AFTER "blk". We check to make sure that doing so
16860         // would put the block in the correct EH region. We make an assumption here that you can
16861         // ALWAYS insert the new block before "endBlk" (that is, at the end of the search range)
16862         // and be in the correct EH region. This is must be guaranteed by the caller (as it is by
16863         // fgNewBBinRegion(), which passes the search range as an exact EH region block range).
16864         // Because of this assumption, we only check the EH information for blocks before the last block.
16865         if (blk->bbNext != endBlk)
16866         {
16867             // We are in the middle of the search range. We can't insert the new block in
16868             // an inner try or handler region. We can, however, set the insertion
16869             // point to the last block of an EH try/handler region, if the enclosing
16870             // region is the region we wish to insert in. (Since multiple regions can
16871             // end at the same block, we need to search outwards, checking that the
16872             // block is the last block of every EH region out to the region we want
16873             // to insert in.) This is especially useful for putting a call-to-finally
16874             // block on AMD64 immediately after its corresponding 'try' block, so in the
16875             // common case, we'll just fall through to it. For example:
16876             //
16877             //      BB01
16878             //      BB02 -- first block of try
16879             //      BB03
16880             //      BB04 -- last block of try
16881             //      BB05 -- first block of finally
16882             //      BB06
16883             //      BB07 -- last block of handler
16884             //      BB08
16885             //
16886             // Assume there is only one try/finally, so BB01 and BB08 are in the "main function".
16887             // For AMD64 call-to-finally, we'll want to insert the BBJ_CALLFINALLY in
16888             // the main function, immediately after BB04. This allows us to do that.
16889
16890             if (!fgCheckEHCanInsertAfterBlock(blk, regionIndex, putInTryRegion))
16891             {
16892                 // Can't insert here.
16893                 continue;
16894             }
16895         }
16896
16897         // Look for an insert location:
16898         // 1. We want blocks that don't end with a fall through,
16899         // 2. Also, when blk equals nearBlk we may want to insert here.
16900         if (!blk->bbFallsThrough() || (blk == nearBlk))
16901         {
16902             bool updateBestBlk = true; // We will probably update the bestBlk
16903
16904             // If blk falls through then we must decide whether to use the nearBlk
16905             // hint
16906             if (blk->bbFallsThrough())
16907             {
16908                 noway_assert(blk == nearBlk);
16909                 if (jumpBlk != nullptr)
16910                 {
16911                     updateBestBlk = fgIsBetterFallThrough(blk, jumpBlk);
16912                 }
16913                 else
16914                 {
16915                     updateBestBlk = false;
16916                 }
16917             }
16918
16919             // If we already have a best block, see if the 'runRarely' flags influences
16920             // our choice. If we want a runRarely insertion point, and the existing best
16921             // block is run rarely but the current block isn't run rarely, then don't
16922             // update the best block.
16923             // TODO-CQ: We should also handle the reverse case, where runRarely is false (we
16924             // want a non-rarely-run block), but bestBlock->isRunRarely() is true. In that
16925             // case, we should update the block, also. Probably what we want is:
16926             //    (bestBlk->isRunRarely() != runRarely) && (blk->isRunRarely() == runRarely)
16927             if (updateBestBlk && (bestBlk != nullptr) && runRarely && bestBlk->isRunRarely() && !blk->isRunRarely())
16928             {
16929                 updateBestBlk = false;
16930             }
16931
16932             if (updateBestBlk)
16933             {
16934                 // We found a 'best' insertion location, so save it away.
16935                 bestBlk = blk;
16936
16937                 // If we've reached nearBlk, we've satisfied all the criteria,
16938                 // so we're done.
16939                 if (reachedNear)
16940                 {
16941                     goto DONE;
16942                 }
16943
16944                 // If we haven't reached nearBlk, keep looking for a 'best' location, just
16945                 // in case we'll find one at or after nearBlk. If no nearBlk was specified,
16946                 // we prefer inserting towards the end of the given range, so keep looking
16947                 // for more acceptable insertion locations.
16948             }
16949         }
16950
16951         // No need to update goodBlk after we have set bestBlk, but we could still find a better
16952         // bestBlk, so keep looking.
16953         if (bestBlk != nullptr)
16954         {
16955             continue;
16956         }
16957
16958         // Set the current block as a "good enough" insertion point, if it meets certain criteria.
16959         // We'll return this block if we don't find a "best" block in the search range. The block
16960         // can't be a BBJ_CALLFINALLY of a BBJ_CALLFINALLY/BBJ_ALWAYS pair (since we don't want
16961         // to insert anything between these two blocks). Otherwise, we can use it. However,
16962         // if we'd previously chosen a BBJ_COND block, then we'd prefer the "good" block to be
16963         // something else. We keep updating it until we've reached the 'nearBlk', to push it as
16964         // close to endBlk as possible.
16965         if (!blk->isBBCallAlwaysPair())
16966         {
16967             if (goodBlk == nullptr)
16968             {
16969                 goodBlk = blk;
16970             }
16971             else if ((goodBlk->bbJumpKind == BBJ_COND) || (blk->bbJumpKind != BBJ_COND))
16972             {
16973                 if ((blk == nearBlk) || !reachedNear)
16974                 {
16975                     goodBlk = blk;
16976                 }
16977             }
16978         }
16979     }
16980
16981     // If we didn't find a non-fall_through block, then insert at the last good block.
16982
16983     if (bestBlk == nullptr)
16984     {
16985         bestBlk = goodBlk;
16986     }
16987
16988 DONE:;
16989
16990     return bestBlk;
16991 }
16992
16993 //------------------------------------------------------------------------
16994 // Creates a new BasicBlock and inserts it in a specific EH region, given by 'tryIndex', 'hndIndex', and 'putInFilter'.
16995 //
16996 // If 'putInFilter' it true, then the block is inserted in the filter region given by 'hndIndex'. In this case, tryIndex
16997 // must be a less nested EH region (that is, tryIndex > hndIndex).
16998 //
16999 // Otherwise, the block is inserted in either the try region or the handler region, depending on which one is the inner
17000 // region. In other words, if the try region indicated by tryIndex is nested in the handler region indicated by
17001 // hndIndex,
17002 // then the new BB will be created in the try region. Vice versa.
17003 //
17004 // Note that tryIndex and hndIndex are numbered the same as BasicBlock::bbTryIndex and BasicBlock::bbHndIndex, that is,
17005 // "0" is "main method" and otherwise is +1 from normal, so we can call, e.g., ehGetDsc(tryIndex - 1).
17006 //
17007 // To be more specific, this function will create a new BB in one of the following 5 regions (if putInFilter is false):
17008 // 1. When tryIndex = 0 and hndIndex = 0:
17009 //    The new BB will be created in the method region.
17010 // 2. When tryIndex != 0 and hndIndex = 0:
17011 //    The new BB will be created in the try region indicated by tryIndex.
17012 // 3. When tryIndex == 0 and hndIndex != 0:
17013 //    The new BB will be created in the handler region indicated by hndIndex.
17014 // 4. When tryIndex != 0 and hndIndex != 0 and tryIndex < hndIndex:
17015 //    In this case, the try region is nested inside the handler region. Therefore, the new BB will be created
17016 //    in the try region indicated by tryIndex.
17017 // 5. When tryIndex != 0 and hndIndex != 0 and tryIndex > hndIndex:
17018 //    In this case, the handler region is nested inside the try region. Therefore, the new BB will be created
17019 //    in the handler region indicated by hndIndex.
17020 //
17021 // Note that if tryIndex != 0 and hndIndex != 0 then tryIndex must not be equal to hndIndex (this makes sense because
17022 // if they are equal, you are asking to put the new block in both the try and handler, which is impossible).
17023 //
17024 // The BasicBlock will not be inserted inside an EH region that is more nested than the requested tryIndex/hndIndex
17025 // region (so the function is careful to skip more nested EH regions when searching for a place to put the new block).
17026 //
17027 // This function cannot be used to insert a block as the first block of any region. It always inserts a block after
17028 // an existing block in the given region.
17029 //
17030 // If nearBlk is nullptr, or the block is run rarely, then the new block is assumed to be run rarely.
17031 //
17032 // Arguments:
17033 //    jumpKind - the jump kind of the new block to create.
17034 //    tryIndex - the try region to insert the new block in, described above. This must be a number in the range
17035 //               [0..compHndBBtabCount].
17036 //    hndIndex - the handler region to insert the new block in, described above. This must be a number in the range
17037 //               [0..compHndBBtabCount].
17038 //    nearBlk  - insert the new block closely after this block, if possible. If nullptr, put the new block anywhere
17039 //               in the requested region.
17040 //    putInFilter - put the new block in the filter region given by hndIndex, as described above.
17041 //    runRarely - 'true' if the new block is run rarely.
17042 //    insertAtEnd - 'true' if the block should be inserted at the end of the region. Note: this is currently only
17043 //                  implemented when inserting into the main function (not into any EH region).
17044 //
17045 // Return Value:
17046 //    The new block.
17047
17048 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind,
17049                                       unsigned    tryIndex,
17050                                       unsigned    hndIndex,
17051                                       BasicBlock* nearBlk,
17052                                       bool        putInFilter /* = false */,
17053                                       bool        runRarely /* = false */,
17054                                       bool        insertAtEnd /* = false */)
17055 {
17056     assert(tryIndex <= compHndBBtabCount);
17057     assert(hndIndex <= compHndBBtabCount);
17058
17059     /* afterBlk is the block which will precede the newBB */
17060     BasicBlock* afterBlk;
17061
17062     // start and end limit for inserting the block
17063     BasicBlock* startBlk = nullptr;
17064     BasicBlock* endBlk   = nullptr;
17065
17066     bool     putInTryRegion = true;
17067     unsigned regionIndex    = 0;
17068
17069     // First, figure out which region (the "try" region or the "handler" region) to put the newBB in.
17070     if ((tryIndex == 0) && (hndIndex == 0))
17071     {
17072         assert(!putInFilter);
17073
17074         endBlk = fgEndBBAfterMainFunction(); // don't put new BB in funclet region
17075
17076         if (insertAtEnd || (nearBlk == nullptr))
17077         {
17078             /* We'll just insert the block at the end of the method, before the funclets */
17079
17080             afterBlk = fgLastBBInMainFunction();
17081             goto _FoundAfterBlk;
17082         }
17083         else
17084         {
17085             // We'll search through the entire method
17086             startBlk = fgFirstBB;
17087         }
17088
17089         noway_assert(regionIndex == 0);
17090     }
17091     else
17092     {
17093         noway_assert(tryIndex > 0 || hndIndex > 0);
17094         PREFIX_ASSUME(tryIndex <= compHndBBtabCount);
17095         PREFIX_ASSUME(hndIndex <= compHndBBtabCount);
17096
17097         // Decide which region to put in, the "try" region or the "handler" region.
17098         if (tryIndex == 0)
17099         {
17100             noway_assert(hndIndex > 0);
17101             putInTryRegion = false;
17102         }
17103         else if (hndIndex == 0)
17104         {
17105             noway_assert(tryIndex > 0);
17106             noway_assert(putInTryRegion);
17107             assert(!putInFilter);
17108         }
17109         else
17110         {
17111             noway_assert(tryIndex > 0 && hndIndex > 0 && tryIndex != hndIndex);
17112             putInTryRegion = (tryIndex < hndIndex);
17113         }
17114
17115         if (putInTryRegion)
17116         {
17117             // Try region is the inner region.
17118             // In other words, try region must be nested inside the handler region.
17119             noway_assert(hndIndex == 0 || bbInHandlerRegions(hndIndex - 1, ehGetDsc(tryIndex - 1)->ebdTryBeg));
17120             assert(!putInFilter);
17121         }
17122         else
17123         {
17124             // Handler region is the inner region.
17125             // In other words, handler region must be nested inside the try region.
17126             noway_assert(tryIndex == 0 || bbInTryRegions(tryIndex - 1, ehGetDsc(hndIndex - 1)->ebdHndBeg));
17127         }
17128
17129         // Figure out the start and end block range to search for an insertion location. Pick the beginning and
17130         // ending blocks of the target EH region (the 'endBlk' is one past the last block of the EH region, to make
17131         // loop iteration easier). Note that, after funclets have been created (for FEATURE_EH_FUNCLETS),
17132         // this linear block range will not include blocks of handlers for try/handler clauses nested within
17133         // this EH region, as those blocks have been extracted as funclets. That is ok, though, because we don't
17134         // want to insert a block in any nested EH region.
17135
17136         if (putInTryRegion)
17137         {
17138             // We will put the newBB in the try region.
17139             EHblkDsc* ehDsc = ehGetDsc(tryIndex - 1);
17140             startBlk        = ehDsc->ebdTryBeg;
17141             endBlk          = ehDsc->ebdTryLast->bbNext;
17142             regionIndex     = tryIndex;
17143         }
17144         else if (putInFilter)
17145         {
17146             // We will put the newBB in the filter region.
17147             EHblkDsc* ehDsc = ehGetDsc(hndIndex - 1);
17148             startBlk        = ehDsc->ebdFilter;
17149             endBlk          = ehDsc->ebdHndBeg;
17150             regionIndex     = hndIndex;
17151         }
17152         else
17153         {
17154             // We will put the newBB in the handler region.
17155             EHblkDsc* ehDsc = ehGetDsc(hndIndex - 1);
17156             startBlk        = ehDsc->ebdHndBeg;
17157             endBlk          = ehDsc->ebdHndLast->bbNext;
17158             regionIndex     = hndIndex;
17159         }
17160
17161         noway_assert(regionIndex > 0);
17162     }
17163
17164     // Now find the insertion point.
17165     afterBlk = fgFindInsertPoint(regionIndex, putInTryRegion, startBlk, endBlk, nearBlk, nullptr, runRarely);
17166
17167 _FoundAfterBlk:;
17168
17169     /* We have decided to insert the block after 'afterBlk'. */
17170     noway_assert(afterBlk != nullptr);
17171
17172     JITDUMP("fgNewBBinRegion(jumpKind=%u, tryIndex=%u, hndIndex=%u, putInFilter=%s, runRarely=%s, insertAtEnd=%s): "
17173             "inserting after BB%02u\n",
17174             jumpKind, tryIndex, hndIndex, dspBool(putInFilter), dspBool(runRarely), dspBool(insertAtEnd),
17175             afterBlk->bbNum);
17176
17177     return fgNewBBinRegionWorker(jumpKind, afterBlk, regionIndex, putInTryRegion);
17178 }
17179
17180 //------------------------------------------------------------------------
17181 // Creates a new BasicBlock and inserts it in the same EH region as 'srcBlk'.
17182 //
17183 // See the implementation of fgNewBBinRegion() used by this one for more notes.
17184 //
17185 // Arguments:
17186 //    jumpKind - the jump kind of the new block to create.
17187 //    srcBlk   - insert the new block in the same EH region as this block, and closely after it if possible.
17188 //
17189 // Return Value:
17190 //    The new block.
17191
17192 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind,
17193                                       BasicBlock* srcBlk,
17194                                       bool        runRarely /* = false */,
17195                                       bool        insertAtEnd /* = false */)
17196 {
17197     assert(srcBlk != nullptr);
17198
17199     const unsigned tryIndex    = srcBlk->bbTryIndex;
17200     const unsigned hndIndex    = srcBlk->bbHndIndex;
17201     bool           putInFilter = false;
17202
17203     // Check to see if we need to put the new block in a filter. We do if srcBlk is in a filter.
17204     // This can only be true if there is a handler index, and the handler region is more nested than the
17205     // try region (if any). This is because no EH regions can be nested within a filter.
17206     if (BasicBlock::ehIndexMaybeMoreNested(hndIndex, tryIndex))
17207     {
17208         assert(hndIndex != 0); // If hndIndex is more nested, we must be in some handler!
17209         putInFilter = ehGetDsc(hndIndex - 1)->InFilterRegionBBRange(srcBlk);
17210     }
17211
17212     return fgNewBBinRegion(jumpKind, tryIndex, hndIndex, srcBlk, putInFilter, runRarely, insertAtEnd);
17213 }
17214
17215 //------------------------------------------------------------------------
17216 // Creates a new BasicBlock and inserts it at the end of the function.
17217 //
17218 // See the implementation of fgNewBBinRegion() used by this one for more notes.
17219 //
17220 // Arguments:
17221 //    jumpKind - the jump kind of the new block to create.
17222 //
17223 // Return Value:
17224 //    The new block.
17225
17226 BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind)
17227 {
17228     return fgNewBBinRegion(jumpKind, 0, 0, nullptr, /* putInFilter */ false, /* runRarely */ false,
17229                            /* insertAtEnd */ true);
17230 }
17231
17232 //------------------------------------------------------------------------
17233 // Creates a new BasicBlock, and inserts it after 'afterBlk'.
17234 //
17235 // The block cannot be inserted into a more nested try/handler region than that specified by 'regionIndex'.
17236 // (It is given exactly 'regionIndex'.) Thus, the parameters must be passed to ensure proper EH nesting
17237 // rules are followed.
17238 //
17239 // Arguments:
17240 //    jumpKind - the jump kind of the new block to create.
17241 //    afterBlk - insert the new block after this one.
17242 //    regionIndex - the block will be put in this EH region.
17243 //    putInTryRegion - If true, put the new block in the 'try' region corresponding to 'regionIndex', and
17244 //          set its handler index to the most nested handler region enclosing that 'try' region.
17245 //          Otherwise, put the block in the handler region specified by 'regionIndex', and set its 'try'
17246 //          index to the most nested 'try' region enclosing that handler region.
17247 //
17248 // Return Value:
17249 //    The new block.
17250
17251 BasicBlock* Compiler::fgNewBBinRegionWorker(BBjumpKinds jumpKind,
17252                                             BasicBlock* afterBlk,
17253                                             unsigned    regionIndex,
17254                                             bool        putInTryRegion)
17255 {
17256     /* Insert the new block */
17257     BasicBlock* afterBlkNext = afterBlk->bbNext;
17258     (void)afterBlkNext; // prevent "unused variable" error from GCC
17259     BasicBlock* newBlk = fgNewBBafter(jumpKind, afterBlk, false);
17260
17261     if (putInTryRegion)
17262     {
17263         noway_assert(regionIndex <= MAX_XCPTN_INDEX);
17264         newBlk->bbTryIndex = (unsigned short)regionIndex;
17265         newBlk->bbHndIndex = bbFindInnermostHandlerRegionContainingTryRegion(regionIndex);
17266     }
17267     else
17268     {
17269         newBlk->bbTryIndex = bbFindInnermostTryRegionContainingHandlerRegion(regionIndex);
17270         noway_assert(regionIndex <= MAX_XCPTN_INDEX);
17271         newBlk->bbHndIndex = (unsigned short)regionIndex;
17272     }
17273
17274     // We're going to compare for equal try regions (to handle the case of 'mutually protect'
17275     // regions). We need to save off the current try region, otherwise we might change it
17276     // before it gets compared later, thereby making future comparisons fail.
17277
17278     BasicBlock* newTryBeg;
17279     BasicBlock* newTryLast;
17280     (void)ehInitTryBlockRange(newBlk, &newTryBeg, &newTryLast);
17281
17282     unsigned  XTnum;
17283     EHblkDsc* HBtab;
17284
17285     for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++)
17286     {
17287         // Is afterBlk at the end of a try region?
17288         if (HBtab->ebdTryLast == afterBlk)
17289         {
17290             noway_assert(afterBlkNext == newBlk->bbNext);
17291
17292             bool extendTryRegion = false;
17293             if (newBlk->hasTryIndex())
17294             {
17295                 // We're adding a block after the last block of some try region. Do
17296                 // we extend the try region to include the block, or not?
17297                 // If the try region is exactly the same as the try region
17298                 // associated with the new block (based on the block's try index,
17299                 // which represents the innermost try the block is a part of), then
17300                 // we extend it.
17301                 // If the try region is a "parent" try region -- an enclosing try region
17302                 // that has the same last block as the new block's try region -- then
17303                 // we also extend. For example:
17304                 //      try { // 1
17305                 //          ...
17306                 //          try { // 2
17307                 //          ...
17308                 //      } /* 2 */ } /* 1 */
17309                 // This example is meant to indicate that both try regions 1 and 2 end at
17310                 // the same block, and we're extending 2. Thus, we must also extend 1. If we
17311                 // only extended 2, we would break proper nesting. (Dev11 bug 137967)
17312
17313                 extendTryRegion = HBtab->ebdIsSameTry(newTryBeg, newTryLast) || bbInTryRegions(XTnum, newBlk);
17314             }
17315
17316             // Does newBlk extend this try region?
17317             if (extendTryRegion)
17318             {
17319                 // Yes, newBlk extends this try region
17320
17321                 // newBlk is the now the new try last block
17322                 fgSetTryEnd(HBtab, newBlk);
17323             }
17324         }
17325
17326         // Is afterBlk at the end of a handler region?
17327         if (HBtab->ebdHndLast == afterBlk)
17328         {
17329             noway_assert(afterBlkNext == newBlk->bbNext);
17330
17331             // Does newBlk extend this handler region?
17332             bool extendHndRegion = false;
17333             if (newBlk->hasHndIndex())
17334             {
17335                 // We're adding a block after the last block of some handler region. Do
17336                 // we extend the handler region to include the block, or not?
17337                 // If the handler region is exactly the same as the handler region
17338                 // associated with the new block (based on the block's handler index,
17339                 // which represents the innermost handler the block is a part of), then
17340                 // we extend it.
17341                 // If the handler region is a "parent" handler region -- an enclosing
17342                 // handler region that has the same last block as the new block's handler
17343                 // region -- then we also extend. For example:
17344                 //      catch { // 1
17345                 //          ...
17346                 //          catch { // 2
17347                 //          ...
17348                 //      } /* 2 */ } /* 1 */
17349                 // This example is meant to indicate that both handler regions 1 and 2 end at
17350                 // the same block, and we're extending 2. Thus, we must also extend 1. If we
17351                 // only extended 2, we would break proper nesting. (Dev11 bug 372051)
17352
17353                 extendHndRegion = bbInHandlerRegions(XTnum, newBlk);
17354             }
17355
17356             if (extendHndRegion)
17357             {
17358                 // Yes, newBlk extends this handler region
17359
17360                 // newBlk is now the last block of the handler.
17361                 fgSetHndEnd(HBtab, newBlk);
17362             }
17363         }
17364     }
17365
17366     /* If afterBlk falls through, we insert a jump around newBlk */
17367     fgConnectFallThrough(afterBlk, newBlk->bbNext);
17368
17369 #ifdef DEBUG
17370     fgVerifyHandlerTab();
17371 #endif
17372
17373     return newBlk;
17374 }
17375
17376 /*****************************************************************************
17377  */
17378
17379 /* static */
17380 unsigned Compiler::acdHelper(SpecialCodeKind codeKind)
17381 {
17382     switch (codeKind)
17383     {
17384         case SCK_RNGCHK_FAIL:
17385             return CORINFO_HELP_RNGCHKFAIL;
17386 #if COR_JIT_EE_VERSION > 460
17387         case SCK_ARG_EXCPN:
17388             return CORINFO_HELP_THROW_ARGUMENTEXCEPTION;
17389         case SCK_ARG_RNG_EXCPN:
17390             return CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION;
17391 #endif // COR_JIT_EE_VERSION
17392         case SCK_DIV_BY_ZERO:
17393             return CORINFO_HELP_THROWDIVZERO;
17394         case SCK_ARITH_EXCPN:
17395             return CORINFO_HELP_OVERFLOW;
17396         default:
17397             assert(!"Bad codeKind");
17398             return 0;
17399     }
17400 }
17401
17402 /*****************************************************************************
17403  *
17404  *  Find/create an added code entry associated with the given block and with
17405  *  the given kind.
17406  */
17407
17408 BasicBlock* Compiler::fgAddCodeRef(BasicBlock* srcBlk, unsigned refData, SpecialCodeKind kind, unsigned stkDepth)
17409 {
17410     // Record that the code will call a THROW_HELPER
17411     // so on Windows Amd64 we can allocate the 4 outgoing
17412     // arg slots on the stack frame if there are no other calls.
17413     compUsesThrowHelper = true;
17414
17415     // For debuggable code, genJumpToThrowHlpBlk() will generate the 'throw'
17416     // code inline. It has to be kept consistent with fgAddCodeRef()
17417     if (opts.compDbgCode)
17418     {
17419         return nullptr;
17420     }
17421
17422     const static BBjumpKinds jumpKinds[] = {
17423         BBJ_NONE,   // SCK_NONE
17424         BBJ_THROW,  // SCK_RNGCHK_FAIL
17425         BBJ_ALWAYS, // SCK_PAUSE_EXEC
17426         BBJ_THROW,  // SCK_DIV_BY_ZERO
17427         BBJ_THROW,  // SCK_ARITH_EXCP, SCK_OVERFLOW
17428         BBJ_THROW,  // SCK_ARG_EXCPN
17429         BBJ_THROW,  // SCK_ARG_RNG_EXCPN
17430     };
17431
17432     noway_assert(sizeof(jumpKinds) == SCK_COUNT); // sanity check
17433
17434     /* First look for an existing entry that matches what we're looking for */
17435
17436     AddCodeDsc* add = fgFindExcptnTarget(kind, refData);
17437
17438     if (add) // found it
17439     {
17440 #ifdef _TARGET_X86_
17441         // If different range checks happen at different stack levels,
17442         // they can't all jump to the same "call @rngChkFailed" AND have
17443         // frameless methods, as the rngChkFailed may need to unwind the
17444         // stack, and we have to be able to report the stack level.
17445         //
17446         // The following check forces most methods that reference an
17447         // array element in a parameter list to have an EBP frame,
17448         // this restriction could be removed with more careful code
17449         // generation for BBJ_THROW (i.e. range check failed).
17450         //
17451         if (add->acdStkLvl != stkDepth)
17452         {
17453             codeGen->setFrameRequired(true);
17454         }
17455 #endif // _TARGET_X86_
17456
17457         return add->acdDstBlk;
17458     }
17459
17460     /* We have to allocate a new entry and prepend it to the list */
17461
17462     add            = new (this, CMK_Unknown) AddCodeDsc;
17463     add->acdData   = refData;
17464     add->acdKind   = kind;
17465     add->acdStkLvl = (unsigned short)stkDepth;
17466     noway_assert(add->acdStkLvl == stkDepth);
17467     add->acdNext  = fgAddCodeList;
17468     fgAddCodeList = add;
17469
17470     /* Create the target basic block */
17471
17472     BasicBlock* newBlk;
17473
17474     newBlk = add->acdDstBlk = fgNewBBinRegion(jumpKinds[kind], srcBlk, /* runRarely */ true, /* insertAtEnd */ true);
17475
17476     add->acdDstBlk->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL;
17477
17478 #ifdef DEBUG
17479     if (verbose)
17480     {
17481         const char* msgWhere = "";
17482         if (!srcBlk->hasTryIndex() && !srcBlk->hasHndIndex())
17483         {
17484             msgWhere = "non-EH region";
17485         }
17486         else if (!srcBlk->hasTryIndex())
17487         {
17488             msgWhere = "handler";
17489         }
17490         else if (!srcBlk->hasHndIndex())
17491         {
17492             msgWhere = "try";
17493         }
17494         else if (srcBlk->getTryIndex() < srcBlk->getHndIndex())
17495         {
17496             msgWhere = "try";
17497         }
17498         else
17499         {
17500             msgWhere = "handler";
17501         }
17502
17503         const char* msg;
17504         switch (kind)
17505         {
17506             case SCK_RNGCHK_FAIL:
17507                 msg = " for RNGCHK_FAIL";
17508                 break;
17509             case SCK_PAUSE_EXEC:
17510                 msg = " for PAUSE_EXEC";
17511                 break;
17512             case SCK_DIV_BY_ZERO:
17513                 msg = " for DIV_BY_ZERO";
17514                 break;
17515             case SCK_OVERFLOW:
17516                 msg = " for OVERFLOW";
17517                 break;
17518 #if COR_JIT_EE_VERSION > 460
17519             case SCK_ARG_EXCPN:
17520                 msg = " for ARG_EXCPN";
17521                 break;
17522             case SCK_ARG_RNG_EXCPN:
17523                 msg = " for ARG_RNG_EXCPN";
17524                 break;
17525 #endif // COR_JIT_EE_VERSION
17526             default:
17527                 msg = " for ??";
17528                 break;
17529         }
17530
17531         printf("\nfgAddCodeRef -"
17532                " Add BB in %s%s, new block BB%02u [%08p], stkDepth is %d\n",
17533                msgWhere, msg, add->acdDstBlk->bbNum, dspPtr(add->acdDstBlk), stkDepth);
17534     }
17535 #endif // DEBUG
17536
17537 #ifdef DEBUG
17538     newBlk->bbTgtStkDepth = stkDepth;
17539 #endif // DEBUG
17540
17541     /* Mark the block as added by the compiler and not removable by future flow
17542        graph optimizations. Note that no bbJumpDest points to these blocks. */
17543
17544     newBlk->bbFlags |= BBF_IMPORTED;
17545     newBlk->bbFlags |= BBF_DONT_REMOVE;
17546
17547     /* Remember that we're adding a new basic block */
17548
17549     fgAddCodeModf      = true;
17550     fgRngChkThrowAdded = true;
17551
17552     /* Now figure out what code to insert */
17553
17554     GenTreeCall* tree;
17555     int          helper = CORINFO_HELP_UNDEF;
17556
17557     switch (kind)
17558     {
17559         case SCK_RNGCHK_FAIL:
17560             helper = CORINFO_HELP_RNGCHKFAIL;
17561             break;
17562
17563         case SCK_DIV_BY_ZERO:
17564             helper = CORINFO_HELP_THROWDIVZERO;
17565             break;
17566
17567         case SCK_ARITH_EXCPN:
17568             helper = CORINFO_HELP_OVERFLOW;
17569             noway_assert(SCK_OVERFLOW == SCK_ARITH_EXCPN);
17570             break;
17571
17572 #if COR_JIT_EE_VERSION > 460
17573         case SCK_ARG_EXCPN:
17574             helper = CORINFO_HELP_THROW_ARGUMENTEXCEPTION;
17575             break;
17576
17577         case SCK_ARG_RNG_EXCPN:
17578             helper = CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION;
17579             break;
17580 #endif // COR_JIT_EE_VERSION
17581
17582         // case SCK_PAUSE_EXEC:
17583         //     noway_assert(!"add code to pause exec");
17584
17585         default:
17586             noway_assert(!"unexpected code addition kind");
17587             return nullptr;
17588     }
17589
17590     noway_assert(helper != CORINFO_HELP_UNDEF);
17591
17592     // Add the appropriate helper call.
17593     tree = gtNewHelperCallNode(helper, TYP_VOID, GTF_EXCEPT);
17594
17595     // There are no args here but fgMorphArgs has side effects
17596     // such as setting the outgoing arg area (which is necessary
17597     // on AMD if there are any calls).
17598     tree = fgMorphArgs(tree);
17599
17600     // Store the tree in the new basic block.
17601     assert(!srcBlk->isEmpty());
17602     if (!srcBlk->IsLIR())
17603     {
17604         fgInsertStmtAtEnd(newBlk, fgNewStmtFromTree(tree));
17605     }
17606     else
17607     {
17608         LIR::AsRange(newBlk).InsertAtEnd(LIR::SeqTree(this, tree));
17609     }
17610
17611     return add->acdDstBlk;
17612 }
17613
17614 /*****************************************************************************
17615  * Finds the block to jump to, to throw a given kind of exception
17616  * We maintain a cache of one AddCodeDsc for each kind, to make searching fast.
17617  * Note : Each block uses the same (maybe shared) block as the jump target for
17618  * a given type of exception
17619  */
17620
17621 Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, unsigned refData)
17622 {
17623     if (!(fgExcptnTargetCache[kind] && // Try the cached value first
17624           fgExcptnTargetCache[kind]->acdData == refData))
17625     {
17626         // Too bad, have to search for the jump target for the exception
17627
17628         AddCodeDsc* add = nullptr;
17629
17630         for (add = fgAddCodeList; add != nullptr; add = add->acdNext)
17631         {
17632             if (add->acdData == refData && add->acdKind == kind)
17633             {
17634                 break;
17635             }
17636         }
17637
17638         fgExcptnTargetCache[kind] = add; // Cache it
17639     }
17640
17641     return fgExcptnTargetCache[kind];
17642 }
17643
17644 /*****************************************************************************
17645  *
17646  *  The given basic block contains an array range check; return the label this
17647  *  range check is to jump to upon failure.
17648  */
17649
17650 BasicBlock* Compiler::fgRngChkTarget(BasicBlock* block, unsigned stkDepth, SpecialCodeKind kind)
17651 {
17652 #ifdef DEBUG
17653     if (verbose)
17654     {
17655         printf("*** Computing fgRngChkTarget for block BB%02u to stkDepth %d\n", block->bbNum, stkDepth);
17656         if (!block->IsLIR())
17657         {
17658             gtDispTree(compCurStmt);
17659         }
17660     }
17661 #endif // DEBUG
17662
17663     /* We attach the target label to the containing try block (if any) */
17664     noway_assert(!compIsForInlining());
17665     return fgAddCodeRef(block, bbThrowIndex(block), kind, stkDepth);
17666 }
17667
17668 // Sequences the tree.
17669 // prevTree is what gtPrev of the first node in execution order gets set to.
17670 // Returns the first node (execution order) in the sequenced tree.
17671 GenTree* Compiler::fgSetTreeSeq(GenTree* tree, GenTree* prevTree, bool isLIR)
17672 {
17673     GenTree list;
17674
17675     if (prevTree == nullptr)
17676     {
17677         prevTree = &list;
17678     }
17679     fgTreeSeqLst = prevTree;
17680     fgTreeSeqNum = 0;
17681     fgTreeSeqBeg = nullptr;
17682     fgSetTreeSeqHelper(tree, isLIR);
17683
17684     GenTree* result = prevTree->gtNext;
17685     if (prevTree == &list)
17686     {
17687         list.gtNext->gtPrev = nullptr;
17688     }
17689
17690     return result;
17691 }
17692
17693 /*****************************************************************************
17694  *
17695  *  Assigns sequence numbers to the given tree and its sub-operands, and
17696  *  threads all the nodes together via the 'gtNext' and 'gtPrev' fields.
17697  *  Uses 'global' - fgTreeSeqLst
17698  */
17699
17700 void Compiler::fgSetTreeSeqHelper(GenTreePtr tree, bool isLIR)
17701 {
17702     genTreeOps oper;
17703     unsigned   kind;
17704
17705     noway_assert(tree);
17706     assert(!IsUninitialized(tree));
17707     noway_assert(tree->gtOper != GT_STMT);
17708
17709     /* Figure out what kind of a node we have */
17710
17711     oper = tree->OperGet();
17712     kind = tree->OperKind();
17713
17714     /* Is this a leaf/constant node? */
17715
17716     if (kind & (GTK_CONST | GTK_LEAF))
17717     {
17718         fgSetTreeSeqFinish(tree, isLIR);
17719         return;
17720     }
17721
17722     /* Is it a 'simple' unary/binary operator? */
17723
17724     if (kind & GTK_SMPOP)
17725     {
17726         GenTreePtr op1 = tree->gtOp.gtOp1;
17727         GenTreePtr op2 = tree->gtGetOp2();
17728
17729         // Special handling for GT_LIST
17730         if (tree->OperGet() == GT_LIST)
17731         {
17732
17733             if (tree->gtOp.gtOp2 != nullptr && tree->gtOp.gtOp2->gtOper != GT_LIST)
17734             {
17735                 // This is a special kind of GT_LIST that only occurs under initBlk and copyBlk.
17736                 // It is used as a pair, where op1 is the dst and op2 is the src (value or location)
17737                 // The use must appear before the def because of the case where a local is cpblk'ed to itself.
17738                 // If it were otherwise, upstream stores to the local would appear to be dead.
17739                 assert(tree->gtOp.gtOp1->gtOper != GT_LIST);
17740                 fgSetTreeSeqHelper(tree->gtOp.gtOp2, isLIR);
17741                 fgSetTreeSeqHelper(tree->gtOp.gtOp1, isLIR);
17742                 fgSetTreeSeqFinish(tree, isLIR);
17743                 return;
17744             }
17745
17746             // First, handle the list items, which will be linked in forward order.
17747             // As we go, we will link the GT_LIST nodes in reverse order - we will number
17748             // them and update fgTreeSeqList in a subsequent traversal.
17749             GenTreePtr nextList = tree;
17750             GenTreePtr list     = nullptr;
17751             while (nextList != nullptr && nextList->OperGet() == GT_LIST)
17752             {
17753                 list                = nextList;
17754                 GenTreePtr listItem = list->gtOp.gtOp1;
17755                 fgSetTreeSeqHelper(listItem, isLIR);
17756                 nextList = list->gtOp.gtOp2;
17757                 if (nextList != nullptr)
17758                 {
17759                     nextList->gtNext = list;
17760                 }
17761                 list->gtPrev = nextList;
17762             }
17763             // Next, handle the GT_LIST nodes.
17764             // Note that fgSetTreeSeqFinish() sets the gtNext to null, so we need to capture the nextList
17765             // before we call that method.
17766             nextList = list;
17767             do
17768             {
17769                 assert(list != nullptr);
17770                 list     = nextList;
17771                 nextList = list->gtNext;
17772                 fgSetTreeSeqFinish(list, isLIR);
17773             } while (list != tree);
17774             return;
17775         }
17776
17777         /* Special handling for AddrMode */
17778         if (tree->OperIsAddrMode())
17779         {
17780             bool reverse = ((tree->gtFlags & GTF_REVERSE_OPS) != 0);
17781             if (reverse)
17782             {
17783                 assert(op1 != nullptr && op2 != nullptr);
17784                 fgSetTreeSeqHelper(op2, isLIR);
17785             }
17786             if (op1 != nullptr)
17787             {
17788                 fgSetTreeSeqHelper(op1, isLIR);
17789             }
17790             if (!reverse && op2 != nullptr)
17791             {
17792                 fgSetTreeSeqHelper(op2, isLIR);
17793             }
17794
17795             fgSetTreeSeqFinish(tree, isLIR);
17796             return;
17797         }
17798
17799         /* Check for a nilary operator */
17800
17801         if (op1 == nullptr)
17802         {
17803             noway_assert(op2 == nullptr);
17804             fgSetTreeSeqFinish(tree, isLIR);
17805             return;
17806         }
17807
17808         /* Is this a unary operator?
17809          * Although UNARY GT_IND has a special structure */
17810
17811         if (oper == GT_IND)
17812         {
17813             /* Visit the indirection first - op2 may point to the
17814              * jump Label for array-index-out-of-range */
17815
17816             fgSetTreeSeqHelper(op1, isLIR);
17817             fgSetTreeSeqFinish(tree, isLIR);
17818             return;
17819         }
17820
17821         /* Now this is REALLY a unary operator */
17822
17823         if (!op2)
17824         {
17825             /* Visit the (only) operand and we're done */
17826
17827             fgSetTreeSeqHelper(op1, isLIR);
17828             fgSetTreeSeqFinish(tree, isLIR);
17829             return;
17830         }
17831
17832         /*
17833            For "real" ?: operators, we make sure the order is
17834            as follows:
17835
17836                condition
17837                1st operand
17838                GT_COLON
17839                2nd operand
17840                GT_QMARK
17841         */
17842
17843         if (oper == GT_QMARK)
17844         {
17845             noway_assert((tree->gtFlags & GTF_REVERSE_OPS) == 0);
17846
17847             fgSetTreeSeqHelper(op1, isLIR);
17848             // Here, for the colon, the sequence does not actually represent "order of evaluation":
17849             // one or the other of the branches is executed, not both.  Still, to make debugging checks
17850             // work, we want the sequence to match the order in which we'll generate code, which means
17851             // "else" clause then "then" clause.
17852             fgSetTreeSeqHelper(op2->AsColon()->ElseNode(), isLIR);
17853             fgSetTreeSeqHelper(op2, isLIR);
17854             fgSetTreeSeqHelper(op2->AsColon()->ThenNode(), isLIR);
17855
17856             fgSetTreeSeqFinish(tree, isLIR);
17857             return;
17858         }
17859
17860         if (oper == GT_COLON)
17861         {
17862             fgSetTreeSeqFinish(tree, isLIR);
17863             return;
17864         }
17865
17866         /* This is a binary operator */
17867
17868         if (tree->gtFlags & GTF_REVERSE_OPS)
17869         {
17870             fgSetTreeSeqHelper(op2, isLIR);
17871             fgSetTreeSeqHelper(op1, isLIR);
17872         }
17873         else
17874         {
17875             fgSetTreeSeqHelper(op1, isLIR);
17876             fgSetTreeSeqHelper(op2, isLIR);
17877         }
17878
17879         fgSetTreeSeqFinish(tree, isLIR);
17880         return;
17881     }
17882
17883     /* See what kind of a special operator we have here */
17884
17885     switch (oper)
17886     {
17887         case GT_FIELD:
17888             noway_assert(tree->gtField.gtFldObj == nullptr);
17889             break;
17890
17891         case GT_CALL:
17892
17893             /* We'll evaluate the 'this' argument value first */
17894             if (tree->gtCall.gtCallObjp)
17895             {
17896                 fgSetTreeSeqHelper(tree->gtCall.gtCallObjp, isLIR);
17897             }
17898
17899             /* We'll evaluate the arguments next, left to right
17900              * NOTE: setListOrder needs cleanup - eliminate the #ifdef afterwards */
17901
17902             if (tree->gtCall.gtCallArgs)
17903             {
17904                 fgSetTreeSeqHelper(tree->gtCall.gtCallArgs, isLIR);
17905             }
17906
17907             /* Evaluate the temp register arguments list
17908              * This is a "hidden" list and its only purpose is to
17909              * extend the life of temps until we make the call */
17910
17911             if (tree->gtCall.gtCallLateArgs)
17912             {
17913                 fgSetTreeSeqHelper(tree->gtCall.gtCallLateArgs, isLIR);
17914             }
17915
17916             if ((tree->gtCall.gtCallType == CT_INDIRECT) && (tree->gtCall.gtCallCookie != nullptr))
17917             {
17918                 fgSetTreeSeqHelper(tree->gtCall.gtCallCookie, isLIR);
17919             }
17920
17921             if (tree->gtCall.gtCallType == CT_INDIRECT)
17922             {
17923                 fgSetTreeSeqHelper(tree->gtCall.gtCallAddr, isLIR);
17924             }
17925
17926             if (tree->gtCall.gtControlExpr)
17927             {
17928                 fgSetTreeSeqHelper(tree->gtCall.gtControlExpr, isLIR);
17929             }
17930
17931             break;
17932
17933         case GT_ARR_ELEM:
17934
17935             fgSetTreeSeqHelper(tree->gtArrElem.gtArrObj, isLIR);
17936
17937             unsigned dim;
17938             for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
17939             {
17940                 fgSetTreeSeqHelper(tree->gtArrElem.gtArrInds[dim], isLIR);
17941             }
17942
17943             break;
17944
17945         case GT_ARR_OFFSET:
17946             fgSetTreeSeqHelper(tree->gtArrOffs.gtOffset, isLIR);
17947             fgSetTreeSeqHelper(tree->gtArrOffs.gtIndex, isLIR);
17948             fgSetTreeSeqHelper(tree->gtArrOffs.gtArrObj, isLIR);
17949             break;
17950
17951         case GT_CMPXCHG:
17952             // Evaluate the trees left to right
17953             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpLocation, isLIR);
17954             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpValue, isLIR);
17955             fgSetTreeSeqHelper(tree->gtCmpXchg.gtOpComparand, isLIR);
17956             break;
17957
17958         case GT_ARR_BOUNDS_CHECK:
17959 #ifdef FEATURE_SIMD
17960         case GT_SIMD_CHK:
17961 #endif // FEATURE_SIMD
17962             // Evaluate the trees left to right
17963             fgSetTreeSeqHelper(tree->gtBoundsChk.gtArrLen, isLIR);
17964             fgSetTreeSeqHelper(tree->gtBoundsChk.gtIndex, isLIR);
17965             break;
17966
17967         default:
17968 #ifdef DEBUG
17969             gtDispTree(tree);
17970             noway_assert(!"unexpected operator");
17971 #endif // DEBUG
17972             break;
17973     }
17974
17975     fgSetTreeSeqFinish(tree, isLIR);
17976 }
17977
17978 void Compiler::fgSetTreeSeqFinish(GenTreePtr tree, bool isLIR)
17979 {
17980     // If we are sequencing a node that does not appear in LIR,
17981     // do not add it to the list.
17982     if (isLIR && (((tree->OperGet() == GT_LIST) && !tree->AsArgList()->IsAggregate()) || tree->OperGet() == GT_ARGPLACE))
17983     {
17984         return;
17985     }
17986
17987     /* Append to the node list */
17988     ++fgTreeSeqNum;
17989
17990 #ifdef DEBUG
17991     tree->gtSeqNum = fgTreeSeqNum;
17992
17993     if (verbose & 0)
17994     {
17995         printf("SetTreeOrder: ");
17996         printTreeID(fgTreeSeqLst);
17997         printf(" followed by ");
17998         printTreeID(tree);
17999         printf("\n");
18000     }
18001 #endif // DEBUG
18002
18003     fgTreeSeqLst->gtNext = tree;
18004     tree->gtNext         = nullptr;
18005     tree->gtPrev         = fgTreeSeqLst;
18006     fgTreeSeqLst         = tree;
18007
18008     /* Remember the very first node */
18009
18010     if (!fgTreeSeqBeg)
18011     {
18012         fgTreeSeqBeg = tree;
18013         assert(tree->gtSeqNum == 1);
18014     }
18015 }
18016
18017 /*****************************************************************************
18018  *
18019  *  Figure out the order in which operators should be evaluated, along with
18020  *  other information (such as the register sets trashed by each subtree).
18021  *  Also finds blocks that need GC polls and inserts them as needed.
18022  */
18023
18024 void Compiler::fgSetBlockOrder()
18025 {
18026 #ifdef DEBUG
18027     if (verbose)
18028     {
18029         printf("*************** In fgSetBlockOrder()\n");
18030     }
18031 #endif // DEBUG
18032
18033 #ifdef DEBUG
18034     BasicBlock::s_nMaxTrees = 0;
18035 #endif
18036
18037     /* Walk the basic blocks to assign sequence numbers */
18038
18039     /* If we don't compute the doms, then we never mark blocks as loops. */
18040     if (fgDomsComputed)
18041     {
18042         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18043         {
18044             /* If this block is a loop header, mark it appropriately */
18045
18046             if (block->isLoopHead())
18047             {
18048                 fgMarkLoopHead(block);
18049             }
18050         }
18051     }
18052     // only enable fully interruptible code for if we're hijacking.
18053     else if (GCPOLL_NONE == opts.compGCPollType)
18054     {
18055         /* If we don't have the dominators, use an abbreviated test for fully interruptible.  If there are
18056          * any back edges, check the source and destination blocks to see if they're GC Safe.  If not, then
18057          * go fully interruptible. */
18058
18059         /* XXX Mon 1/21/2008
18060          * Wouldn't it be nice to have a block iterator that can do this loop?
18061          */
18062         for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18063         {
18064 // true if the edge is forward, or if it is a back edge and either the source and dest are GC safe.
18065 #define EDGE_IS_GC_SAFE(src, dst)                                                                                      \
18066     (((src)->bbNum < (dst)->bbNum) || (((src)->bbFlags | (dst)->bbFlags) & BBF_GC_SAFE_POINT))
18067
18068             bool partiallyInterruptible = true;
18069             switch (block->bbJumpKind)
18070             {
18071                 case BBJ_COND:
18072                 case BBJ_ALWAYS:
18073                     partiallyInterruptible = EDGE_IS_GC_SAFE(block, block->bbJumpDest);
18074                     break;
18075
18076                 case BBJ_SWITCH:
18077
18078                     unsigned jumpCnt;
18079                     jumpCnt = block->bbJumpSwt->bbsCount;
18080                     BasicBlock** jumpPtr;
18081                     jumpPtr = block->bbJumpSwt->bbsDstTab;
18082
18083                     do
18084                     {
18085                         partiallyInterruptible &= EDGE_IS_GC_SAFE(block, *jumpPtr);
18086                     } while (++jumpPtr, --jumpCnt);
18087
18088                     break;
18089
18090                 default:
18091                     break;
18092             }
18093
18094             if (!partiallyInterruptible)
18095             {
18096                 // DDB 204533:
18097                 // The GC encoding for fully interruptible methods does not
18098                 // support more than 1023 pushed arguments, so we can't set
18099                 // genInterruptible here when we have 1024 or more pushed args
18100                 //
18101                 if (compCanEncodePtrArgCntMax())
18102                 {
18103                     genInterruptible = true;
18104                 }
18105                 break;
18106             }
18107 #undef EDGE_IS_GC_SAFE
18108         }
18109     }
18110
18111     if (!fgGCPollsCreated)
18112     {
18113         fgCreateGCPolls();
18114     }
18115
18116     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
18117     {
18118
18119 #if FEATURE_FASTTAILCALL
18120 #ifndef JIT32_GCENCODER
18121         if (block->endsWithTailCallOrJmp(this, true) && !(block->bbFlags & BBF_GC_SAFE_POINT) &&
18122             optReachWithoutCall(fgFirstBB, block))
18123         {
18124             // We have a tail call that is reachable without making any other
18125             // 'normal' call that would have counted as a GC Poll.  If we were
18126             // using polls, all return blocks meeting this criteria would have
18127             // already added polls and then marked as being GC safe
18128             // (BBF_GC_SAFE_POINT). Thus we can only reach here when *NOT*
18129             // using GC polls, but instead relying on the JIT to generate
18130             // fully-interruptible code.
18131             noway_assert(GCPOLL_NONE == opts.compGCPollType);
18132
18133             // This tail call might combine with other tail calls to form a
18134             // loop.  Thus we need to either add a poll, or make the method
18135             // fully interruptible.  I chose the later because that's what
18136             // JIT64 does.
18137             genInterruptible = true;
18138         }
18139 #endif // !JIT32_GCENCODER
18140 #endif // FEATURE_FASTTAILCALL
18141
18142         fgSetBlockOrder(block);
18143     }
18144
18145     /* Remember that now the tree list is threaded */
18146
18147     fgStmtListThreaded = true;
18148
18149 #ifdef DEBUG
18150     if (verbose)
18151     {
18152         printf("The biggest BB has %4u tree nodes\n", BasicBlock::s_nMaxTrees);
18153     }
18154     fgDebugCheckLinks();
18155 #endif // DEBUG
18156 }
18157
18158 /*****************************************************************************/
18159
18160 void Compiler::fgSetStmtSeq(GenTreePtr tree)
18161 {
18162     GenTree list; // helper node that we use to start the StmtList
18163                   // It's located in front of the first node in the list
18164
18165     noway_assert(tree->gtOper == GT_STMT);
18166
18167     /* Assign numbers and next/prev links for this tree */
18168
18169     fgTreeSeqNum = 0;
18170     fgTreeSeqLst = &list;
18171     fgTreeSeqBeg = nullptr;
18172
18173     fgSetTreeSeqHelper(tree->gtStmt.gtStmtExpr, false);
18174
18175     /* Record the address of the first node */
18176
18177     tree->gtStmt.gtStmtList = fgTreeSeqBeg;
18178
18179 #ifdef DEBUG
18180
18181     if (list.gtNext->gtPrev != &list)
18182     {
18183         printf("&list ");
18184         printTreeID(&list);
18185         printf(" != list.next->prev ");
18186         printTreeID(list.gtNext->gtPrev);
18187         printf("\n");
18188         goto BAD_LIST;
18189     }
18190
18191     GenTreePtr temp;
18192     GenTreePtr last;
18193     for (temp = list.gtNext, last = &list; temp; last = temp, temp = temp->gtNext)
18194     {
18195         if (temp->gtPrev != last)
18196         {
18197             printTreeID(temp);
18198             printf("->gtPrev = ");
18199             printTreeID(temp->gtPrev);
18200             printf(", but last = ");
18201             printTreeID(last);
18202             printf("\n");
18203
18204         BAD_LIST:;
18205
18206             printf("\n");
18207             gtDispTree(tree->gtStmt.gtStmtExpr);
18208             printf("\n");
18209
18210             for (GenTreePtr bad = &list; bad; bad = bad->gtNext)
18211             {
18212                 printf("  entry at ");
18213                 printTreeID(bad);
18214                 printf(" (prev=");
18215                 printTreeID(bad->gtPrev);
18216                 printf(",next=)");
18217                 printTreeID(bad->gtNext);
18218                 printf("\n");
18219             }
18220
18221             printf("\n");
18222             noway_assert(!"Badly linked tree");
18223             break;
18224         }
18225     }
18226 #endif // DEBUG
18227
18228     /* Fix the first node's 'prev' link */
18229
18230     noway_assert(list.gtNext->gtPrev == &list);
18231     list.gtNext->gtPrev = nullptr;
18232
18233 #ifdef DEBUG
18234     /* Keep track of the highest # of tree nodes */
18235
18236     if (BasicBlock::s_nMaxTrees < fgTreeSeqNum)
18237     {
18238         BasicBlock::s_nMaxTrees = fgTreeSeqNum;
18239     }
18240 #endif // DEBUG
18241 }
18242
18243 /*****************************************************************************/
18244
18245 void Compiler::fgSetBlockOrder(BasicBlock* block)
18246 {
18247     GenTreePtr tree;
18248
18249     tree = block->bbTreeList;
18250     if (!tree)
18251     {
18252         return;
18253     }
18254
18255     for (;;)
18256     {
18257         fgSetStmtSeq(tree);
18258
18259         /* Are there any more trees in this basic block? */
18260
18261         if (tree->gtNext == nullptr)
18262         {
18263             /* last statement in the tree list */
18264             noway_assert(block->lastStmt() == tree);
18265             break;
18266         }
18267
18268 #ifdef DEBUG
18269         if (block->bbTreeList == tree)
18270         {
18271             /* first statement in the list */
18272             noway_assert(tree->gtPrev->gtNext == nullptr);
18273         }
18274         else
18275         {
18276             noway_assert(tree->gtPrev->gtNext == tree);
18277         }
18278
18279         noway_assert(tree->gtNext->gtPrev == tree);
18280 #endif // DEBUG
18281
18282         tree = tree->gtNext;
18283     }
18284 }
18285
18286 #ifdef LEGACY_BACKEND
18287 /*****************************************************************************
18288  *
18289  * For GT_INITBLK and GT_COPYBLK, the tree looks like this :
18290  *                                tree->gtOp
18291  *                                 /    \
18292  *                               /        \.
18293  *                           GT_LIST  [size/clsHnd]
18294  *                            /    \
18295  *                           /      \
18296  *                       [dest]     [val/src]
18297  *
18298  * ie. they are ternary operators. However we use nested binary trees so that
18299  * GTF_REVERSE_OPS will be set just like for other binary operators. As the
18300  * operands need to end up in specific registers to issue the "rep stos" or
18301  * the "rep movs" instruction, if we don't allow the order of evaluation of
18302  * the 3 operands to be mixed, we may generate really bad code.
18303  *
18304  * eg. For "rep stos", [val] has to be in EAX. Then if [size]
18305  * has a division, we will have to spill [val] from EAX. It will be better to
18306  * evaluate [size] and the evaluate [val] into EAX.
18307  *
18308  * This function stores the operands in the order to be evaluated
18309  * into opsPtr[]. The regsPtr[] contains reg0,reg1,reg2 in the correspondingly
18310  * switched order.
18311  */
18312
18313 void Compiler::fgOrderBlockOps(GenTreePtr  tree,
18314                                regMaskTP   reg0,
18315                                regMaskTP   reg1,
18316                                regMaskTP   reg2,
18317                                GenTreePtr* opsPtr,  // OUT
18318                                regMaskTP*  regsPtr) // OUT
18319 {
18320     assert(tree->OperIsBlkOp());
18321
18322     assert(tree->gtOp.gtOp1 && tree->gtOp.gtOp1->IsList());
18323     assert(tree->gtOp.gtOp1->gtOp.gtOp1 && tree->gtOp.gtOp1->gtOp.gtOp2);
18324     assert(tree->gtOp.gtOp2);
18325
18326     GenTreePtr ops[3] = {
18327         tree->gtOp.gtOp1->gtOp.gtOp1, // Dest address
18328         tree->gtOp.gtOp1->gtOp.gtOp2, // Val / Src address
18329         tree->gtOp.gtOp2              // Size of block
18330     };
18331
18332     regMaskTP regs[3] = {reg0, reg1, reg2};
18333
18334     static int blockOpsOrder[4][3] =
18335         //      tree->gtFlags    |  tree->gtOp.gtOp1->gtFlags
18336         {
18337             //  ---------------------+----------------------------
18338             {0, 1, 2}, //           -           |              -
18339             {2, 0, 1}, //     GTF_REVERSE_OPS   |              -
18340             {1, 0, 2}, //           -           |       GTF_REVERSE_OPS
18341             {2, 1, 0}  //     GTF_REVERSE_OPS   |       GTF_REVERSE_OPS
18342         };
18343
18344     int orderNum =
18345         ((tree->gtFlags & GTF_REVERSE_OPS) != 0) * 1 + ((tree->gtOp.gtOp1->gtFlags & GTF_REVERSE_OPS) != 0) * 2;
18346
18347     assert(orderNum < 4);
18348
18349     int* order = blockOpsOrder[orderNum];
18350
18351     PREFIX_ASSUME(order != NULL);
18352
18353     // Fill in the OUT arrays according to the order we have selected
18354
18355     opsPtr[0] = ops[order[0]];
18356     opsPtr[1] = ops[order[1]];
18357     opsPtr[2] = ops[order[2]];
18358
18359     regsPtr[0] = regs[order[0]];
18360     regsPtr[1] = regs[order[1]];
18361     regsPtr[2] = regs[order[2]];
18362 }
18363 #endif // LEGACY_BACKEND
18364
18365 //------------------------------------------------------------------------
18366 // fgGetFirstNode: Get the first node in the tree, in execution order
18367 //
18368 // Arguments:
18369 //    tree - The top node of the tree of interest
18370 //
18371 // Return Value:
18372 //    The first node in execution order, that belongs to tree.
18373 //
18374 // Assumptions:
18375 //     'tree' must either be a leaf, or all of its constituent nodes must be contiguous
18376 //     in execution order.
18377 //     TODO-Cleanup: Add a debug-only method that verifies this.
18378
18379 /* static */
18380 GenTreePtr Compiler::fgGetFirstNode(GenTreePtr tree)
18381 {
18382     GenTreePtr child = tree;
18383     while (child->NumChildren() > 0)
18384     {
18385         if (child->OperIsBinary() && child->IsReverseOp())
18386         {
18387             child = child->GetChild(1);
18388         }
18389         else
18390         {
18391             child = child->GetChild(0);
18392         }
18393     }
18394     return child;
18395 }
18396
18397 // Examine the bbTreeList and return the estimated code size for this block
18398 unsigned Compiler::fgGetCodeEstimate(BasicBlock* block)
18399 {
18400     unsigned costSz = 0; // estimate of blocks code size cost
18401
18402     switch (block->bbJumpKind)
18403     {
18404         case BBJ_NONE:
18405             costSz = 0;
18406             break;
18407         case BBJ_ALWAYS:
18408         case BBJ_EHCATCHRET:
18409         case BBJ_LEAVE:
18410         case BBJ_COND:
18411             costSz = 2;
18412             break;
18413         case BBJ_CALLFINALLY:
18414             costSz = 5;
18415             break;
18416         case BBJ_SWITCH:
18417             costSz = 10;
18418             break;
18419         case BBJ_THROW:
18420             costSz = 1; // We place a int3 after the code for a throw block
18421             break;
18422         case BBJ_EHFINALLYRET:
18423         case BBJ_EHFILTERRET:
18424             costSz = 1;
18425             break;
18426         case BBJ_RETURN: // return from method
18427             costSz = 3;
18428             break;
18429         default:
18430             noway_assert(!"Bad bbJumpKind");
18431             break;
18432     }
18433
18434     GenTreePtr tree = block->FirstNonPhiDef();
18435     if (tree)
18436     {
18437         do
18438         {
18439             noway_assert(tree->gtOper == GT_STMT);
18440
18441             if (tree->gtCostSz < MAX_COST)
18442             {
18443                 costSz += tree->gtCostSz;
18444             }
18445             else
18446             {
18447                 // We could walk the tree to find out the real gtCostSz,
18448                 // but just using MAX_COST for this trees code size works OK
18449                 costSz += tree->gtCostSz;
18450             }
18451
18452             tree = tree->gtNext;
18453         } while (tree);
18454     }
18455
18456     return costSz;
18457 }
18458
18459 #if DUMP_FLOWGRAPHS
18460
18461 struct escapeMapping_t
18462 {
18463     char        ch;
18464     const char* sub;
18465 };
18466
18467 // clang-format off
18468 static escapeMapping_t s_EscapeFileMapping[] =
18469 {
18470     {':', "="},
18471     {'<', "["},
18472     {'>', "]"},
18473     {';', "~semi~"},
18474     {'|', "~bar~"},
18475     {'&', "~amp~"},
18476     {'"', "~quot~"},
18477     {'*', "~star~"},
18478     {0, nullptr}
18479 };
18480
18481 static escapeMapping_t s_EscapeMapping[] =
18482 {
18483     {'<', "&lt;"},
18484     {'>', "&gt;"},
18485     {'&', "&amp;"},
18486     {'"', "&quot;"},
18487     {0, nullptr}
18488 };
18489 // clang-formt on
18490
18491 const char*   Compiler::fgProcessEscapes(const char* nameIn, escapeMapping_t* map)
18492 {
18493     const char*  nameOut = nameIn;
18494     unsigned     lengthOut;
18495     unsigned     index;
18496     bool         match;
18497     bool         subsitutionRequired;
18498     const char*  pChar;
18499
18500     lengthOut = 1;
18501     subsitutionRequired = false;
18502     pChar = nameIn;
18503     while (*pChar != '\0')
18504     {
18505         match = false;
18506         index = 0;
18507         while (map[index].ch != 0)
18508         {
18509             if (*pChar == map[index].ch)
18510             {
18511                 match = true;
18512                 break;
18513             }
18514             index++;
18515         }
18516         if (match)
18517         {
18518             subsitutionRequired = true;
18519             lengthOut += (unsigned)strlen(map[index].sub);
18520         }
18521         else
18522         {
18523             lengthOut += 1;
18524         }
18525         pChar++;
18526     }
18527
18528     if (subsitutionRequired)
18529     {
18530         char*   newName = (char*) compGetMemA(lengthOut, CMK_DebugOnly);
18531         char*   pDest;
18532         pDest = newName;
18533         pChar = nameIn;
18534         while (*pChar != '\0')
18535         {
18536             match = false;
18537             index = 0;
18538             while (map[index].ch != 0)
18539             {
18540                 if (*pChar == map[index].ch)
18541                 {
18542                     match = true;
18543                     break;
18544                 }
18545                 index++;
18546             }
18547             if (match)
18548             {
18549                 strcpy(pDest, map[index].sub);
18550                 pDest += strlen(map[index].sub);
18551             }
18552             else
18553             {
18554                 *pDest++ = *pChar;
18555             }
18556             pChar++;
18557         }
18558         *pDest++ = '\0';
18559         nameOut = (const char*) newName;
18560     }
18561
18562     return nameOut;
18563 }
18564
18565 static void fprintfDouble(FILE* fgxFile, double value)
18566 {
18567     assert(value >= 0.0);
18568
18569     if ((value >= 0.010) || (value == 0.0))
18570     {
18571         fprintf(fgxFile, "\"%7.3f\"", value);
18572     }
18573     else if (value >= 0.00010)
18574     {
18575         fprintf(fgxFile, "\"%7.5f\"", value);
18576     }
18577     else
18578     {
18579         fprintf(fgxFile, "\"%7E\"", value);
18580     }
18581 }
18582
18583 //------------------------------------------------------------------------
18584 // fgOpenFlowGraphFile: Open a file to dump either the xml or dot format flow graph
18585 //
18586 // Arguments:
18587 //    wbDontClose - A boolean out argument that indicates whether the caller should close the file
18588 //    phase       - A phase identifier to indicate which phase is associated with the dump
18589 //    type        - A (wide) string indicating the type of dump, "dot" or "xml"
18590 //
18591 // Return Value:
18592 //    Opens a file to which a flowgraph can be dumped, whose name is based on the current
18593 //    config vales.
18594
18595 FILE*              Compiler::fgOpenFlowGraphFile(bool*  wbDontClose, Phases phase, LPCWSTR type)
18596 {
18597     FILE*          fgxFile;
18598     LPCWSTR        pattern  = nullptr;
18599     LPCWSTR        filename = nullptr;
18600     LPCWSTR        pathname = nullptr;
18601     const char*    escapedString;
18602     bool           createDuplicateFgxFiles = true;
18603
18604 #ifdef DEBUG
18605     if (opts.eeFlags & CORJIT_FLG_PREJIT)
18606     {
18607         pattern = JitConfig.NgenDumpFg();
18608         filename = JitConfig.NgenDumpFgFile();
18609         pathname = JitConfig.NgenDumpFgDir();
18610     }
18611     else
18612     {
18613         pattern = JitConfig.JitDumpFg();
18614         filename = JitConfig.JitDumpFgFile();
18615         pathname = JitConfig.JitDumpFgDir();
18616     }
18617 #endif // DEBUG
18618
18619     if (fgBBcount <= 1) {
18620         return nullptr;
18621 }
18622
18623     if (pattern == nullptr) {
18624         return nullptr;
18625 }
18626
18627     if (wcslen(pattern) == 0) {
18628         return nullptr;
18629 }
18630
18631     LPCWSTR phasePattern = JitConfig.JitDumpFgPhase();
18632     LPCWSTR phaseName = PhaseShortNames[phase];
18633     if (phasePattern == nullptr)
18634     {
18635         if (phase != PHASE_DETERMINE_FIRST_COLD_BLOCK)
18636         {
18637             return nullptr;
18638         }
18639     }
18640     else if (*phasePattern != W('*'))
18641     {
18642         if (wcsstr(phasePattern, phaseName) == nullptr)
18643         {
18644             return nullptr;
18645         }
18646     }
18647
18648     if (*pattern != W('*'))
18649     {
18650         bool hasColon = (wcschr(pattern, W(':')) != nullptr);
18651
18652         if (hasColon)
18653         {
18654             const char* className = info.compClassName;
18655             if (*pattern == W('*'))
18656             {
18657                 pattern++;
18658             }
18659             else
18660             {
18661                 while ((*pattern != W(':')) && (*pattern != W('*')))
18662                 {
18663                     if (*pattern != *className) {
18664                         return nullptr;
18665 }
18666
18667                     pattern++;
18668                     className++;
18669                 }
18670                 if (*pattern == W('*'))
18671                 {
18672                     pattern++;
18673                 }
18674                 else
18675                 {
18676                     if (*className != 0) {
18677                         return nullptr;
18678 }
18679                 }
18680             }
18681             if (*pattern != W(':')) {
18682                 return nullptr;
18683 }
18684
18685             pattern++;
18686         }
18687
18688         const char* methodName = info.compMethodName;
18689         if (*pattern == W('*'))
18690         {
18691             pattern++;
18692         }
18693         else
18694         {
18695             while ((*pattern != 0) && (*pattern != W('*')))
18696             {
18697                 if (*pattern != *methodName) {
18698                     return nullptr;
18699 }
18700
18701                 pattern++;
18702                 methodName++;
18703             }
18704             if (*pattern == W('*'))
18705             {
18706                 pattern++;
18707             }
18708             else
18709             {
18710                 if (*methodName != 0) {
18711                     return nullptr;
18712 }
18713             }
18714         }
18715         if (*pattern != 0) {
18716             return nullptr;
18717 }
18718     }
18719
18720     if (filename == nullptr)
18721     {
18722         filename = W("default");
18723     }
18724
18725     if (wcscmp(filename, W("profiled")) == 0)
18726     {
18727         if ((fgFirstBB->bbFlags & BBF_PROF_WEIGHT) != 0)
18728         {
18729             createDuplicateFgxFiles = true;
18730             goto ONE_FILE_PER_METHOD;
18731         }
18732         else
18733         {
18734             return nullptr;
18735         }
18736     }
18737     if (wcscmp(filename, W("hot")) == 0)
18738     {
18739         if (info.compMethodInfo->regionKind == CORINFO_REGION_HOT)
18740
18741         {
18742             createDuplicateFgxFiles = true;
18743             goto ONE_FILE_PER_METHOD;
18744         }
18745         else
18746         {
18747             return nullptr;
18748         }
18749     }
18750     else if (wcscmp(filename, W("cold")) == 0)
18751     {
18752         if (info.compMethodInfo->regionKind == CORINFO_REGION_COLD)
18753         {
18754             createDuplicateFgxFiles = true;
18755             goto ONE_FILE_PER_METHOD;
18756         }
18757         else
18758         {
18759             return nullptr;
18760         }
18761     }
18762     else if (wcscmp(filename, W("jit")) == 0)
18763     {
18764         if (info.compMethodInfo->regionKind == CORINFO_REGION_JIT)
18765         {
18766             createDuplicateFgxFiles = true;
18767             goto ONE_FILE_PER_METHOD;
18768         }
18769         else
18770         {
18771             return nullptr;
18772         }
18773     }
18774     else if (wcscmp(filename, W("all")) == 0)
18775     {
18776         createDuplicateFgxFiles = true;
18777
18778 ONE_FILE_PER_METHOD:;
18779
18780         escapedString = fgProcessEscapes(info.compFullName, s_EscapeFileMapping);
18781         size_t wCharCount = strlen(escapedString) + wcslen(phaseName) + 1 + strlen("~999") + wcslen(type) + 1;
18782         if (pathname != nullptr)
18783         {
18784             wCharCount += wcslen(pathname) + 1;
18785         }
18786         filename = (LPCWSTR) alloca(wCharCount * sizeof(WCHAR));
18787         if (pathname != nullptr)
18788         {
18789             swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%S-%s.%s"), pathname, escapedString, phaseName, type);
18790         }
18791         else
18792         {
18793             swprintf_s((LPWSTR)filename, wCharCount, W("%S.%s"), escapedString, type);
18794         }
18795         fgxFile = _wfopen(filename, W("r"));   // Check if this file already exists
18796         if (fgxFile != nullptr)
18797         {
18798             // For Generic methods we will have both hot and cold versions
18799             if (createDuplicateFgxFiles == false)
18800             {
18801                 fclose(fgxFile);
18802                 return nullptr;
18803             }
18804             // Yes, this filename already exists, so create a different one by appending ~2, ~3, etc...
18805             for (int i = 2; i < 1000; i++)
18806             {
18807                 fclose(fgxFile);
18808                 if (pathname != nullptr)
18809                 {
18810                     swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%S~%d.%s"), pathname, escapedString, i, type);
18811                 }
18812                 else
18813                 {
18814                     swprintf_s((LPWSTR)filename, wCharCount, W("%S~%d.%s"), escapedString, i, type);
18815                 }
18816                 fgxFile = _wfopen(filename, W("r"));   // Check if this file exists
18817                 if (fgxFile == nullptr) {
18818                     break;
18819 }
18820             }
18821             // If we have already created 1000 files with this name then just fail
18822             if (fgxFile != nullptr)
18823             {
18824                 fclose(fgxFile);
18825                 return nullptr;
18826             }
18827         }
18828         fgxFile = _wfopen(filename, W("a+"));
18829         *wbDontClose = false;
18830     }
18831     else if (wcscmp(filename, W("stdout")) == 0)
18832     {
18833         fgxFile = jitstdout;
18834         *wbDontClose = true;
18835     }
18836     else if (wcscmp(filename, W("stderr")) == 0)
18837     {
18838         fgxFile = stderr;
18839         *wbDontClose = true;
18840     }
18841     else
18842     {
18843         LPCWSTR origFilename = filename;
18844         size_t wCharCount = wcslen(origFilename) + wcslen(type) + 2;
18845         if (pathname != nullptr)
18846         {
18847             wCharCount += wcslen(pathname) + 1;
18848         }
18849         filename = (LPCWSTR) alloca(wCharCount * sizeof(WCHAR));
18850         if (pathname != nullptr)
18851         {
18852             swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%s.%s"), pathname, origFilename, type);
18853         }
18854         else
18855         {
18856             swprintf_s((LPWSTR)filename, wCharCount, W("%s.%s"), origFilename, type);
18857         }
18858         fgxFile = _wfopen(filename, W("a+"));
18859         *wbDontClose = false;
18860     }
18861
18862     return fgxFile;
18863 }
18864
18865 //------------------------------------------------------------------------
18866 // fgDumpFlowGraph: Dump the xml or dot format flow graph, if enabled for this phase.
18867 //
18868 // Arguments:
18869 //    phase       - A phase identifier to indicate which phase is associated with the dump,
18870 //                  i.e. which phase has just completed.
18871 //
18872 // Return Value:
18873 //    True iff a flowgraph has been dumped.
18874 //
18875 // Notes:
18876 //    The xml dumps are the historical mechanism for dumping the flowgraph.
18877 //    The dot format can be viewed by:
18878 //    - Graphviz (http://www.graphviz.org/)
18879 //      - The command "C:\Program Files (x86)\Graphviz2.38\bin\dot.exe" -Tsvg -oFoo.svg -Kdot Foo.dot
18880 //        will produce a Foo.svg file that can be opened with any svg-capable browser (e.g. IE).
18881 //    - http://rise4fun.com/Agl/
18882 //      - Cut and paste the graph from your .dot file, replacing the digraph on the page, and then click the play
18883 //        button.
18884 //      - It will show a rotating '/' and then render the graph in the browser.
18885 //    MSAGL has also been open-sourced to https://github.com/Microsoft/automatic-graph-layout.git.
18886 //
18887 //    Here are the config values that control it:
18888 //      COMPlus_JitDumpFg       A string (ala the COMPlus_JitDump string) indicating what methods to dump flowgraphs
18889 //                              for.
18890 //      COMPlus_JitDumpFgDir    A path to a directory into which the flowgraphs will be dumped.
18891 //      COMPlus_JitDumpFgFile   The filename to use. The default is "default.[xml|dot]".
18892 //                              Note that the new graphs will be appended to this file if it already exists.
18893 //      COMPlus_JitDumpFgPhase  Phase(s) after which to dump the flowgraph.
18894 //                              Set to the short name of a phase to see the flowgraph after that phase.
18895 //                              Leave unset to dump after COLD-BLK (determine first cold block) or set to * for all
18896 //                              phases.
18897 //      COMPlus_JitDumpFgDot    Set to non-zero to emit Dot instead of Xml Flowgraph dump. (Default is xml format.)
18898
18899 bool               Compiler::fgDumpFlowGraph(Phases phase)
18900 {
18901     bool    result    = false;
18902     bool    dontClose = false;
18903     bool    createDotFile = false;
18904     if (JitConfig.JitDumpFgDot())
18905     {
18906         createDotFile = true;
18907     }
18908             
18909     FILE*   fgxFile   = fgOpenFlowGraphFile(&dontClose, phase, createDotFile ? W("dot") : W("fgx"));
18910
18911     if (fgxFile == nullptr)
18912     {
18913         return false;
18914     }
18915     bool           validWeights  = fgHaveValidEdgeWeights;
18916     unsigned       calledCount   = max(fgCalledWeight, BB_UNITY_WEIGHT) / BB_UNITY_WEIGHT;
18917     double         weightDivisor = (double) (calledCount * BB_UNITY_WEIGHT);
18918     const char*    escapedString;
18919     const char*    regionString  = "NONE";
18920
18921     if      (info.compMethodInfo->regionKind == CORINFO_REGION_HOT)
18922     {
18923         regionString="HOT";
18924     }
18925     else if (info.compMethodInfo->regionKind == CORINFO_REGION_COLD)
18926     {
18927         regionString="COLD";
18928     }
18929     else if (info.compMethodInfo->regionKind == CORINFO_REGION_JIT)
18930     {
18931         regionString="JIT";
18932     }
18933
18934     if (createDotFile)
18935     {
18936         fprintf(fgxFile, "digraph %s\n{\n", info.compMethodName);
18937         fprintf(fgxFile, "/* Method %d, after phase %s */", Compiler::jitTotalMethodCompiled, PhaseNames[phase]);
18938     }
18939     else
18940     {
18941         fprintf(fgxFile,   "<method");
18942
18943         escapedString = fgProcessEscapes(info.compFullName, s_EscapeMapping);
18944         fprintf(fgxFile, "\n    name=\"%s\"", escapedString);
18945
18946         escapedString = fgProcessEscapes(info.compClassName, s_EscapeMapping);
18947         fprintf(fgxFile, "\n    className=\"%s\"", escapedString);
18948
18949         escapedString = fgProcessEscapes(info.compMethodName, s_EscapeMapping);
18950         fprintf(fgxFile, "\n    methodName=\"%s\"", escapedString);
18951         fprintf(fgxFile, "\n    ngenRegion=\"%s\"", regionString);
18952
18953         fprintf(fgxFile, "\n    bytesOfIL=\"%d\"", info.compILCodeSize);
18954         fprintf(fgxFile, "\n    localVarCount=\"%d\"", lvaCount);
18955
18956         if (fgHaveProfileData())
18957         {
18958             fprintf(fgxFile, "\n    calledCount=\"%d\"", calledCount);
18959             fprintf(fgxFile, "\n    profileData=\"true\"");
18960         }
18961         if (compHndBBtabCount > 0)
18962         {
18963             fprintf(fgxFile, "\n    hasEHRegions=\"true\"");
18964         }
18965         if (fgHasLoops)
18966         {
18967             fprintf(fgxFile, "\n    hasLoops=\"true\"");
18968         }
18969         if (validWeights)
18970         {
18971             fprintf(fgxFile, "\n    validEdgeWeights=\"true\"");
18972             if (!fgSlopUsedInEdgeWeights && !fgRangeUsedInEdgeWeights)
18973             {
18974                 fprintf(fgxFile, "\n    exactEdgeWeights=\"true\"");
18975             }
18976         }
18977         if (fgFirstColdBlock != nullptr)
18978         {
18979             fprintf(fgxFile, "\n    firstColdBlock=\"%d\"", fgFirstColdBlock->bbNum);
18980         }
18981
18982         fprintf(fgxFile,        ">");
18983
18984         fprintf(fgxFile, "\n    <blocks");
18985         fprintf(fgxFile, "\n        blockCount=\"%d\"", fgBBcount);
18986         fprintf(fgxFile,            ">");
18987     }
18988
18989     static const char* kindImage[] = { "EHFINALLYRET", "EHFILTERRET", "EHCATCHRET", 
18990                                        "THROW", "RETURN", "NONE", "ALWAYS", "LEAVE",
18991                                        "CALLFINALLY", "COND", "SWITCH" };
18992
18993     BasicBlock* block;
18994     unsigned    blockOrdinal;
18995     for (block = fgFirstBB    , blockOrdinal = 1;
18996          block != nullptr;
18997          block = block->bbNext, blockOrdinal++)
18998     {
18999         if (createDotFile)
19000         {
19001             // Add constraint edges to try to keep nodes ordered.
19002             // It seems to work best if these edges are all created first.
19003             switch(block->bbJumpKind)
19004             {
19005             case BBJ_COND:
19006             case BBJ_NONE:
19007                 assert(block->bbNext != nullptr);
19008                 fprintf(fgxFile, "    BB%02u -> BB%02u\n", block->bbNum, block->bbNext->bbNum);
19009                 break;
19010             default:
19011                 // These may or may not have an edge to the next block.
19012                 // Add a transparent edge to keep nodes ordered.
19013                 if (block->bbNext != nullptr)
19014                 {
19015                     fprintf(fgxFile, "    BB%02u -> BB%02u [arrowtail=none,color=transparent]\n", block->bbNum, block->bbNext->bbNum);
19016                 }
19017             }
19018         }
19019         else
19020         {
19021             fprintf(fgxFile,"\n        <block");
19022             fprintf(fgxFile,"\n            id=\"%d\"", block->bbNum);
19023             fprintf(fgxFile,"\n            ordinal=\"%d\"", blockOrdinal);
19024             fprintf(fgxFile,"\n            jumpKind=\"%s\"", kindImage[block->bbJumpKind]);
19025             if (block->hasTryIndex())
19026             {
19027                 fprintf(fgxFile,"\n            inTry=\"%s\"", "true");
19028             }
19029             if (block->hasHndIndex())
19030             {
19031                 fprintf(fgxFile,"\n            inHandler=\"%s\"", "true");
19032             }
19033             if (((fgFirstBB->bbFlags & BBF_PROF_WEIGHT) != 0) &&
19034                 ((block->bbFlags     & BBF_COLD)        == 0)    )
19035             {
19036                 fprintf(fgxFile,"\n            hot=\"true\"");
19037             }
19038             if (block->bbFlags & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY))
19039             {
19040                 fprintf(fgxFile,"\n            callsNew=\"true\"");
19041             }
19042             if (block->bbFlags & BBF_LOOP_HEAD)
19043             {
19044                 fprintf(fgxFile,"\n            loopHead=\"true\"");
19045             }
19046             fprintf(fgxFile,"\n            weight=");
19047             fprintfDouble(fgxFile, ((double) block->bbWeight) / weightDivisor);
19048             fprintf(fgxFile,"\n            codeEstimate=\"%d\"", fgGetCodeEstimate(block));
19049             fprintf(fgxFile,"\n            startOffset=\"%d\"", block->bbCodeOffs);
19050             fprintf(fgxFile,"\n            endOffset=\"%d\"", block->bbCodeOffsEnd);
19051             fprintf(fgxFile,               ">");
19052             fprintf(fgxFile,"\n        </block>");
19053         }
19054     }
19055
19056     if (!createDotFile)
19057     {
19058         fprintf(fgxFile, "\n    </blocks>");
19059
19060         fprintf(fgxFile, "\n    <edges");
19061         fprintf(fgxFile, "\n        edgeCount=\"%d\"", fgEdgeCount);
19062         fprintf(fgxFile,            ">");
19063     }
19064
19065     unsigned edgeNum = 1;
19066     BasicBlock* bTarget;
19067     for (bTarget = fgFirstBB; bTarget != nullptr; bTarget = bTarget->bbNext)
19068     {
19069         double targetWeightDivisor;
19070         if (bTarget->bbWeight == BB_ZERO_WEIGHT)
19071         {
19072             targetWeightDivisor = 1.0;
19073         }
19074         else
19075         {
19076             targetWeightDivisor = (double) bTarget->bbWeight;
19077         }
19078
19079         flowList* edge;
19080         for (edge = bTarget->bbPreds; edge != nullptr; edge = edge->flNext, edgeNum++)
19081         {
19082             BasicBlock*  bSource = edge->flBlock;
19083             double       sourceWeightDivisor;
19084             if (bSource->bbWeight == BB_ZERO_WEIGHT)
19085             {
19086                 sourceWeightDivisor = 1.0;
19087             }
19088             else
19089             {
19090                 sourceWeightDivisor = (double) bSource->bbWeight;
19091             }
19092             if (createDotFile)
19093             {
19094                 // Don't duplicate the edges we added above.
19095                 if ((bSource->bbNum == (bTarget->bbNum - 1)) &&
19096                     ((bSource->bbJumpKind == BBJ_NONE) || (bSource->bbJumpKind == BBJ_COND)))
19097                 {
19098                     continue;
19099                 }
19100                 fprintf(fgxFile, "    BB%02u -> BB%02u", bSource->bbNum, bTarget->bbNum);
19101                 if ((bSource->bbNum > bTarget->bbNum))
19102                 {
19103                     fprintf(fgxFile, "[arrowhead=normal,arrowtail=none,color=green]\n");
19104                 }
19105                 else
19106                 {
19107                     fprintf(fgxFile, "\n");
19108                 }
19109             }
19110             else
19111             {
19112                 fprintf(fgxFile,"\n        <edge");
19113                 fprintf(fgxFile,"\n            id=\"%d\"", edgeNum);
19114                 fprintf(fgxFile,"\n            source=\"%d\"", bSource->bbNum);
19115                 fprintf(fgxFile,"\n            target=\"%d\"", bTarget->bbNum);
19116                 if (bSource->bbJumpKind == BBJ_SWITCH)
19117                 {
19118                     if (edge->flDupCount >= 2)
19119                     {
19120                         fprintf(fgxFile,"\n            switchCases=\"%d\"", edge->flDupCount);
19121                     }
19122                     if (bSource->bbJumpSwt->getDefault() == bTarget)
19123                     {
19124                         fprintf(fgxFile,"\n            switchDefault=\"true\"");
19125                     }
19126                 }
19127                 if (validWeights)
19128                 {
19129                     unsigned edgeWeight = (edge->flEdgeWeightMin + edge->flEdgeWeightMax) / 2;
19130                     fprintf(fgxFile,"\n            weight=");
19131                     fprintfDouble(fgxFile, ((double) edgeWeight) / weightDivisor);
19132
19133                     if (edge->flEdgeWeightMin != edge->flEdgeWeightMax)
19134                     {
19135                         fprintf(fgxFile,"\n            minWeight=");
19136                         fprintfDouble(fgxFile, ((double) edge->flEdgeWeightMin) / weightDivisor);
19137                         fprintf(fgxFile,"\n            maxWeight=");
19138                         fprintfDouble(fgxFile, ((double) edge->flEdgeWeightMax) / weightDivisor);
19139                     }
19140
19141                     if (edgeWeight > 0)
19142                     {
19143                         if (edgeWeight < bSource->bbWeight)
19144                         {
19145                             fprintf(fgxFile,"\n            out=");
19146                             fprintfDouble(fgxFile, ((double) edgeWeight) / sourceWeightDivisor );
19147                         }
19148                         if (edgeWeight < bTarget->bbWeight)
19149                         {
19150                             fprintf(fgxFile,"\n            in=");
19151                             fprintfDouble(fgxFile, ((double) edgeWeight) / targetWeightDivisor);
19152                         }
19153                     }
19154                 }
19155             }
19156             if (!createDotFile)
19157             {
19158                 fprintf(fgxFile,               ">");
19159                 fprintf(fgxFile,"\n        </edge>");
19160             }
19161         }
19162     }
19163     if (createDotFile)
19164     {
19165         fprintf(fgxFile, "}\n");
19166     }
19167     else
19168     {
19169         fprintf(fgxFile, "\n    </edges>");
19170         fprintf(fgxFile, "\n</method>\n");
19171     }
19172
19173     if (dontClose)
19174     {
19175         // fgxFile is jitstdout or stderr
19176         fprintf(fgxFile, "\n");
19177     }
19178     else
19179     {
19180         fclose(fgxFile);
19181     }
19182
19183     return result;
19184 }
19185
19186 #endif // DUMP_FLOWGRAPHS
19187
19188 /*****************************************************************************/
19189 #ifdef DEBUG
19190
19191 void                Compiler::fgDispReach()
19192 {
19193     printf("------------------------------------------------\n");
19194     printf("BBnum  Reachable by \n");
19195     printf("------------------------------------------------\n");
19196
19197     for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
19198     {
19199         printf("BB%02u : ", block->bbNum);
19200         BLOCKSET_ITER_INIT(this, iter, block->bbReach, bbNum);
19201         while (iter.NextElem(this, &bbNum))
19202         {
19203             printf("BB%02u ", bbNum);
19204         }
19205         printf("\n");
19206     }
19207 }
19208
19209 void                Compiler::fgDispDoms()
19210 {
19211     // Don't bother printing this when we have a large number of BasicBlocks in the method
19212     if (fgBBcount > 256)
19213     {
19214         return;
19215     }
19216
19217     printf("------------------------------------------------\n");
19218     printf("BBnum  Dominated by\n");
19219     printf("------------------------------------------------\n");
19220
19221     for (unsigned i = 1; i <= fgBBNumMax; ++i)
19222     {
19223         BasicBlock* current = fgBBInvPostOrder[i];
19224         printf("BB%02u:  ", current->bbNum);
19225         while (current != current->bbIDom)
19226         {
19227             printf("BB%02u ", current->bbNum);
19228             current = current->bbIDom;
19229         }
19230         printf("\n");
19231     }
19232 }
19233
19234 /*****************************************************************************/
19235
19236 void                Compiler::fgTableDispBasicBlock(BasicBlock* block,
19237                                                     int ibcColWidth /* = 0 */)
19238 {
19239     unsigned        flags = block->bbFlags;
19240
19241     unsigned bbNumMax = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax;
19242     int maxBlockNumWidth = CountDigits(bbNumMax);
19243     maxBlockNumWidth = max(maxBlockNumWidth, 2);
19244     int blockNumWidth = CountDigits(block->bbNum);
19245     blockNumWidth = max(blockNumWidth, 2);
19246     int blockNumPadding = maxBlockNumWidth - blockNumWidth;
19247
19248     printf("BB%02u%*s [%08p] %2u",
19249            block->bbNum,
19250            blockNumPadding, "",
19251            dspPtr(block),
19252            block->bbRefs);
19253
19254     //
19255     // Display EH 'try' region index
19256     //
19257
19258     if (block->hasTryIndex())
19259     {
19260         printf(" %2u", block->getTryIndex());
19261     }
19262     else
19263     {
19264         printf("   ");
19265     }
19266
19267     //
19268     // Display EH handler region index
19269     //
19270
19271     if (block->hasHndIndex())
19272     {
19273         printf(" %2u", block->getHndIndex());
19274     }
19275     else
19276     {
19277         printf("   ");
19278     }
19279
19280     printf(" ");
19281
19282     //
19283     // Display block predecessor list
19284     //
19285
19286     unsigned charCnt;
19287     if (fgCheapPredsValid)
19288     {
19289         charCnt = block->dspCheapPreds();
19290     }
19291     else
19292     {
19293         charCnt = block->dspPreds();
19294     }
19295
19296     if (charCnt < 19)
19297     {
19298         printf("%*s", 19 - charCnt, "");
19299     }
19300
19301     printf(" ");
19302
19303     //
19304     // Display block weight
19305     //
19306
19307     if (block->isMaxBBWeight())
19308     {
19309         printf(" MAX  ");
19310     }
19311     else
19312     {
19313         printf("%6s", refCntWtd2str(block->getBBWeight(this)));
19314     }
19315
19316     //
19317     // Display optional IBC weight column.
19318     // Note that iColWidth includes one character for a leading space, if there is an IBC column.
19319     //
19320
19321     if (ibcColWidth > 0)
19322     {
19323         if (block->bbFlags & BBF_PROF_WEIGHT)
19324         {
19325             printf("%*u", ibcColWidth, block->bbWeight);
19326         }
19327         else
19328         {
19329             // No IBC data. Just print spaces to align the column.
19330             printf("%*s", ibcColWidth, "");
19331         }
19332     }
19333
19334     printf(" ");
19335
19336     //
19337     // Display block IL range
19338     //
19339
19340     block->dspBlockILRange();
19341
19342     //
19343     // Display block branch target
19344     //
19345
19346     if  (flags & BBF_REMOVED)
19347     {
19348         printf(  "[removed]       ");
19349     }
19350     else
19351     {
19352         switch (block->bbJumpKind)
19353         {
19354         case BBJ_COND:
19355             printf("-> BB%02u%*s ( cond )", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19356             break;
19357
19358         case BBJ_CALLFINALLY:
19359             printf("-> BB%02u%*s (callf )", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19360             break;
19361
19362         case BBJ_ALWAYS:
19363             if (flags & BBF_KEEP_BBJ_ALWAYS)
19364             {
19365                 printf("-> BB%02u%*s (ALWAYS)", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19366             }
19367             else
19368             {
19369                 printf("-> BB%02u%*s (always)", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19370             }
19371             break;
19372
19373         case BBJ_LEAVE:
19374             printf("-> BB%02u%*s (leave )", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19375             break;
19376
19377         case BBJ_EHFINALLYRET:
19378             printf(  "%*s        (finret)", maxBlockNumWidth - 2, "");
19379             break;
19380
19381         case BBJ_EHFILTERRET:
19382             printf(  "%*s        (fltret)", maxBlockNumWidth - 2, "");
19383             break;
19384
19385         case BBJ_EHCATCHRET:
19386             printf("-> BB%02u%*s ( cret )", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), "");
19387             break;
19388
19389         case BBJ_THROW:
19390             printf(  "%*s        (throw )", maxBlockNumWidth - 2, "");
19391             break;
19392
19393         case BBJ_RETURN:
19394             printf(  "%*s        (return)", maxBlockNumWidth - 2, "");
19395             break;
19396
19397         default:
19398             printf(  "%*s                ", maxBlockNumWidth - 2, "");
19399             break;
19400
19401         case BBJ_SWITCH:
19402             printf("->");
19403
19404             unsigned        jumpCnt;
19405                             jumpCnt = block->bbJumpSwt->bbsCount;
19406             BasicBlock**    jumpTab;
19407                             jumpTab = block->bbJumpSwt->bbsDstTab;
19408             int             switchWidth;
19409                             switchWidth = 0;
19410             do
19411             {
19412                 printf("%cBB%02u",
19413                        (jumpTab == block->bbJumpSwt->bbsDstTab) ? ' ' : ',',
19414                        (*jumpTab)->bbNum);
19415                 switchWidth += 1 /* space/comma */ + 2 /* BB */ + max(CountDigits((*jumpTab)->bbNum), 2);
19416             }
19417             while (++jumpTab, --jumpCnt);
19418
19419             if (switchWidth < 7)
19420             {
19421                 printf("%*s", 8 - switchWidth, "");
19422             }
19423
19424             printf(" (switch)");
19425             break;
19426         }
19427     }
19428
19429     printf(" ");
19430
19431     //
19432     // Display block EH region and type, including nesting indicator
19433     //
19434
19435     if (block->hasTryIndex())
19436     {
19437         printf("T%d ", block->getTryIndex());
19438     }
19439     else
19440     {
19441         printf("   ");
19442     }
19443
19444     if (block->hasHndIndex())
19445     {
19446         printf("H%d ", block->getHndIndex());
19447     }
19448     else
19449     {
19450         printf("   ");
19451     }
19452
19453     if (flags & BBF_FUNCLET_BEG)
19454     {
19455         printf("F ");
19456     }
19457     else
19458     {
19459         printf("  ");
19460     }
19461
19462     int cnt = 0;
19463
19464     switch (block->bbCatchTyp)
19465     {
19466     case BBCT_NONE:            break;
19467     case BBCT_FAULT:           printf("fault ");   cnt += 6; break;
19468     case BBCT_FINALLY:         printf("finally "); cnt += 8; break;
19469     case BBCT_FILTER:          printf("filter ");  cnt += 7; break;
19470     case BBCT_FILTER_HANDLER:  printf("filtHnd "); cnt += 8; break;
19471     default:                   printf("catch ");   cnt += 6; break;
19472     }
19473
19474     if (block->bbCatchTyp != BBCT_NONE)
19475     {
19476         cnt += 2;
19477         printf("{ ");
19478         /* brace matching editor workaround to compensate for the preceding line: } */
19479     }
19480
19481     if (flags & BBF_TRY_BEG)
19482     {
19483         // Output a brace for every try region that this block opens
19484
19485         EHblkDsc* HBtab;
19486         EHblkDsc* HBtabEnd;
19487
19488         for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount;
19489              HBtab < HBtabEnd;
19490              HBtab++)
19491         {
19492             if (HBtab->ebdTryBeg == block)
19493             {
19494                 cnt += 6;
19495                 printf("try { ");
19496                 /* brace matching editor workaround to compensate for the preceding line: } */
19497             }
19498         }
19499     }
19500
19501     EHblkDsc* HBtab;
19502     EHblkDsc* HBtabEnd;
19503
19504     for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount;
19505          HBtab < HBtabEnd;
19506          HBtab++)
19507     {
19508         if (HBtab->ebdTryLast == block)
19509         {
19510             cnt += 2;
19511             /* brace matching editor workaround to compensate for the following line: { */
19512             printf("} ");
19513         }
19514         if (HBtab->ebdHndLast == block)
19515         {
19516             cnt += 2;
19517             /* brace matching editor workaround to compensate for the following line: { */
19518             printf("} ");
19519         }
19520         if (HBtab->HasFilter() && block->bbNext == HBtab->ebdHndBeg)
19521         {
19522             cnt += 2;
19523             /* brace matching editor workaround to compensate for the following line: { */
19524             printf("} ");
19525         }
19526     }
19527
19528     while (cnt < 12)
19529     {
19530         cnt++;
19531         printf(" ");
19532     }
19533
19534     //
19535     // Display block flags
19536     //
19537
19538     block->dspFlags();
19539
19540     printf("\n");
19541 }
19542
19543 /****************************************************************************
19544     Dump blocks from firstBlock to lastBlock.
19545 */
19546
19547 void                Compiler::fgDispBasicBlocks(BasicBlock*  firstBlock,
19548                                                 BasicBlock*  lastBlock,
19549                                                 bool         dumpTrees)
19550 {
19551     BasicBlock* block;
19552
19553     int padWidth = 0;
19554 #ifdef _TARGET_AMD64_
19555     padWidth = 8;
19556 #endif // _TARGET_AMD64_
19557
19558     // If any block has IBC data, we add an "IBC weight" column just before the 'IL range' column. This column is as
19559     // wide as necessary to accommodate all the various IBC weights. It's at least 4 characters wide, to accommodate
19560     // the "IBC" title and leading space.
19561     int ibcColWidth = 0;
19562     for (block = firstBlock; block != nullptr; block = block->bbNext)
19563     {
19564         if (block->bbFlags & BBF_PROF_WEIGHT)
19565         {
19566             int thisIbcWidth = CountDigits(block->bbWeight);
19567             ibcColWidth = max(ibcColWidth, thisIbcWidth);
19568         }
19569
19570         if (block == lastBlock) {
19571             break;
19572 }
19573     }
19574     if (ibcColWidth > 0)
19575     {
19576         ibcColWidth = max(ibcColWidth, 3) + 1; // + 1 for the leading space
19577     }
19578
19579     unsigned bbNumMax = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax;
19580     int maxBlockNumWidth = CountDigits(bbNumMax);
19581     maxBlockNumWidth = max(maxBlockNumWidth, 2);
19582
19583     padWidth += maxBlockNumWidth - 2; // Account for functions with a large number of blocks.
19584
19585     printf("\n");
19586     printf("------%*s------------------------------------%*s-----------------------%*s----------------------------------------\n",
19587         padWidth, "------------",
19588         ibcColWidth, "------------",
19589         maxBlockNumWidth, "----");
19590     printf("BBnum %*sdescAddr ref try hnd %s     weight  %*s%s [IL range]      [jump]%*s    [EH region]         [flags]\n",
19591         padWidth, "",
19592         fgCheapPredsValid       ? "cheap preds" :
19593         (fgComputePredsDone     ? "preds      "
19594                                 : "           "),
19595         ((ibcColWidth > 0) ? ibcColWidth - 3 : 0), "",  // Subtract 3 for the width of "IBC", printed next.
19596         ((ibcColWidth > 0)      ? "IBC"
19597                                 : ""),
19598         maxBlockNumWidth, ""
19599         );
19600     printf("------%*s------------------------------------%*s-----------------------%*s----------------------------------------\n",
19601         padWidth, "------------",
19602         ibcColWidth, "------------",
19603         maxBlockNumWidth, "----");
19604
19605     for (block = firstBlock;
19606          block;
19607          block = block->bbNext)
19608     {
19609         // First, do some checking on the bbPrev links
19610         if (block->bbPrev)
19611         {
19612             if (block->bbPrev->bbNext != block)
19613             {
19614                 printf("bad prev link\n");
19615             }
19616         }
19617         else if (block != fgFirstBB)
19618         {
19619             printf("bad prev link!\n");
19620         }
19621             
19622         if (block == fgFirstColdBlock)
19623         {
19624             printf("~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
19625                 padWidth, "~~~~~~~~~~~~",
19626                 ibcColWidth, "~~~~~~~~~~~~",
19627                 maxBlockNumWidth, "~~~~");
19628         }
19629
19630 #if FEATURE_EH_FUNCLETS
19631         if (block == fgFirstFuncletBB)
19632         {
19633             printf("++++++%*s++++++++++++++++++++++++++++++++++++%*s+++++++++++++++++++++++%*s++++++++++++++++++++++++++++++++++++++++ funclets follow\n",
19634                 padWidth, "++++++++++++",
19635                 ibcColWidth, "++++++++++++",
19636                 maxBlockNumWidth, "++++");
19637         }
19638 #endif // FEATURE_EH_FUNCLETS
19639
19640         fgTableDispBasicBlock(block, ibcColWidth);
19641
19642         if (block == lastBlock) {
19643             break;
19644 }
19645     }
19646
19647     printf("------%*s------------------------------------%*s-----------------------%*s----------------------------------------\n",
19648         padWidth, "------------",
19649         ibcColWidth, "------------",
19650         maxBlockNumWidth, "----");
19651
19652     if (dumpTrees)
19653     {
19654         fgDumpTrees(firstBlock, lastBlock);
19655     }
19656 }
19657
19658 /*****************************************************************************/
19659
19660 void                Compiler::fgDispBasicBlocks(bool dumpTrees)
19661 {
19662     fgDispBasicBlocks(fgFirstBB, nullptr, dumpTrees);
19663 }
19664
19665 /*****************************************************************************/
19666 //  Increment the stmtNum and dump the tree using gtDispTree
19667 //
19668 void                Compiler::fgDumpStmtTree(GenTreePtr stmt, unsigned blkNum)
19669 {
19670     compCurStmtNum++;  // Increment the current stmtNum
19671
19672     printf("\n***** BB%02u, stmt %d\n", blkNum, compCurStmtNum);
19673
19674     if (fgOrder == FGOrderLinear || opts.compDbgInfo)
19675     {
19676         gtDispTree(stmt);
19677     }
19678     else
19679     {
19680         gtDispTree(stmt->gtStmt.gtStmtExpr);
19681     }
19682 }
19683
19684 //------------------------------------------------------------------------
19685 // Compiler::fgDumpBlock: dumps the contents of the given block to stdout.
19686 //
19687 // Arguments:
19688 //    block - The block to dump.
19689 //
19690 void                Compiler::fgDumpBlock(BasicBlock* block)
19691 {
19692     printf("\n------------ ");
19693     block->dspBlockHeader(this);
19694
19695     if (!block->IsLIR())
19696     {
19697         for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
19698         {
19699             fgDumpStmtTree(stmt, block->bbNum);
19700             if (stmt == block->bbTreeList)
19701             {
19702                 block->bbStmtNum = compCurStmtNum;  // Set the block->bbStmtNum
19703             }
19704         }
19705     }
19706     else
19707     {
19708         gtDispRange(LIR::AsRange(block));
19709     }
19710 }
19711
19712 /*****************************************************************************/
19713 //  Walk the BasicBlock list calling fgDumpTree once per Stmt
19714 //
19715 void                Compiler::fgDumpTrees(BasicBlock*  firstBlock,
19716                                           BasicBlock*  lastBlock)
19717 {
19718     compCurStmtNum = 0;  // Reset the current stmtNum
19719
19720     /* Walk the basic blocks */
19721
19722     // Note that typically we have already called fgDispBasicBlocks() 
19723     //  so we don't need to print the preds and succs again here
19724     //
19725     for (BasicBlock* block = firstBlock; block; block = block->bbNext)
19726     {
19727         fgDumpBlock(block);
19728
19729         if (block == lastBlock) {
19730             break;
19731 }
19732     }
19733     printf("\n-------------------------------------------------------------------------------------------------------------------\n");
19734 }
19735
19736
19737 /*****************************************************************************
19738  * Try to create as many candidates for GTF_MUL_64RSLT as possible.
19739  * We convert 'intOp1*intOp2' into 'int(long(nop(intOp1))*long(intOp2))'.
19740  */
19741
19742 /* static */
19743 Compiler::fgWalkResult      Compiler::fgStress64RsltMulCB(GenTreePtr* pTree, fgWalkData* data)
19744 {
19745     GenTreePtr tree = *pTree;
19746     Compiler*  pComp = data->compiler;
19747     
19748     if (tree->gtOper != GT_MUL || tree->gtType != TYP_INT || (tree->gtOverflow())) {
19749         return WALK_CONTINUE;
19750 }
19751
19752     // To ensure optNarrowTree() doesn't fold back to the original tree.
19753     tree->gtOp.gtOp1 = pComp->gtNewOperNode(GT_NOP, TYP_LONG, tree->gtOp.gtOp1); 
19754     tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, TYP_LONG);
19755     tree->gtOp.gtOp2 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp2,  TYP_LONG);
19756     tree->gtType = TYP_LONG;
19757     *pTree = pComp->gtNewCastNode(TYP_INT, tree, TYP_INT);
19758
19759     return WALK_SKIP_SUBTREES;
19760 }
19761
19762 void                Compiler::fgStress64RsltMul()
19763 {
19764     if (!compStressCompile(STRESS_64RSLT_MUL, 20)) {
19765         return;
19766 }
19767
19768     fgWalkAllTreesPre(fgStress64RsltMulCB, (void*)this);
19769 }
19770
19771
19772 // This variable is used to generate "traversal labels": one-time constants with which
19773 // we label basic blocks that are members of the basic block list, in order to have a
19774 // fast, high-probability test for membership in that list.  Type is "volatile" because
19775 // it's incremented with an atomic operation, which wants a volatile type; "long" so that
19776 // wrap-around to 0 (which I think has the highest probability of accidental collision) is
19777 // postponed a *long* time.
19778 static volatile int bbTraverseLabel = 1;
19779
19780 /*****************************************************************************
19781  *
19782  * A DEBUG routine to check the consistency of the flowgraph,
19783  * i.e. bbNum, bbRefs, bbPreds have to be up to date.
19784  *
19785  *****************************************************************************/
19786
19787 void                Compiler::fgDebugCheckBBlist(bool checkBBNum  /* = false */,
19788                                                  bool checkBBRefs /* = true  */)
19789 {
19790 #ifdef DEBUG
19791     if (verbose)
19792     {
19793         printf("*************** In fgDebugCheckBBlist\n");
19794     }
19795 #endif // DEBUG
19796
19797     fgDebugCheckBlockLinks();
19798     
19799     if (fgBBcount > 10000 && expensiveDebugCheckLevel < 1)
19800     {
19801         // The basic block checks are too expensive if there are too many blocks,
19802         // so give up unless we've been told to try hard.
19803         return;
19804     }
19805
19806     DWORD startTickCount = GetTickCount();
19807
19808     BasicBlock* block;
19809     BasicBlock* prevBlock;
19810     BasicBlock* blockPred;
19811     flowList*   pred;
19812     unsigned    blockRefs;
19813
19814 #if FEATURE_EH_FUNCLETS
19815     bool            reachedFirstFunclet = false;
19816     if (fgFuncletsCreated)
19817     {
19818         //
19819         // Make sure that fgFirstFuncletBB is accurate.
19820         // It should be the first basic block in a handler region.
19821         //
19822         if (fgFirstFuncletBB != nullptr)
19823         {
19824             assert(fgFirstFuncletBB->hasHndIndex() == true);
19825             assert(fgFirstFuncletBB->bbFlags & BBF_FUNCLET_BEG);
19826         }
19827     }
19828 #endif // FEATURE_EH_FUNCLETS
19829
19830     /* Check bbNum, bbRefs and bbPreds */
19831     // First, pick a traversal stamp, and label all the blocks with it.
19832     unsigned curTraversalStamp = unsigned(InterlockedIncrement((LONG*)&bbTraverseLabel));
19833     for (block = fgFirstBB; block; block = block->bbNext)
19834     {
19835         block->bbTraversalStamp = curTraversalStamp;
19836     }
19837
19838     for (prevBlock = nullptr, block = fgFirstBB;
19839                               block;
19840          prevBlock = block,   block = block->bbNext)
19841     {
19842         blockRefs = 0;
19843
19844         /* First basic block has countOfInEdges() >= 1 */
19845
19846         if  (block == fgFirstBB)
19847         {
19848             noway_assert(block->countOfInEdges() >= 1);
19849             blockRefs = 1;
19850         }
19851
19852         if (checkBBNum)
19853         {
19854             // Check that bbNum is sequential
19855             noway_assert(block->bbNext == nullptr || (block->bbNum + 1 == block->bbNext->bbNum));
19856         }
19857
19858         // If the block is a BBJ_COND, a BBJ_SWITCH or a
19859         // lowered GT_SWITCH_TABLE node then make sure it
19860         // ends with a GT_JTRUE or a GT_SWITCH
19861
19862         if (block->bbJumpKind == BBJ_COND)
19863         {
19864             noway_assert(block->lastNode()->gtNext == nullptr && block->lastNode()->gtOper == GT_JTRUE);
19865         }
19866         else if (block->bbJumpKind == BBJ_SWITCH)
19867         {
19868 #ifndef LEGACY_BACKEND
19869             noway_assert(block->lastNode()->gtNext == nullptr &&
19870                          (block->lastNode()->gtOper == GT_SWITCH ||
19871                           block->lastNode()->gtOper == GT_SWITCH_TABLE));
19872 #else // LEGACY_BACKEND
19873             noway_assert(block->lastStmt()->gtNext == NULL &&
19874                          block->lastStmt()->gtStmtExpr->gtOper == GT_SWITCH);
19875 #endif // LEGACY_BACKEND
19876         }
19877         else if (!(   block->bbJumpKind == BBJ_ALWAYS
19878                    || block->bbJumpKind == BBJ_RETURN))
19879         {
19880             //this block cannot have a poll
19881             noway_assert(!(block->bbFlags & BBF_NEEDS_GCPOLL));
19882         }
19883
19884         if (block->bbCatchTyp == BBCT_FILTER)
19885         {
19886             if (!fgCheapPredsValid) // Don't check cheap preds
19887             {
19888                 // A filter has no predecessors
19889                 noway_assert(block->bbPreds == nullptr);
19890             }
19891         }
19892
19893 #if FEATURE_EH_FUNCLETS
19894         if (fgFuncletsCreated)
19895         {
19896             //
19897             // There should be no handler blocks until
19898             // we get to the fgFirstFuncletBB block,
19899             // then every block should be a handler block
19900             //
19901             if (!reachedFirstFunclet)
19902             {
19903                 if (block == fgFirstFuncletBB)
19904                 {
19905                     assert(block->hasHndIndex() == true);
19906                     reachedFirstFunclet = true;
19907                 }
19908                 else
19909                 {
19910                     assert(block->hasHndIndex() == false);
19911                 }
19912             }
19913             else // reachedFirstFunclet
19914             {
19915                 assert(block->hasHndIndex() == true);
19916             }
19917         }
19918 #endif // FEATURE_EH_FUNCLETS
19919
19920         // Don't check cheap preds.
19921         for (pred = (fgCheapPredsValid ? nullptr : block->bbPreds); pred != nullptr; blockRefs += pred->flDupCount, pred = pred->flNext)
19922         {
19923             assert(fgComputePredsDone); // If this isn't set, why do we have a preds list?
19924
19925             /*  make sure this pred is part of the BB list */
19926
19927             blockPred = pred->flBlock;
19928             noway_assert(blockPred->bbTraversalStamp == curTraversalStamp);
19929
19930             EHblkDsc* ehTryDsc = ehGetBlockTryDsc(block);
19931             if (ehTryDsc != nullptr)
19932             {
19933                 // You can jump to the start of a try
19934                 if (ehTryDsc->ebdTryBeg == block) {
19935                     goto CHECK_HND;
19936 }
19937
19938                 // You can jump within the same try region
19939                 if (bbInTryRegions(block->getTryIndex(), blockPred)) {
19940                     goto CHECK_HND;
19941 }
19942
19943                 // The catch block can jump back into the middle of the try
19944                 if (bbInCatchHandlerRegions(block, blockPred)) {
19945                     goto CHECK_HND;
19946 }
19947
19948                 // The end of a finally region is a BBJ_EHFINALLYRET block (during importing, BBJ_LEAVE) which
19949                 // is marked as "returning" to the BBJ_ALWAYS block following the BBJ_CALLFINALLY
19950                 // block that does a local call to the finally. This BBJ_ALWAYS is within
19951                 // the try region protected by the finally (for x86, ARM), but that's ok.
19952                 if (prevBlock->bbJumpKind == BBJ_CALLFINALLY &&
19953                         block->bbJumpKind == BBJ_ALWAYS &&
19954                     blockPred->bbJumpKind == BBJ_EHFINALLYRET) {
19955                     goto CHECK_HND;
19956 }
19957
19958                 printf("Jump into the middle of try region: BB%02u branches to BB%02u\n", blockPred->bbNum, block->bbNum);
19959                 noway_assert(!"Jump into middle of try region");
19960             }
19961
19962 CHECK_HND:;
19963
19964             EHblkDsc* ehHndDsc = ehGetBlockHndDsc(block);
19965             if (ehHndDsc != nullptr)
19966             {
19967                 // You can do a BBJ_EHFINALLYRET or BBJ_EHFILTERRET into a handler region
19968                 if (   (blockPred->bbJumpKind == BBJ_EHFINALLYRET)
19969                     || (blockPred->bbJumpKind == BBJ_EHFILTERRET)) {
19970                     goto CHECK_JUMP;
19971 }
19972
19973                 // Our try block can call our finally block
19974                 if ((block->bbCatchTyp == BBCT_FINALLY) &&
19975                     (blockPred->bbJumpKind == BBJ_CALLFINALLY) &&
19976                     ehCallFinallyInCorrectRegion(blockPred, block->getHndIndex()))
19977                 {
19978                     goto CHECK_JUMP;
19979                 }
19980
19981                 // You can jump within the same handler region
19982                 if (bbInHandlerRegions(block->getHndIndex(), blockPred)) {
19983                     goto CHECK_JUMP;
19984 }
19985
19986                 // A filter can jump to the start of the filter handler
19987                 if (ehHndDsc->HasFilter()) {
19988                     goto CHECK_JUMP;
19989 }
19990
19991                 printf("Jump into the middle of handler region: BB%02u branches to BB%02u\n", blockPred->bbNum, block->bbNum);
19992                 noway_assert(!"Jump into the middle of handler region");
19993             }
19994
19995 CHECK_JUMP:;
19996
19997             switch (blockPred->bbJumpKind)
19998             {
19999             case BBJ_COND:
20000                 noway_assert(blockPred->bbNext == block || blockPred->bbJumpDest == block);
20001                 break;
20002
20003             case BBJ_NONE:
20004                 noway_assert(blockPred->bbNext == block);
20005                 break;
20006
20007             case BBJ_CALLFINALLY:
20008             case BBJ_ALWAYS:
20009             case BBJ_EHCATCHRET:
20010             case BBJ_EHFILTERRET:
20011                 noway_assert(blockPred->bbJumpDest == block);
20012                 break;
20013
20014             case BBJ_EHFINALLYRET:
20015                 {
20016                     // If the current block is a successor to a BBJ_EHFINALLYRET (return from finally),
20017                     // then the lexically previous block should be a call to the same finally.
20018                     // Verify all of that.
20019
20020                     unsigned hndIndex = blockPred->getHndIndex();
20021                     EHblkDsc* ehDsc = ehGetDsc(hndIndex);
20022                     BasicBlock* finBeg = ehDsc->ebdHndBeg;
20023
20024                     // Because there is no bbPrev, we have to search for the lexically previous
20025                     // block.  We can shorten the search by only looking in places where it is legal
20026                     // to have a call to the finally.
20027
20028                     BasicBlock* begBlk;
20029                     BasicBlock* endBlk;
20030                     ehGetCallFinallyBlockRange(hndIndex, &begBlk, &endBlk);
20031
20032                     for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext)
20033                     {
20034                         if  (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg) {
20035                             continue;
20036 }
20037
20038                         if  (block == bcall->bbNext) {
20039                             goto PRED_OK;
20040 }
20041                     }
20042
20043 #if FEATURE_EH_FUNCLETS
20044
20045                     if (fgFuncletsCreated)
20046                     {
20047                         // There is no easy way to search just the funclets that were pulled out of
20048                         // the corresponding try body, so instead we search all the funclets, and if
20049                         // we find a potential 'hit' we check if the funclet we're looking at is
20050                         // from the correct try region.
20051
20052                         for (BasicBlock* bcall = fgFirstFuncletBB; bcall; bcall = bcall->bbNext)
20053                         {
20054                             if  (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg) {
20055                                 continue;
20056 }
20057
20058                             if  (block != bcall->bbNext) {
20059                                 continue;
20060 }
20061
20062                             if (ehCallFinallyInCorrectRegion(bcall, hndIndex)) {
20063                                 goto PRED_OK;
20064 }
20065                         }
20066                     }
20067
20068 #endif // FEATURE_EH_FUNCLETS
20069
20070                     noway_assert(!"BBJ_EHFINALLYRET predecessor of block that doesn't follow a BBJ_CALLFINALLY!");
20071                 }
20072                 break;
20073
20074             case BBJ_THROW:
20075             case BBJ_RETURN:
20076                 noway_assert(!"THROW and RETURN block cannot be in the predecessor list!");
20077                 break;
20078
20079             case BBJ_SWITCH:
20080                 unsigned        jumpCnt; jumpCnt = blockPred->bbJumpSwt->bbsCount;
20081                 BasicBlock**    jumpTab; jumpTab = blockPred->bbJumpSwt->bbsDstTab;
20082
20083                 do
20084                 {
20085                     if  (block == *jumpTab)
20086                     {
20087                         goto PRED_OK;
20088                     }
20089                 }
20090                 while (++jumpTab, --jumpCnt);
20091
20092                 noway_assert(!"SWITCH in the predecessor list with no jump label to BLOCK!");
20093                 break;
20094
20095             default:
20096                 noway_assert(!"Unexpected bbJumpKind");
20097                 break;
20098             }
20099
20100 PRED_OK:;
20101
20102         }
20103
20104         /* Check the bbRefs */
20105         noway_assert(!checkBBRefs || block->bbRefs == blockRefs);
20106
20107         /* Check that BBF_HAS_HANDLER is valid bbTryIndex */
20108         if (block->hasTryIndex())
20109         {
20110             noway_assert(block->getTryIndex() < compHndBBtabCount);
20111         }
20112
20113         /* Check if BBF_RUN_RARELY is set that we have bbWeight of zero */
20114         if (block->isRunRarely())
20115         {
20116             noway_assert(block->bbWeight == BB_ZERO_WEIGHT);
20117         }
20118         else
20119         {
20120             noway_assert(block->bbWeight > BB_ZERO_WEIGHT);
20121         }
20122     }
20123
20124     // Make sure the one return BB is not changed.
20125     if (genReturnBB)
20126     {
20127         noway_assert(genReturnBB->bbTreeList);
20128         noway_assert(genReturnBB->IsLIR() || genReturnBB->bbTreeList->gtOper == GT_STMT);
20129         noway_assert(genReturnBB->IsLIR() || genReturnBB->bbTreeList->gtType == TYP_VOID);
20130     }
20131
20132     // The general encoder/decoder (currently) only reports "this" as a generics context as a stack location,
20133     // so we mark info.compThisArg as lvAddrTaken to ensure that it is not enregistered. Otherwise, it should
20134     // not be address-taken.  This variable determines if the address-taken-ness of "thisArg" is "OK".
20135     bool copiedForGenericsCtxt;
20136 #ifndef JIT32_GCENCODER
20137     copiedForGenericsCtxt = ((info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0);
20138 #else  // JIT32_GCENCODER
20139     copiedForGenericsCtxt = FALSE;
20140 #endif  // JIT32_GCENCODER
20141
20142     // This if only in support of the noway_asserts it contains.
20143     if (info.compIsStatic)
20144     {
20145         // For static method, should have never grabbed the temp.
20146         noway_assert(lvaArg0Var == BAD_VAR_NUM);
20147     }
20148     else
20149     {
20150         // For instance method:
20151         assert(info.compThisArg != BAD_VAR_NUM);
20152         bool compThisArgAddrExposedOK = !lvaTable[info.compThisArg].lvAddrExposed;
20153 #ifndef JIT32_GCENCODER
20154         compThisArgAddrExposedOK = compThisArgAddrExposedOK || copiedForGenericsCtxt;
20155 #endif  // !JIT32_GCENCODER
20156         noway_assert(compThisArgAddrExposedOK &&                  //     should never expose the address of arg 0 or
20157                      !lvaTable[info.compThisArg].lvArgWrite &&    //     write to arg 0.
20158                      (                                                  //   In addition,
20159                         lvaArg0Var == info.compThisArg ||               //     lvArg0Var should remain 0 if arg0 is not written to or address-exposed.
20160                         lvaArg0Var != info.compThisArg &&
20161                         (lvaTable[lvaArg0Var].lvAddrExposed || lvaTable[lvaArg0Var].lvArgWrite || copiedForGenericsCtxt)
20162                      ));
20163     }
20164 }
20165
20166 /*****************************************************************************
20167  *
20168  * A DEBUG routine to check the that the exception flags are correctly set.
20169  *
20170  ****************************************************************************/
20171
20172 void                Compiler::fgDebugCheckFlags(GenTreePtr tree)
20173 {
20174     noway_assert(tree->gtOper != GT_STMT);
20175
20176     genTreeOps      oper        = tree->OperGet();
20177     unsigned        kind        = tree->OperKind();
20178     unsigned        treeFlags   = tree->gtFlags & GTF_ALL_EFFECT;
20179     unsigned        chkFlags    = 0;
20180
20181     /* Is this a leaf node? */
20182
20183     if  (kind & GTK_LEAF)
20184     {
20185         switch (oper)
20186         {
20187         case GT_CLS_VAR:
20188             chkFlags |= GTF_GLOB_REF;
20189             break;
20190
20191         case GT_CATCH_ARG:
20192             chkFlags |= GTF_ORDER_SIDEEFF;
20193             break;
20194
20195         default:
20196             break;
20197         }
20198     }
20199
20200     /* Is it a 'simple' unary/binary operator? */
20201
20202     else if  (kind & GTK_SMPOP)
20203     {
20204         GenTreePtr      op1 = tree->gtOp.gtOp1;
20205         GenTreePtr      op2 = tree->gtGetOp2();
20206
20207         // During GS work, we make shadow copies for params.
20208         // In gsParamsToShadows(), we create a shadow var of TYP_INT for every small type param.
20209         // Then in gsReplaceShadowParams(), we change the gtLclNum to the shadow var.
20210         // We also change the types of the local var tree and the assignment tree to TYP_INT if necessary.
20211         // However, since we don't morph the tree at this late stage. Manually propagating
20212         // TYP_INT up to the GT_ASG tree is only correct if we don't need to propagate the TYP_INT back up.
20213         // The following checks will ensure this.
20214
20215         // Is the left child of "tree" a GT_ASG?,
20216         if (op1 && op1->gtOper == GT_ASG)
20217         {
20218             assert(tree->gtType == TYP_VOID ||  // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
20219                    tree->gtOper == GT_COMMA);   // (or) If GT_ASG is the left child of a GT_COMMA, the type of the GT_COMMA node will
20220         }                                       // be determined by its right child. So we don't need to propagate TYP_INT up either. We are fine.
20221
20222         // Is the right child of "tree" a GT_ASG?,
20223         if (op2 && op2->gtOper == GT_ASG)
20224         {
20225             assert(tree->gtType == TYP_VOID);   // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine.
20226         }
20227
20228         switch (oper)
20229         {
20230         case GT_QMARK:
20231             if (op1->OperIsCompare())
20232             {
20233                 noway_assert(op1->gtFlags & GTF_DONT_CSE);
20234             }
20235             else
20236             {
20237                 noway_assert( (op1->gtOper == GT_CNS_INT) &&
20238                               ((op1->gtIntCon.gtIconVal == 0) || (op1->gtIntCon.gtIconVal == 1)) );
20239             }
20240             break;
20241
20242         case GT_LIST:
20243             if ((op2 != nullptr) && op2->IsList())
20244             {
20245                 ArrayStack<GenTree *> stack(this);
20246                 while ((tree->gtGetOp2() != nullptr) && tree->gtGetOp2()->IsList())
20247                 {
20248                     stack.Push(tree);
20249                     tree = tree->gtGetOp2();
20250                 }
20251
20252                 fgDebugCheckFlags(tree);
20253
20254                 while (stack.Height() > 0)
20255                 {
20256                     tree = stack.Pop();
20257                     assert((tree->gtFlags & GTF_REVERSE_OPS) == 0);
20258                     fgDebugCheckFlags(tree->gtOp.gtOp1);
20259                     chkFlags |= (tree->gtOp.gtOp1->gtFlags & GTF_ALL_EFFECT);
20260                     chkFlags |= (tree->gtGetOp2()->gtFlags & GTF_ALL_EFFECT);
20261                     fgDebugCheckFlagsHelper(tree, (tree->gtFlags & GTF_ALL_EFFECT), chkFlags);
20262                 }
20263
20264                 return;
20265             }
20266             break;
20267
20268         default:
20269             break;
20270         }
20271
20272         /* Recursively check the subtrees */
20273
20274         if (op1)
20275         {
20276             fgDebugCheckFlags(op1);
20277         }
20278         if (op2)
20279         {
20280             fgDebugCheckFlags(op2);
20281         }
20282
20283         if (op1) 
20284         {
20285             chkFlags   |= (op1->gtFlags & GTF_ALL_EFFECT);
20286         }
20287         if (op2)
20288         {
20289             chkFlags   |= (op2->gtFlags & GTF_ALL_EFFECT);
20290         }
20291
20292         // We reuse the value of GTF_REVERSE_OPS for a GT_IND-specific flag,
20293         // so exempt that (unary) operator.
20294         if (tree->OperGet() != GT_IND && tree->gtFlags & GTF_REVERSE_OPS)
20295         {
20296             /* Must have two operands if GTF_REVERSE is set */
20297             noway_assert(op1 && op2);
20298
20299             /* Make sure that the order of side effects has not been swapped. */
20300
20301             /* However CSE may introduce an assignment after the reverse flag
20302                was set and thus GTF_ASG cannot be considered here. */
20303
20304             /* For a GT_ASG(GT_IND(x), y) we are interested in the side effects of x */
20305             GenTreePtr  op1p;
20306             if ((kind & GTK_ASGOP) && (op1->gtOper == GT_IND))
20307             {
20308                 op1p = op1->gtOp.gtOp1;
20309             }
20310             else
20311             {
20312                 op1p = op1;
20313             }
20314
20315             /* This isn't true any more with the sticky GTF_REVERSE */
20316             /*
20317             // if op1p has side effects, then op2 cannot have side effects
20318             if (op1p->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
20319             {
20320                 if (op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG))
20321                     gtDispTree(tree);
20322                 noway_assert(!(op2->gtFlags & (GTF_SIDE_EFFECT & ~GTF_ASG)));
20323             }
20324             */
20325         }
20326
20327         if (kind & GTK_ASGOP)
20328         {
20329             chkFlags        |= GTF_ASG;
20330         }
20331
20332         /* Note that it is OK for treeFlags not to have a GTF_EXCEPT,
20333            AssertionProp's non-Null may have cleared it */
20334         if (tree->OperMayThrow())
20335         {
20336             chkFlags        |= (treeFlags & GTF_EXCEPT);
20337         }
20338
20339         if (oper == GT_ADDR &&
20340             (op1->OperIsLocal() ||
20341              op1->gtOper == GT_CLS_VAR ||
20342              (op1->gtOper == GT_IND && op1->gtOp.gtOp1->gtOper == GT_CLS_VAR_ADDR)))
20343         {
20344             /* &aliasedVar doesn't need GTF_GLOB_REF, though alisasedVar does.
20345                Similarly for clsVar */
20346             treeFlags |= GTF_GLOB_REF;
20347         }
20348     }
20349
20350     /* See what kind of a special operator we have here */
20351
20352     else 
20353     { 
20354         switch  (tree->OperGet())
20355         {
20356         case GT_CALL:
20357
20358             GenTreePtr      args;
20359             GenTreePtr      argx;
20360             GenTreeCall*    call;
20361         
20362             call = tree->AsCall();
20363
20364             chkFlags |= GTF_CALL;
20365
20366             if ((treeFlags & GTF_EXCEPT) && !(chkFlags & GTF_EXCEPT))
20367             {
20368                 switch (eeGetHelperNum(tree->gtCall.gtCallMethHnd))
20369                 {
20370                     // Is this a helper call that can throw an exception ?
20371                 case CORINFO_HELP_LDIV:
20372                 case CORINFO_HELP_LMOD:
20373                 case CORINFO_HELP_METHOD_ACCESS_CHECK:
20374                 case CORINFO_HELP_FIELD_ACCESS_CHECK:
20375                 case CORINFO_HELP_CLASS_ACCESS_CHECK:
20376                 case CORINFO_HELP_DELEGATE_SECURITY_CHECK:
20377                     chkFlags |= GTF_EXCEPT;
20378                     break;
20379                 default:
20380                     break;
20381                 }
20382             }
20383
20384             if (call->gtCallObjp)
20385             {
20386                 fgDebugCheckFlags(call->gtCallObjp);
20387                 chkFlags |= (call->gtCallObjp->gtFlags & GTF_SIDE_EFFECT);
20388
20389                 if (call->gtCallObjp->gtFlags & GTF_ASG)
20390                 {
20391                     treeFlags |= GTF_ASG;
20392                 }
20393             }
20394
20395             for (args = call->gtCallArgs; args; args = args->gtOp.gtOp2)
20396             {
20397                 argx = args->gtOp.gtOp1;
20398                 fgDebugCheckFlags(argx);
20399
20400                 chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT);
20401
20402                 if (argx->gtFlags & GTF_ASG)
20403                 {
20404                     treeFlags |= GTF_ASG;
20405                 }
20406             }
20407
20408             for (args = call->gtCallLateArgs; args; args = args->gtOp.gtOp2)
20409             {
20410                 argx = args->gtOp.gtOp1;
20411                 fgDebugCheckFlags(argx);
20412
20413                 chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT);
20414
20415                 if (argx->gtFlags & GTF_ASG)
20416                 {
20417                     treeFlags |= GTF_ASG;
20418                 }
20419             }
20420
20421             if ((call->gtCallType == CT_INDIRECT) && (call->gtCallCookie != nullptr))
20422             {
20423                 fgDebugCheckFlags(call->gtCallCookie);
20424                 chkFlags |= (call->gtCallCookie->gtFlags & GTF_SIDE_EFFECT);
20425             }
20426
20427             if (call->gtCallType == CT_INDIRECT)
20428             {
20429                 fgDebugCheckFlags(call->gtCallAddr);
20430                 chkFlags |= (call->gtCallAddr->gtFlags & GTF_SIDE_EFFECT);
20431             }
20432
20433             if (call->IsUnmanaged() &&
20434                 (call->gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL))
20435             {
20436                 if (call->gtCallArgs->gtOp.gtOp1->OperGet() == GT_NOP)
20437                 {
20438                     noway_assert(call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL ||
20439                                  call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF);
20440                 }
20441                 else
20442                 {
20443                     noway_assert(call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL ||
20444                                  call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF);
20445                 }
20446             }
20447             break;
20448
20449         case GT_ARR_ELEM:
20450
20451             GenTreePtr      arrObj;
20452             unsigned        dim;
20453
20454             arrObj = tree->gtArrElem.gtArrObj;
20455             fgDebugCheckFlags(arrObj);
20456             chkFlags   |= (arrObj->gtFlags & GTF_ALL_EFFECT);
20457
20458             for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
20459             {
20460                 fgDebugCheckFlags(tree->gtArrElem.gtArrInds[dim]);
20461                 chkFlags |= tree->gtArrElem.gtArrInds[dim]->gtFlags & GTF_ALL_EFFECT;
20462             }
20463             break;
20464
20465         case GT_ARR_OFFSET:
20466             fgDebugCheckFlags(tree->gtArrOffs.gtOffset);
20467             chkFlags   |= (tree->gtArrOffs.gtOffset->gtFlags & GTF_ALL_EFFECT);
20468             fgDebugCheckFlags(tree->gtArrOffs.gtIndex);
20469             chkFlags   |= (tree->gtArrOffs.gtIndex->gtFlags & GTF_ALL_EFFECT);
20470             fgDebugCheckFlags(tree->gtArrOffs.gtArrObj);
20471             chkFlags   |= (tree->gtArrOffs.gtArrObj->gtFlags & GTF_ALL_EFFECT);
20472             break;
20473
20474         default:
20475             break;
20476         }
20477     }
20478
20479     fgDebugCheckFlagsHelper(tree, treeFlags, chkFlags);
20480 }
20481
20482 //------------------------------------------------------------------------------
20483 // fgDebugCheckFlagsHelper : Check if all bits that are set in chkFlags are also set in treeFlags.
20484 //
20485 //
20486 // Arguments:
20487 //    tree  - Tree whose flags are being checked
20488 //    treeFlags - Actual flags on the tree
20489 //    chkFlags - Expected flags
20490 //
20491 // Note:
20492 //    Checking that all bits that are set in treeFlags are also set in chkFlags is currently disabled.
20493
20494 void  Compiler::fgDebugCheckFlagsHelper(GenTreePtr tree, unsigned treeFlags, unsigned chkFlags)
20495 {
20496     if (chkFlags & ~treeFlags)
20497     {
20498         // Print the tree so we can see it in the log.
20499         printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
20500         GenTree::gtDispFlags(chkFlags & ~treeFlags, GTF_DEBUG_NONE);
20501         printf("\n");
20502         gtDispTree(tree);
20503
20504         noway_assert(!"Missing flags on tree");
20505
20506         // Print the tree again so we can see it right after we hook up the debugger.
20507         printf("Missing flags on tree [%06d]: ", dspTreeID(tree));
20508         GenTree::gtDispFlags(chkFlags & ~treeFlags, GTF_DEBUG_NONE);
20509         printf("\n");
20510         gtDispTree(tree);
20511     }
20512     else if (treeFlags & ~chkFlags)
20513     {
20514 #if 0
20515         // TODO-Cleanup:
20516         /* The tree has extra flags set. However, this will happen if we
20517         replace a subtree with something, but don't clear the flags up
20518         the tree. Can't flag this unless we start clearing flags above.
20519
20520         Note: we need this working for GTF_CALL and CSEs, so I'm enabling
20521         it for calls.
20522         */
20523         if (tree->OperGet() != GT_CALL && (treeFlags & GTF_CALL) && !(chkFlags & GTF_CALL))
20524         {
20525             // Print the tree so we can see it in the log.
20526             printf("Extra GTF_CALL flags on parent tree [%X]: ", tree);
20527             GenTree::gtDispFlags(treeFlags & ~chkFlags, GTF_DEBUG_NONE);
20528             printf("\n");
20529             gtDispTree(tree);
20530
20531             noway_assert(!"Extra flags on tree");
20532
20533             // Print the tree again so we can see it right after we hook up the debugger.
20534             printf("Extra GTF_CALL flags on parent tree [%X]: ", tree);
20535             GenTree::gtDispFlags(treeFlags & ~chkFlags, GTF_DEBUG_NONE);
20536             printf("\n");
20537             gtDispTree(tree);
20538     }
20539 #endif // 0
20540 }
20541 }
20542
20543 // DEBUG routine to check correctness of the internal gtNext, gtPrev threading of a statement.
20544 // This threading is only valid when fgStmtListThreaded is true.
20545 // This calls an alternate method for FGOrderLinear.
20546 void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node)
20547 {
20548     // LIR blocks are checked using BasicBlock::CheckLIR().
20549     if (block->IsLIR())
20550     {
20551         LIR::AsRange(block).CheckLIR(this);
20552         // TODO: return?
20553     }
20554
20555     GenTreeStmt* stmt = node->AsStmt();
20556
20557     assert(fgStmtListThreaded);
20558
20559     noway_assert(stmt->gtStmtList);
20560
20561     // The first node's gtPrev must be nullptr (the gtPrev list is not circular).
20562     // The last node's gtNext must be nullptr (the gtNext list is not circular). This is tested if the loop below terminates.
20563     assert(stmt->gtStmtList->gtPrev == nullptr);
20564
20565     for (GenTreePtr tree = stmt->gtStmtList;
20566          tree != nullptr;
20567          tree = tree->gtNext)
20568     {
20569         if  (tree->gtPrev)
20570         {
20571             noway_assert(tree->gtPrev->gtNext == tree);
20572         }
20573         else
20574         {
20575             noway_assert(tree == stmt->gtStmtList);
20576         }
20577
20578         if  (tree->gtNext)
20579         {
20580             noway_assert(tree->gtNext->gtPrev == tree);
20581         }
20582         else
20583         {
20584             noway_assert(tree == stmt->gtStmtExpr);
20585         }
20586
20587         /* Cross-check gtPrev,gtNext with gtOp for simple trees */
20588
20589         GenTreePtr expectedPrevTree = nullptr;
20590
20591         if (tree->OperIsLeaf())
20592         {
20593             if (tree->gtOper == GT_CATCH_ARG)
20594             {
20595                 // The GT_CATCH_ARG should always have GTF_ORDER_SIDEEFF set
20596                 noway_assert(tree->gtFlags & GTF_ORDER_SIDEEFF);
20597                 // The GT_CATCH_ARG has to be the first thing evaluated
20598                 noway_assert(stmt == block->FirstNonPhiDef());
20599                 noway_assert(stmt->gtStmtList->gtOper == GT_CATCH_ARG);
20600                 // The root of the tree should have GTF_ORDER_SIDEEFF set
20601                 noway_assert(stmt->gtStmtExpr->gtFlags & GTF_ORDER_SIDEEFF);
20602             }
20603         }
20604
20605         if (tree->OperIsUnary() && tree->gtOp.gtOp1)
20606         {
20607             GenTreePtr lclVarTree;
20608             expectedPrevTree = tree->gtOp.gtOp1;
20609         }
20610         else if (tree->OperIsBinary() && tree->gtOp.gtOp1)
20611         {
20612             switch (tree->gtOper)
20613             {
20614             case GT_QMARK:
20615                 expectedPrevTree = tree->gtOp.gtOp2->AsColon()->ThenNode(); // "then" operand of the GT_COLON (generated second).
20616                 break;
20617
20618             case GT_COLON:
20619                 expectedPrevTree = tree->AsColon()->ElseNode(); // "else" branch result (generated first).
20620                 break;
20621
20622             case GT_INITBLK:
20623             case GT_COPYBLK:
20624             case GT_COPYOBJ:
20625                 // the first child is a GT_LIST, where has op1 is the dst and op2 is the src.
20626                 // The read has to occur before the write so make sure REVERSE_OPS is set.
20627                 assert(tree->gtOp.gtOp1->gtFlags & GTF_REVERSE_OPS);
20628                 __fallthrough;
20629
20630             default:
20631                 if (tree->gtOp.gtOp2)
20632                 {
20633                     if (tree->gtFlags & GTF_REVERSE_OPS)
20634                     {
20635                         expectedPrevTree = tree->gtOp.gtOp1;
20636                     }
20637                     else
20638                     {
20639                         expectedPrevTree = tree->gtOp.gtOp2;
20640                     }
20641                 }
20642                 else
20643                 {
20644                     expectedPrevTree = tree->gtOp.gtOp1;
20645                 }
20646                 break;
20647             }
20648         }
20649
20650         noway_assert(expectedPrevTree == nullptr ||                // No expectations about the prev node
20651                      tree->gtPrev == expectedPrevTree);         // The "normal" case
20652     }
20653 }
20654
20655
20656 /*****************************************************************************
20657  *
20658  * A DEBUG routine to check the correctness of the links between GT_STMT nodes
20659  * and ordinary nodes within a statement.
20660  *
20661  ****************************************************************************/
20662
20663 void                Compiler::fgDebugCheckLinks(bool morphTrees)
20664 {
20665     // This used to be only on for stress, and there was a comment stating that
20666     // it was "quite an expensive operation" but I did not find that to be true.
20667     // Set DO_SANITY_DEBUG_CHECKS to false to revert to that behavior.
20668     const bool DO_SANITY_DEBUG_CHECKS = true;
20669
20670     if (!DO_SANITY_DEBUG_CHECKS &&
20671         !compStressCompile(STRESS_CHK_FLOW_UPDATE, 30))
20672     {
20673         return;
20674     }
20675
20676     fgDebugCheckBlockLinks();
20677
20678     /* For each basic block check the bbTreeList links */
20679     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
20680     {
20681 PROCESS_BLOCK_AGAIN:;
20682         if (block->IsLIR())
20683         {
20684             LIR::AsRange(block).CheckLIR(this);
20685         }
20686         else
20687         {
20688             for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
20689             {
20690                 /* Verify that bbTreeList is threaded correctly */
20691                 /* Note that for the GT_STMT list, the gtPrev list is circular. The gtNext list is not: gtNext of the last GT_STMT in a block is nullptr. */
20692
20693                 noway_assert(stmt->gtPrev);
20694
20695                 if  (stmt == block->bbTreeList)
20696                 {
20697                     noway_assert(stmt->gtPrev->gtNext == nullptr);
20698                 }
20699                 else
20700                 {
20701                     noway_assert(stmt->gtPrev->gtNext == stmt);
20702                 }
20703
20704                 if  (stmt->gtNext)
20705                 {
20706                     noway_assert(stmt->gtNext->gtPrev == stmt);
20707                 }
20708                 else
20709                 {
20710                     noway_assert(block->lastStmt() == stmt);
20711                 }
20712
20713                 /* For each statement check that the exception flags are properly set */
20714
20715                 noway_assert(stmt->gtStmtExpr);
20716
20717                 if (verbose && 0)
20718                 {
20719                     gtDispTree(stmt->gtStmtExpr);
20720                 }
20721
20722                 fgDebugCheckFlags(stmt->gtStmtExpr);
20723
20724                 // Not only will this stress fgMorphBlockStmt(), but we also get all the checks
20725                 // done by fgMorphTree()
20726
20727                 if (morphTrees)
20728                 {
20729                     // If 'stmt' is removed from the block, restart
20730                     if (fgMorphBlockStmt(block, stmt DEBUGARG("test morphing")))
20731                     {
20732                         goto PROCESS_BLOCK_AGAIN;
20733                     }
20734                 }
20735
20736                 /* For each GT_STMT node check that the nodes are threaded correcly - gtStmtList */
20737
20738                 if (fgStmtListThreaded)
20739                 {
20740                     fgDebugCheckNodeLinks(block, stmt);
20741                 }
20742             }
20743         }
20744     }
20745 }
20746
20747 // ensure that bbNext and bbPrev are consistent
20748 void Compiler::fgDebugCheckBlockLinks()
20749 {
20750     assert(fgFirstBB->bbPrev == nullptr);
20751
20752     for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
20753     {
20754         if (block->bbNext)
20755         {
20756             assert(block->bbNext->bbPrev == block);
20757         }
20758         else
20759         {
20760             assert(block == fgLastBB);
20761         }
20762
20763         if (block->bbPrev)
20764         {
20765             assert(block->bbPrev->bbNext == block);
20766         }
20767         else
20768         {
20769             assert(block == fgFirstBB);
20770         }
20771
20772         // If this is a switch, check that the tables are consistent.
20773         // Note that we don't call GetSwitchDescMap(), because it has the side-effect
20774         // of allocating it if it is not present.
20775         if (block->bbJumpKind == BBJ_SWITCH && m_switchDescMap != nullptr)
20776         {
20777             SwitchUniqueSuccSet uniqueSuccSet;
20778             if (m_switchDescMap->Lookup(block, &uniqueSuccSet))
20779             {
20780                 // Create a set with all the successors. Don't use BlockSet, so we don't need to worry
20781                 // about the BlockSet epoch.
20782                 BitVecTraits bitVecTraits(fgBBNumMax + 1, this);
20783                 BitVec BITVEC_INIT_NOCOPY(succBlocks, BitVecOps::MakeEmpty(&bitVecTraits));
20784                 BasicBlock** jumpTable = block->bbJumpSwt->bbsDstTab;
20785                 unsigned jumpCount = block->bbJumpSwt->bbsCount;
20786                 for (unsigned i = 0; i < jumpCount; i++)
20787                 {
20788                     BitVecOps::AddElemD(&bitVecTraits, succBlocks, jumpTable[i]->bbNum);
20789                 }
20790                 // Now we should have a set of unique successors that matches what's in the switchMap.
20791                 // First, check the number of entries, then make sure all the blocks in uniqueSuccSet
20792                 // are in the BlockSet.
20793                 unsigned count = BitVecOps::Count(&bitVecTraits, succBlocks);
20794                 assert(uniqueSuccSet.numDistinctSuccs == count);
20795                 for (unsigned i = 0; i < uniqueSuccSet.numDistinctSuccs; i++)
20796                 {
20797                     assert(BitVecOps::IsMember(&bitVecTraits, succBlocks, uniqueSuccSet.nonDuplicates[i]->bbNum));
20798                 }
20799             }
20800         }
20801     }
20802 }
20803
20804 /*****************************************************************************/
20805 #endif // DEBUG
20806 /*****************************************************************************/
20807
20808 //------------------------------------------------------------------------
20809 // fgCheckForInlineDepthAndRecursion: compute depth of the candidate, and
20810 // check for recursion.
20811 //
20812 // Return Value:
20813 //    The depth of the inline candidate. The root method is a depth 0, top-level
20814 //    candidates at depth 1, etc.
20815 //
20816 // Notes:
20817 //    We generally disallow recursive inlines by policy. However, they are
20818 //    supported by the underlying machinery.
20819 //
20820 //    Likewise the depth limit is a policy consideration, and serves mostly
20821 //    as a safeguard to prevent runaway inlining of small methods.
20822
20823 unsigned     Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo)
20824 {
20825     BYTE*          candidateCode = inlineInfo->inlineCandidateInfo->methInfo.ILCode;
20826     InlineContext* inlineContext = inlineInfo->iciStmt->gtStmt.gtInlineContext;
20827     InlineResult*  inlineResult  = inlineInfo->inlineResult;
20828
20829     // There should be a context for all candidates.
20830     assert(inlineContext != nullptr);
20831     int depth = 0;
20832
20833     for (; inlineContext != nullptr; inlineContext = inlineContext->GetParent())
20834     {
20835
20836         depth++;
20837
20838         if (inlineContext->GetCode() == candidateCode)
20839         {
20840             // This inline candidate has the same IL code buffer as an already
20841             // inlined method does.
20842             inlineResult->NoteFatal(InlineObservation::CALLSITE_IS_RECURSIVE);
20843             break;
20844         }
20845
20846         if (depth > InlineStrategy::IMPLEMENTATION_MAX_INLINE_DEPTH)
20847         {
20848             break;
20849         }
20850     }
20851
20852     inlineResult->NoteInt(InlineObservation::CALLSITE_DEPTH, depth);
20853     return depth;
20854 }
20855
20856 /*****************************************************************************
20857  *
20858  *  Inlining phase
20859  */
20860
20861
20862 void                Compiler::fgInline()
20863 {
20864     if (!opts.OptEnabled(CLFLG_INLINING)) {
20865         return;
20866 }
20867
20868 #ifdef DEBUG
20869     if  (verbose) {
20870         printf("*************** In fgInline()\n");
20871 }
20872 #endif // DEBUG
20873
20874     BasicBlock* block = fgFirstBB;
20875     noway_assert(block != nullptr);
20876
20877     // Set the root inline context on all statements
20878     InlineContext* rootContext = m_inlineStrategy->GetRootContext();
20879
20880     for (; block != nullptr; block = block->bbNext)
20881     {
20882         for (GenTreeStmt* stmt = block->firstStmt();
20883              stmt;
20884              stmt = stmt->gtNextStmt)
20885         {
20886             stmt->gtInlineContext = rootContext;
20887         }
20888     }
20889
20890     // Reset block back to start for inlining
20891     block = fgFirstBB;
20892
20893     do
20894     {
20895         /* Make the current basic block address available globally */
20896
20897         compCurBB = block;
20898
20899         GenTreeStmt* stmt;
20900         GenTreePtr   expr;
20901
20902         for (stmt = block->firstStmt();
20903              stmt != nullptr;
20904              stmt = stmt->gtNextStmt)
20905         {
20906             expr = stmt->gtStmtExpr;
20907
20908             // See if we can expand the inline candidate
20909             if ((expr->gtOper == GT_CALL) && ((expr->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0))
20910             {
20911                 GenTreeCall* call = expr->AsCall();
20912                 InlineResult inlineResult(this, call, stmt, "fgInline");
20913
20914                 fgMorphStmt = stmt;
20915
20916                 fgMorphCallInline(call, &inlineResult);
20917
20918                 if (stmt->gtStmtExpr->IsNothingNode())
20919                 {
20920                     fgRemoveStmt(block, stmt);
20921                     continue;
20922                 }
20923             }
20924             else
20925             {
20926 #ifdef DEBUG
20927                 // Look for non-candidates.
20928                 fgWalkTreePre(&stmt->gtStmtExpr, fgFindNonInlineCandidate, stmt);
20929 #endif
20930             }
20931
20932             // See if we need to replace the return value place holder.
20933             fgWalkTreePre(&stmt->gtStmtExpr,
20934                           fgUpdateInlineReturnExpressionPlaceHolder,
20935                           (void *) this);
20936
20937             // See if stmt is of the form GT_COMMA(call, nop)
20938             // If yes, we can get rid of GT_COMMA.            
20939             if (expr->OperGet() == GT_COMMA &&
20940                 expr->gtOp.gtOp1->OperGet() == GT_CALL &&
20941                 expr->gtOp.gtOp2->OperGet() == GT_NOP)
20942             {
20943                 stmt->gtStmtExpr = expr->gtOp.gtOp1;
20944             }
20945         }
20946
20947         block = block->bbNext;
20948
20949     } while (block);
20950
20951 #ifdef DEBUG
20952
20953     // Check that we should not have any inline candidate or return value place holder left.
20954
20955     block = fgFirstBB;
20956     noway_assert(block);
20957
20958     do
20959     {
20960         GenTreeStmt* stmt;
20961
20962         for (stmt = block->firstStmt();
20963              stmt;
20964              stmt = stmt->gtNextStmt)
20965         {
20966             // Call Compiler::fgDebugCheckInlineCandidates on each node
20967             fgWalkTreePre(&stmt->gtStmtExpr, fgDebugCheckInlineCandidates);
20968         }
20969
20970         block = block->bbNext;
20971
20972     } while (block);
20973
20974     fgVerifyHandlerTab();
20975
20976     if  (verbose)
20977     {
20978         printf("*************** After fgInline()\n");
20979         fgDispBasicBlocks(true);
20980         fgDispHandlerTab();
20981     }
20982
20983     if  (verbose || fgPrintInlinedMethods)
20984     {
20985        printf("**************** Inline Tree\n");
20986        m_inlineStrategy->Dump();
20987     }
20988
20989 #endif // DEBUG
20990 }
20991
20992 #ifdef DEBUG
20993
20994 //------------------------------------------------------------------------
20995 // fgFindNonInlineCandidate: tree walk helper to ensure that a tree node
20996 // that is not an inline candidate is noted as a failed inline.
20997 //
20998 // Arguments:
20999 //    pTree - pointer to pointer tree node being walked
21000 //    data  - contextual data for the walk
21001 //
21002 // Return Value:
21003 //    walk result
21004 //
21005 // Note:
21006 //    Invokes fgNoteNonInlineCandidate on the nodes it finds.
21007
21008 Compiler::fgWalkResult      Compiler::fgFindNonInlineCandidate(GenTreePtr* pTree,
21009                                                                fgWalkData* data)
21010 {
21011     GenTreePtr tree = *pTree;
21012     if (tree->gtOper == GT_CALL)
21013     {
21014         Compiler*    compiler = data->compiler;
21015         GenTreePtr   stmt     = (GenTreePtr) data->pCallbackData;
21016         GenTreeCall* call     = tree->AsCall();
21017
21018         compiler->fgNoteNonInlineCandidate(stmt, call);
21019     }
21020     return WALK_CONTINUE;
21021 }
21022
21023 //------------------------------------------------------------------------
21024 // fgNoteNonInlineCandidate: account for inlining failures in calls
21025 // not marked as inline candidates.
21026 //
21027 // Arguments:
21028 //    tree  - statement containing the call
21029 //    call  - the call itself
21030 //
21031 // Notes:
21032 //    Used in debug only to try and place descriptions of inline failures
21033 //    into the proper context in the inline tree.
21034
21035 void Compiler::fgNoteNonInlineCandidate(GenTreePtr   tree,
21036                                         GenTreeCall* call)
21037 {
21038     InlineResult inlineResult(this, call, nullptr, "fgNotInlineCandidate");
21039     InlineObservation currentObservation = InlineObservation::CALLSITE_NOT_CANDIDATE;
21040
21041     // Try and recover the reason left behind when the jit decided
21042     // this call was not a candidate.
21043     InlineObservation priorObservation = call->gtInlineObservation;
21044
21045     if (InlIsValidObservation(priorObservation))
21046     {
21047         currentObservation = priorObservation;
21048     }
21049
21050     // Would like to just call noteFatal here, since this
21051     // observation blocked candidacy, but policy comes into play
21052     // here too.  Also note there's no need to re-report these
21053     // failures, since we reported them during the initial
21054     // candidate scan.
21055     InlineImpact impact = InlGetImpact(currentObservation);
21056
21057     if (impact == InlineImpact::FATAL)
21058     {
21059         inlineResult.NoteFatal(currentObservation);
21060     }
21061     else
21062     {
21063         inlineResult.Note(currentObservation);
21064     }
21065
21066     inlineResult.SetReported();
21067
21068     if (call->gtCallType == CT_USER_FUNC)
21069     {
21070         // Create InlineContext for the failure
21071         m_inlineStrategy->NewFailure(tree, &inlineResult);
21072     }
21073 }
21074
21075 #endif
21076
21077 #if FEATURE_MULTIREG_RET
21078
21079 /*********************************************************************************
21080  *
21081  * tree - The node which needs to be converted to a struct pointer.
21082  *
21083  *  Return the pointer by either __replacing__ the tree node with a suitable pointer
21084  *  type or __without replacing__ and just returning a subtree or by __modifying__
21085  *  a subtree.
21086  */
21087 GenTreePtr Compiler::fgGetStructAsStructPtr(GenTreePtr tree)
21088 {
21089     noway_assert((tree->gtOper == GT_LCL_VAR) ||
21090                  (tree->gtOper == GT_FIELD)   ||
21091                  (tree->gtOper == GT_IND)     ||
21092                  (tree->gtOper == GT_OBJ)     ||
21093                  tree->OperIsSIMD()           ||
21094                  // tree->gtOper == GT_CALL     || cannot get address of call.
21095                  // tree->gtOper == GT_MKREFANY || inlining should've been aborted due to mkrefany opcode.
21096                  // tree->gtOper == GT_RET_EXPR || cannot happen after fgUpdateInlineReturnExpressionPlaceHolder
21097                  (tree->gtOper == GT_COMMA));
21098
21099     switch (tree->OperGet())
21100     {
21101     case GT_OBJ:
21102     case GT_IND:
21103         return tree->gtOp.gtOp1;
21104
21105     case GT_COMMA:
21106         tree->gtOp.gtOp2 = fgGetStructAsStructPtr(tree->gtOp.gtOp2);
21107         tree->gtType = TYP_BYREF;
21108         return tree;
21109
21110     default:
21111         return gtNewOperNode(GT_ADDR, TYP_BYREF, tree);
21112     }
21113 }
21114
21115 /***************************************************************************************************
21116  * child     - The inlinee of the retExpr node.
21117  * retClsHnd - The struct class handle of the type of the inlinee.
21118  *
21119  * Assign the inlinee to a tmp, if it is a call, just assign it to a lclVar, else we can
21120  * use a copyblock to do the assignment.
21121  */
21122 GenTreePtr Compiler::fgAssignStructInlineeToVar(GenTreePtr child, CORINFO_CLASS_HANDLE retClsHnd)
21123 {
21124     assert(child->gtOper != GT_RET_EXPR && child->gtOper != GT_MKREFANY);
21125
21126     unsigned tmpNum = lvaGrabTemp(false DEBUGARG("RetBuf for struct inline return candidates."));
21127     lvaSetStruct(tmpNum, retClsHnd, false);
21128     var_types structType = lvaTable[tmpNum].lvType;
21129
21130     GenTreePtr dst = gtNewLclvNode(tmpNum, structType);
21131
21132     // If we have a call, we'd like it to be: V00 = call(), but first check if
21133     // we have a ", , , call()" -- this is very defensive as we may never get
21134     // an inlinee that is made of commas. If the inlinee is not a call, then
21135     // we use a copy block to do the assignment.
21136     GenTreePtr src = child;
21137     GenTreePtr lastComma = NULL;
21138     while (src->gtOper == GT_COMMA)
21139     {
21140         lastComma = src;
21141         src = src->gtOp.gtOp2;
21142     }
21143
21144     GenTreePtr newInlinee = NULL;
21145     if (src->gtOper == GT_CALL)
21146     {
21147         // If inlinee was just a call, new inlinee is v05 = call()
21148         newInlinee = gtNewAssignNode(dst, src);
21149
21150         // When returning a multi-register value in a local var, make sure the variable is
21151         // marked as lvIsMultiRegRet, so it does not get promoted.
21152         if (src->AsCall()->HasMultiRegRetVal())
21153         {
21154             lvaTable[tmpNum].lvIsMultiRegRet = true;
21155         }
21156
21157         // If inlinee was comma, but a deeper call, new inlinee is (, , , v05 = call())
21158         if (child->gtOper == GT_COMMA)
21159         {
21160             lastComma->gtOp.gtOp2 = newInlinee;
21161             newInlinee = child;
21162         }
21163     }
21164     else
21165     {
21166         // Inlinee is not a call, so just create a copy block to the tmp.
21167         src = child;
21168         GenTreePtr dstAddr = fgGetStructAsStructPtr(dst);
21169         GenTreePtr srcAddr = fgGetStructAsStructPtr(src);
21170         newInlinee = gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false);
21171     }
21172
21173     GenTreePtr production = gtNewLclvNode(tmpNum, structType);
21174     return gtNewOperNode(GT_COMMA, structType, newInlinee, production);
21175 }
21176
21177 /***************************************************************************************************
21178  * tree      - The tree pointer that has one of its child nodes as retExpr.
21179  * child     - The inlinee child.
21180  * retClsHnd - The struct class handle of the type of the inlinee.
21181  *
21182  * V04 = call() assignments are okay as we codegen it. Everything else needs to be a copy block or
21183  * would need a temp. For example, a cast(ldobj) will then be, cast(v05 = ldobj, v05); But it is
21184  * a very rare (or impossible) scenario that we'd have a retExpr transform into a ldobj other than
21185  * a lclVar/call. So it is not worthwhile to do pattern matching optimizations like addr(ldobj(op1))
21186  * can just be op1.
21187  */
21188 void Compiler::fgAttachStructInlineeToAsg(GenTreePtr tree, GenTreePtr child, CORINFO_CLASS_HANDLE retClsHnd)
21189 {
21190     // We are okay to have:
21191     // 1. V02 = call();
21192     // 2. copyBlk(dstAddr, srcAddr);
21193     assert(tree->gtOper == GT_ASG);
21194
21195     // We have an assignment, we codegen only V05 = call().
21196     if (child->gtOper == GT_CALL && tree->gtOp.gtOp1->gtOper == GT_LCL_VAR)
21197     {
21198         return;
21199     }
21200
21201     GenTreePtr dstAddr = fgGetStructAsStructPtr(tree->gtOp.gtOp1);
21202     GenTreePtr srcAddr = fgGetStructAsStructPtr((child->gtOper == GT_CALL)
21203                             ? fgAssignStructInlineeToVar(child, retClsHnd) // Assign to a variable if it is a call.
21204                             : child);                                   // Just get the address, if not a call.
21205
21206     tree->CopyFrom(gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false), this);
21207 }
21208
21209 #endif // FEATURE_MULTIREG_RET
21210
21211 /*****************************************************************************
21212  * Callback to replace the inline return expression place holder (GT_RET_EXPR)
21213  */
21214
21215 /* static */
21216 Compiler::fgWalkResult      Compiler::fgUpdateInlineReturnExpressionPlaceHolder(GenTreePtr* pTree,
21217                                                                                 fgWalkData* data)
21218 {
21219     GenTreePtr tree = *pTree;
21220     Compiler*  comp = data->compiler;
21221     CORINFO_CLASS_HANDLE retClsHnd = NO_CLASS_HANDLE;
21222
21223     if (tree->gtOper == GT_RET_EXPR)
21224     {
21225         // We are going to copy the tree from the inlinee, 
21226         // so record the handle now.
21227         //
21228         if (varTypeIsStruct(tree))
21229         {
21230             retClsHnd = tree->gtRetExpr.gtRetClsHnd;
21231         }
21232
21233         do
21234         {
21235             // Obtained the expanded inline candidate
21236             GenTreePtr inlineCandidate = tree->gtRetExpr.gtInlineCandidate;
21237
21238 #ifdef DEBUG
21239             if (comp->verbose)
21240             {
21241                 printf("\nReplacing the return expression placeholder ");              
21242                 printTreeID(tree);
21243                 printf(" with ");
21244                 printTreeID(inlineCandidate);
21245                 printf("\n");
21246                 // Dump out the old return expression placeholder it will be overwritten by the CopyFrom below
21247                 comp->gtDispTree(tree);
21248             }
21249 #endif // DEBUG
21250
21251             tree->CopyFrom(inlineCandidate, comp);           
21252
21253 #ifdef DEBUG
21254             if (comp->verbose)
21255             {
21256                 printf("\nInserting the inline return expression\n");
21257                 comp->gtDispTree(tree);
21258                 printf("\n");
21259             }
21260 #endif // DEBUG
21261         }
21262         while (tree->gtOper == GT_RET_EXPR);
21263     }
21264
21265 #if FEATURE_MULTIREG_RET
21266
21267     // Did we record a struct return class handle above?
21268     //
21269     if (retClsHnd != NO_CLASS_HANDLE)
21270     {
21271         // Is this a type that is returned in multiple registers?
21272         // if so we need to force into into a form we accept.
21273         // i.e. LclVar = call()
21274         //
21275         if (comp->IsMultiRegReturnedType(retClsHnd))
21276         {
21277             GenTreePtr parent = data->parent;
21278             // See assert below, we only look one level above for an asg parent.
21279             if (parent->gtOper == GT_ASG)
21280             {
21281                 // Either lhs is a call V05 = call(); or lhs is addr, and asg becomes a copyBlk.
21282                 comp->fgAttachStructInlineeToAsg(parent, tree, retClsHnd);
21283             }
21284             else
21285             {
21286                 // Just assign the inlinee to a variable to keep it simple.
21287                 tree->CopyFrom(comp->fgAssignStructInlineeToVar(tree, retClsHnd), comp);
21288             }
21289         }
21290     }
21291
21292 #if defined(DEBUG)
21293
21294     // Make sure we don't have a tree like so: V05 = (, , , retExpr);
21295     // Since we only look one level above for the parent for '=' and
21296     // do not check if there is a series of COMMAs. See above.
21297     // Importer and FlowGraph will not generate such a tree, so just
21298     // leaving an assert in here. This can be fixed by looking ahead
21299     // when we visit GT_ASG similar to fgAttachStructInlineeToAsg.
21300     //
21301     if ((tree->gtOper == GT_ASG) && (tree->gtOp.gtOp2->gtOper == GT_COMMA))
21302     {
21303         GenTreePtr comma;
21304         for (comma = tree->gtOp.gtOp2;
21305              comma->gtOper == GT_COMMA;
21306              comma = comma->gtOp.gtOp2)
21307         {
21308             // empty
21309         }
21310
21311         noway_assert(!varTypeIsStruct(comma) ||
21312                      comma->gtOper != GT_RET_EXPR ||
21313                      !comp->IsMultiRegReturnedType(comma->gtRetExpr.gtRetClsHnd));
21314     }
21315
21316 #endif // defined(DEBUG)
21317 #endif // FEATURE_MULTIREG_RET
21318
21319     return WALK_CONTINUE;
21320 }
21321
21322 #ifdef DEBUG
21323
21324 /*****************************************************************************
21325  * Callback to make sure there is no more GT_RET_EXPR and GTF_CALL_INLINE_CANDIDATE nodes.
21326  */
21327
21328 /* static */
21329 Compiler::fgWalkResult      Compiler::fgDebugCheckInlineCandidates(GenTreePtr* pTree,
21330                                                                    fgWalkData* data)
21331 {
21332     GenTreePtr tree = *pTree;
21333     if (tree->gtOper == GT_CALL)
21334     {
21335         assert((tree->gtFlags & GTF_CALL_INLINE_CANDIDATE) == 0);
21336     }
21337     else
21338     {
21339         assert(tree->gtOper != GT_RET_EXPR);
21340     }
21341
21342     return WALK_CONTINUE;
21343 }
21344
21345 #endif // DEBUG
21346
21347
21348 void       Compiler::fgInvokeInlineeCompiler(GenTreeCall*  call,
21349                                              InlineResult* inlineResult)
21350 {
21351     noway_assert(call->gtOper == GT_CALL);
21352     noway_assert((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0);
21353     noway_assert(opts.OptEnabled(CLFLG_INLINING));
21354
21355     // This is the InlineInfo struct representing a method to be inlined.
21356     InlineInfo inlineInfo = {nullptr};
21357
21358     CORINFO_METHOD_HANDLE fncHandle = call->gtCallMethHnd;
21359
21360     inlineInfo.fncHandle             = fncHandle;
21361     inlineInfo.iciCall               = call;
21362     inlineInfo.iciStmt               = fgMorphStmt;
21363     inlineInfo.iciBlock              = compCurBB;
21364     inlineInfo.thisDereferencedFirst = false;
21365     inlineInfo.retExpr               = nullptr;
21366     inlineInfo.inlineResult          = inlineResult;
21367 #ifdef FEATURE_SIMD
21368     inlineInfo.hasSIMDTypeArgLocalOrReturn = false;
21369 #endif // FEATURE_SIMD
21370
21371     InlineCandidateInfo* inlineCandidateInfo = call->gtInlineCandidateInfo;
21372     noway_assert(inlineCandidateInfo);
21373     // Store the link to inlineCandidateInfo into inlineInfo
21374     inlineInfo.inlineCandidateInfo = inlineCandidateInfo;
21375
21376     unsigned inlineDepth = fgCheckInlineDepthAndRecursion(&inlineInfo);
21377
21378     if (inlineResult->IsFailure())
21379     {
21380 #ifdef DEBUG
21381         if (verbose)
21382         {
21383             printf("Recursive or deep inline recursion detected. Will not expand this INLINECANDIDATE \n");
21384         }
21385 #endif // DEBUG
21386         return;
21387     }
21388
21389     // Set the trap to catch all errors (including recoverable ones from the EE)
21390     struct Param
21391     {
21392         Compiler* pThis;
21393         GenTree* call;
21394         CORINFO_METHOD_HANDLE fncHandle;
21395         InlineCandidateInfo* inlineCandidateInfo;
21396         InlineInfo* inlineInfo;
21397     } param = {nullptr};
21398
21399     param.pThis = this;
21400     param.call = call;
21401     param.fncHandle = fncHandle;
21402     param.inlineCandidateInfo = inlineCandidateInfo;
21403     param.inlineInfo = &inlineInfo;
21404     bool success = eeRunWithErrorTrap<Param>([](Param* pParam)
21405     {
21406         // Init the local var info of the inlinee
21407         pParam->pThis->impInlineInitVars(pParam->inlineInfo);
21408
21409         if (pParam->inlineInfo->inlineResult->IsCandidate())
21410         {
21411             /* Clear the temp table */
21412             memset(pParam->inlineInfo->lclTmpNum, -1, sizeof(pParam->inlineInfo->lclTmpNum));
21413
21414             //
21415             // Prepare the call to jitNativeCode
21416             //
21417
21418             pParam->inlineInfo->InlinerCompiler = pParam->pThis;
21419             if (pParam->pThis->impInlineInfo == nullptr)
21420             {
21421                 pParam->inlineInfo->InlineRoot = pParam->pThis;
21422             }
21423             else
21424             {
21425                 pParam->inlineInfo->InlineRoot = pParam->pThis->impInlineInfo->InlineRoot;
21426             }
21427             pParam->inlineInfo->argCnt                   = pParam->inlineCandidateInfo->methInfo.args.totalILArgs();
21428             pParam->inlineInfo->tokenLookupContextHandle = pParam->inlineCandidateInfo->exactContextHnd;
21429
21430             JITLOG_THIS(pParam->pThis,
21431                         (LL_INFO100000,
21432                          "INLINER: inlineInfo.tokenLookupContextHandle for %s set to 0x%p:\n",
21433                          pParam->pThis->eeGetMethodFullName(pParam->fncHandle),
21434                          pParam->pThis->dspPtr(pParam->inlineInfo->tokenLookupContextHandle)));
21435
21436             CORJIT_FLAGS compileFlagsForInlinee;
21437             memcpy(&compileFlagsForInlinee, pParam->pThis->opts.jitFlags, sizeof(compileFlagsForInlinee));
21438             compileFlagsForInlinee.corJitFlags &= ~CORJIT_FLG_LOST_WHEN_INLINING;
21439             compileFlagsForInlinee.corJitFlags |= CORJIT_FLG_SKIP_VERIFICATION;
21440
21441 #ifdef DEBUG
21442             if (pParam->pThis->verbose)
21443             {
21444                 printf("\nInvoking compiler for the inlinee method %s :\n",
21445                        pParam->pThis->eeGetMethodFullName(pParam->fncHandle));
21446             }
21447 #endif // DEBUG
21448
21449             int result = jitNativeCode(pParam->fncHandle,
21450                           pParam->inlineCandidateInfo->methInfo.scope,
21451                           pParam->pThis->info.compCompHnd,
21452                           &pParam->inlineCandidateInfo->methInfo,
21453                           (void**)pParam->inlineInfo,
21454                           nullptr,
21455                           &compileFlagsForInlinee,
21456                           pParam->inlineInfo);
21457
21458             if (result != CORJIT_OK)
21459             {
21460                 // If we haven't yet determined why this inline fails, use
21461                 // a catch-all something bad happened observation.
21462                 InlineResult* innerInlineResult = pParam->inlineInfo->inlineResult;
21463
21464                 if (!innerInlineResult->IsFailure())
21465                 {
21466                     innerInlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_FAILURE);
21467                 }
21468             }
21469         }
21470     }, &param);
21471     if (!success)
21472     {
21473 #ifdef DEBUG
21474         if (verbose)
21475         {
21476              printf("\nInlining failed due to an exception during invoking the compiler for the inlinee method %s.\n",
21477                     eeGetMethodFullName(fncHandle));
21478         }
21479 #endif // DEBUG
21480
21481         // If we haven't yet determined why this inline fails, use
21482         // a catch-all something bad happened observation.
21483         if (!inlineResult->IsFailure())
21484         {
21485             inlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_ERROR);
21486         }
21487     }
21488
21489     if (inlineResult->IsFailure())
21490     {
21491         return;
21492     }
21493
21494 #ifdef DEBUG
21495     if (0 && verbose)
21496     {
21497          printf("\nDone invoking compiler for the inlinee method %s\n",
21498                 eeGetMethodFullName(fncHandle));
21499     }
21500 #endif // DEBUG
21501
21502     // If there is non-NULL return, but we haven't set the pInlineInfo->retExpr,
21503     // That means we haven't imported any BB that contains CEE_RET opcode.
21504     // (This could happen for example for a BBJ_THROW block fall through a BBJ_RETURN block which
21505     // causes the BBJ_RETURN block not to be imported at all.)
21506     // Fail the inlining attempt
21507     if (inlineCandidateInfo->fncRetType != TYP_VOID && inlineInfo.retExpr == nullptr)
21508     {
21509 #ifdef DEBUG
21510         if (verbose)
21511         {
21512             printf("\nInlining failed because pInlineInfo->retExpr is not set in the inlinee method %s.\n",
21513                     eeGetMethodFullName(fncHandle));
21514         }
21515 #endif // DEBUG
21516         inlineResult->NoteFatal(InlineObservation::CALLEE_LACKS_RETURN);
21517         return;
21518     }
21519
21520     if (inlineCandidateInfo->initClassResult & CORINFO_INITCLASS_SPECULATIVE)
21521     {
21522         // we defer the call to initClass() until inlining is completed in case it fails. If inlining succeeds,
21523         // we will call initClass().
21524         if (!(info.compCompHnd->initClass(nullptr /* field */, fncHandle /* method */,
21525                 inlineCandidateInfo->exactContextHnd /* context */) & CORINFO_INITCLASS_INITIALIZED))
21526         {
21527             inlineResult->NoteFatal(InlineObservation::CALLEE_CLASS_INIT_FAILURE);
21528             return;
21529         }
21530     }
21531
21532     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21533     // The inlining attempt cannot be failed starting from this point.
21534     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21535
21536     // We've successfully obtain the list of inlinee's basic blocks.
21537     // Let's insert it to inliner's basic block list.
21538     fgInsertInlineeBlocks(&inlineInfo);
21539
21540 #ifdef DEBUG
21541
21542     if (verbose || fgPrintInlinedMethods)
21543     {
21544         printf("Successfully inlined %s (%d IL bytes) (depth %d) [%s]\n",
21545                eeGetMethodFullName(fncHandle),
21546                inlineCandidateInfo->methInfo.ILCodeSize,
21547                inlineDepth,
21548                inlineResult->ReasonString());
21549     }
21550
21551     if (verbose)
21552     {
21553         printf("--------------------------------------------------------------------------------------------\n");
21554     }
21555 #endif // DEBUG
21556
21557 #if defined(DEBUG)
21558     impInlinedCodeSize += inlineCandidateInfo->methInfo.ILCodeSize;
21559 #endif
21560
21561     // We inlined...
21562     inlineResult->NoteSuccess();
21563 }
21564
21565 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21566 // The inlining attempt cannot be failed starting from this point.
21567 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21568 void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo)
21569 {
21570     GenTreePtr   iciCall     = pInlineInfo->iciCall;
21571     GenTreePtr   iciStmt     = pInlineInfo->iciStmt;
21572     BasicBlock*  iciBlock    = pInlineInfo->iciBlock;
21573     BasicBlock*  block;
21574
21575     // We can write better assert here. For example, we can check that
21576     // iciBlock contains iciStmt, which in turn contains iciCall.
21577     noway_assert(iciBlock->bbTreeList != nullptr);
21578     noway_assert(iciStmt->gtStmt.gtStmtExpr != nullptr);
21579     noway_assert(iciCall->gtOper == GT_CALL);
21580
21581 #ifdef DEBUG
21582
21583     GenTreePtr currentDumpStmt = nullptr;
21584
21585     if (verbose)
21586     {
21587         printf("\n\n----------- Statements (and blocks) added due to the inlining of call ");
21588         printTreeID(iciCall);
21589         printf(" -----------\n");
21590         // gtDispTree(iciStmt);
21591     }
21592
21593 #endif // DEBUG
21594
21595     //
21596     // Create a new inline context and mark the inlined statements with it
21597     //
21598     InlineContext* calleeContext = m_inlineStrategy->NewSuccess(pInlineInfo);
21599
21600     for (block = InlineeCompiler->fgFirstBB;
21601          block != nullptr;
21602          block = block->bbNext)
21603     {
21604         for (GenTreeStmt* stmt = block->firstStmt();
21605              stmt;
21606              stmt = stmt->gtNextStmt)
21607         {
21608             stmt->gtInlineContext = calleeContext;
21609         }
21610     }
21611
21612     //
21613     // Prepend statements.
21614     //
21615     GenTreePtr stmtAfter;
21616     stmtAfter = fgInlinePrependStatements(pInlineInfo);
21617
21618 #ifdef DEBUG
21619     if (verbose)
21620     {
21621         currentDumpStmt = stmtAfter;
21622         printf("\nInlinee method body:");
21623     }
21624 #endif // DEBUG
21625
21626     if (InlineeCompiler->fgBBcount == 1)
21627     {
21628         // When fgBBCount is 1 we will always have a non-NULL fgFirstBB
21629         //
21630         PREFAST_ASSUME(InlineeCompiler->fgFirstBB != nullptr);
21631
21632         // DDB 91389: Don't throw away the (only) inlinee block
21633         // when its return type is not BBJ_RETURN.
21634         // In other words, we need its BBJ_ to perform the right thing.
21635         if (InlineeCompiler->fgFirstBB->bbJumpKind == BBJ_RETURN)
21636         {
21637             // Inlinee contains just one BB. So just insert its statement list to topBlock.
21638             if (InlineeCompiler->fgFirstBB->bbTreeList)
21639             {
21640                 stmtAfter = fgInsertStmtListAfter(iciBlock,
21641                                                   stmtAfter,
21642                                                   InlineeCompiler->fgFirstBB->bbTreeList);
21643
21644                 // Copy inlinee bbFlags to caller bbFlags.
21645                 const unsigned int inlineeBlockFlags = InlineeCompiler->fgFirstBB->bbFlags;
21646                 noway_assert((inlineeBlockFlags & BBF_HAS_JMP) == 0);
21647                 noway_assert((inlineeBlockFlags & BBF_KEEP_BBJ_ALWAYS) == 0);
21648                 iciBlock->bbFlags |= inlineeBlockFlags;
21649             }
21650 #ifdef DEBUG
21651             if (verbose)
21652             {
21653                 noway_assert(currentDumpStmt);
21654
21655                 if  (currentDumpStmt != stmtAfter)
21656                 {
21657                     do
21658                     {
21659                         currentDumpStmt = currentDumpStmt->gtNext;
21660
21661                         printf("\n");
21662
21663                         noway_assert(currentDumpStmt->gtOper == GT_STMT);
21664
21665                         gtDispTree(currentDumpStmt);
21666                         printf("\n");
21667
21668                     }  while (currentDumpStmt != stmtAfter);
21669                 }
21670             }
21671 #endif // DEBUG
21672             goto _Done;
21673         }
21674     }
21675
21676     //
21677     // ======= Inserting inlinee's basic blocks ===============
21678     //
21679
21680     BasicBlock* topBlock;
21681     BasicBlock* bottomBlock;
21682
21683     topBlock = iciBlock;
21684
21685     bottomBlock = fgNewBBafter(topBlock->bbJumpKind, topBlock, true);
21686     bottomBlock->bbRefs = 1;
21687     bottomBlock->bbJumpDest = topBlock->bbJumpDest;
21688     bottomBlock->inheritWeight(topBlock);
21689
21690     topBlock->bbJumpKind = BBJ_NONE;
21691
21692     // Update block flags
21693     unsigned originalFlags;
21694     originalFlags = topBlock->bbFlags;
21695     noway_assert((originalFlags & BBF_SPLIT_NONEXIST) == 0);
21696     topBlock->bbFlags    &= ~(BBF_SPLIT_LOST);
21697     bottomBlock->bbFlags |= originalFlags & BBF_SPLIT_GAINED;
21698
21699     //
21700     // Split statements between topBlock and bottomBlock
21701     //
21702     GenTreePtr topBlock_Begin;
21703     GenTreePtr topBlock_End;
21704     GenTreePtr bottomBlock_Begin;
21705     GenTreePtr bottomBlock_End;
21706
21707     topBlock_Begin = nullptr;
21708     topBlock_End = nullptr;
21709     bottomBlock_Begin = nullptr;
21710     bottomBlock_End = nullptr;
21711
21712     //
21713     // First figure out bottomBlock_Begin
21714     //
21715
21716     bottomBlock_Begin = stmtAfter->gtNext;
21717
21718     if (topBlock->bbTreeList == nullptr)
21719     {
21720         // topBlock is empty before the split.
21721         // In this case, both topBlock and bottomBlock should be empty
21722         noway_assert(bottomBlock_Begin == nullptr);
21723         topBlock->bbTreeList = nullptr;
21724         bottomBlock->bbTreeList = nullptr;
21725     }
21726     else if (topBlock->bbTreeList == bottomBlock_Begin)
21727     {
21728         noway_assert(bottomBlock_Begin);
21729
21730         // topBlock contains at least one statement before the split.
21731         // And the split is before the first statement.
21732         // In this case, topBlock should be empty, and everything else should be moved to the bottonBlock.
21733         bottomBlock->bbTreeList = topBlock->bbTreeList;
21734         topBlock->bbTreeList = nullptr;
21735     }
21736     else if (bottomBlock_Begin == nullptr)
21737     {
21738         noway_assert(topBlock->bbTreeList);
21739
21740         // topBlock contains at least one statement before the split.
21741         // And the split is at the end of the topBlock.
21742         // In this case, everything should be kept in the topBlock, and the bottomBlock should be empty
21743
21744         bottomBlock->bbTreeList = nullptr;
21745     }
21746     else
21747     {
21748         noway_assert(topBlock->bbTreeList);
21749         noway_assert(bottomBlock_Begin);
21750
21751         // This is the normal case where both blocks should contain at least one statement.
21752         topBlock_Begin  = topBlock->bbTreeList;
21753         noway_assert(topBlock_Begin);
21754         topBlock_End    = bottomBlock_Begin->gtPrev;
21755         noway_assert(topBlock_End);
21756         bottomBlock_End = topBlock->lastStmt();
21757         noway_assert(bottomBlock_End);
21758
21759         // Break the linkage between 2 blocks.
21760         topBlock_End->gtNext = nullptr;
21761
21762         // Fix up all the pointers.
21763         topBlock->bbTreeList         = topBlock_Begin;
21764         topBlock->bbTreeList->gtPrev = topBlock_End;
21765
21766         bottomBlock->bbTreeList         = bottomBlock_Begin;
21767         bottomBlock->bbTreeList->gtPrev = bottomBlock_End;
21768     }
21769
21770     //
21771     // Set the try and handler index and fix the jump types of inlinee's blocks.
21772     //
21773
21774     bool inheritWeight;
21775     inheritWeight = true; // The firstBB does inherit the weight from the iciBlock
21776
21777     for (block = InlineeCompiler->fgFirstBB;
21778          block != nullptr;
21779          block = block->bbNext)
21780     {
21781         noway_assert(!block->hasTryIndex());
21782         noway_assert(!block->hasHndIndex());
21783         block->copyEHRegion(iciBlock);
21784         block->bbFlags   |=  iciBlock->bbFlags & BBF_BACKWARD_JUMP;
21785
21786         if (iciStmt->gtStmt.gtStmtILoffsx != BAD_IL_OFFSET)
21787         {
21788             block->bbCodeOffs    = jitGetILoffs(iciStmt->gtStmt.gtStmtILoffsx);
21789             block->bbCodeOffsEnd = block->bbCodeOffs + 1;  // TODO: is code size of 1 some magic number for inlining?
21790         }
21791         else
21792         {
21793             block->bbCodeOffs     = 0; // TODO: why not BAD_IL_OFFSET?
21794             block->bbCodeOffsEnd  = 0;
21795             block->bbFlags    |= BBF_INTERNAL;
21796         }
21797
21798         if (block->bbJumpKind == BBJ_RETURN)
21799         {
21800             inheritWeight = true; // A return block does inherit the weight from the iciBlock
21801             noway_assert((block->bbFlags & BBF_HAS_JMP) == 0);
21802             if (block->bbNext)
21803             {
21804                 block->bbJumpKind = BBJ_ALWAYS;
21805                 block->bbJumpDest = bottomBlock;
21806 #ifdef DEBUG
21807                 if (verbose)
21808                 {
21809                     printf("\nConvert bbJumpKind of BB%02u to BBJ_ALWAYS to bottomBlock BB%02u\n",
21810                            block->bbNum, bottomBlock->bbNum);
21811                 }
21812 #endif // DEBUG
21813             }
21814             else
21815             {
21816 #ifdef DEBUG
21817                 if (verbose)
21818                 {
21819                     printf("\nConvert bbJumpKind of BB%02u to BBJ_NONE\n", block->bbNum);
21820                 }
21821 #endif // DEBUG
21822                 block->bbJumpKind = BBJ_NONE;
21823             }
21824         }
21825         if (inheritWeight)
21826         {
21827             block->inheritWeight(iciBlock);
21828             inheritWeight = false;
21829         }
21830         else
21831         {
21832             block->modifyBBWeight(iciBlock->bbWeight / 2);
21833         }
21834     }
21835
21836     // Insert inlinee's blocks into inliner's block list.
21837     topBlock->setNext(InlineeCompiler->fgFirstBB);
21838     InlineeCompiler->fgLastBB->setNext(bottomBlock);
21839
21840     //
21841     // Add inlinee's block count to inliner's.
21842     //
21843     fgBBcount += InlineeCompiler->fgBBcount;
21844
21845 #ifdef DEBUG
21846     if (verbose)
21847     {
21848         fgDispBasicBlocks(InlineeCompiler->fgFirstBB, InlineeCompiler->fgLastBB, true);
21849     }
21850 #endif // DEBUG
21851
21852 _Done:
21853
21854     //
21855     // At this point, we have successully inserted inlinee's code.
21856     //
21857
21858     //
21859     // Copy out some flags
21860     //
21861     compLongUsed              |= InlineeCompiler->compLongUsed;
21862     compFloatingPointUsed     |= InlineeCompiler->compFloatingPointUsed;
21863     compLocallocUsed          |= InlineeCompiler->compLocallocUsed;
21864     compQmarkUsed             |= InlineeCompiler->compQmarkUsed;
21865     compUnsafeCastUsed        |= InlineeCompiler->compUnsafeCastUsed;
21866     compNeedsGSSecurityCookie |= InlineeCompiler->compNeedsGSSecurityCookie;
21867     compGSReorderStackLayout  |= InlineeCompiler->compGSReorderStackLayout;
21868
21869     // Update optMethodFlags
21870
21871 #ifdef DEBUG
21872     unsigned optMethodFlagsBefore = optMethodFlags;
21873 #endif
21874
21875     optMethodFlags |= InlineeCompiler->optMethodFlags;
21876
21877 #ifdef DEBUG
21878     if (optMethodFlags != optMethodFlagsBefore)
21879     {
21880         JITDUMP("INLINER: Updating optMethodFlags --  root:%0x callee:%0x new:%0x\n",
21881                 optMethodFlagsBefore, InlineeCompiler->optMethodFlags, optMethodFlags);
21882     }
21883 #endif
21884
21885     // If there is non-NULL return, replace the GT_CALL with its return value expression,
21886     // so later it will be picked up by the GT_RET_EXPR node.
21887     if ((pInlineInfo->inlineCandidateInfo->fncRetType != TYP_VOID) || (iciCall->gtCall.gtReturnType == TYP_STRUCT))
21888     {
21889         noway_assert(pInlineInfo->retExpr);
21890 #ifdef DEBUG
21891         if (verbose)
21892         {
21893             printf("\nReturn expression for call at ");
21894             printTreeID(iciCall);
21895             printf(" is\n");
21896             gtDispTree(pInlineInfo->retExpr);
21897         }
21898 #endif // DEBUG
21899         // Replace the call with the return expression
21900         iciCall->CopyFrom(pInlineInfo->retExpr, this);
21901     }
21902
21903     //
21904     // Detach the GT_CALL node from the original statement by hanging a "nothing" node under it,
21905     // so that fgMorphStmts can remove the statement once we return from here.
21906     //
21907     iciStmt->gtStmt.gtStmtExpr = gtNewNothingNode();
21908 }
21909
21910 // Prepend the statements that are needed before the inlined call.
21911 // Return the last statement that is prepended.
21912
21913 GenTreePtr      Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
21914 {
21915     BasicBlock* block = inlineInfo->iciBlock;
21916
21917     GenTreePtr callStmt  = inlineInfo->iciStmt;
21918     noway_assert(callStmt->gtOper == GT_STMT);
21919     IL_OFFSETX callILOffset = callStmt->gtStmt.gtStmtILoffsx;
21920
21921     GenTreePtr afterStmt = callStmt; // afterStmt is the place where the new statements should be inserted after.
21922     GenTreePtr newStmt;
21923
21924     GenTreePtr call = inlineInfo->iciCall;
21925     noway_assert(call->gtOper == GT_CALL);
21926
21927 #ifdef DEBUG
21928     if (0 && verbose)
21929     {
21930         printf("\nfgInlinePrependStatements for iciCall= ");
21931         printTreeID(call);
21932         printf(":\n");
21933     }
21934 #endif
21935
21936     // Prepend statements for any initialization / side effects
21937
21938     InlArgInfo*       inlArgInfo = inlineInfo->inlArgInfo;
21939     InlLclVarInfo*    lclVarInfo = inlineInfo->lclVarInfo;
21940
21941     GenTreePtr tree;
21942
21943     // Create the null check statement (but not appending it to the statement list yet) for the 'this' pointer if necessary.
21944     // The NULL check should be done after "argument setup statements".
21945     // The only reason we move it here is for calling "impInlineFetchArg(0,..." to reserve a temp
21946     // for the "this" pointer.
21947     // Note: Here we no longer do the optimization that was done by thisDereferencedFirst in the old inliner.
21948     // However the assetionProp logic will remove any unecessary null checks that we may have added
21949     //
21950     GenTreePtr nullcheck = nullptr;
21951
21952     if (call->gtFlags & GTF_CALL_NULLCHECK && !inlineInfo->thisDereferencedFirst)
21953     {
21954         // Call impInlineFetchArg to "reserve" a temp for the "this" pointer.
21955         nullcheck = gtNewOperNode(GT_IND, TYP_INT,
21956                                   impInlineFetchArg(0, inlArgInfo, lclVarInfo));
21957         nullcheck->gtFlags |= GTF_EXCEPT;
21958
21959         // The NULL-check statement will be inserted to the statement list after those statements
21960         // that assign arguments to temps and before the actual body of the inlinee method.
21961     }
21962
21963     /* Treat arguments that had to be assigned to temps */
21964     if (inlineInfo->argCnt)
21965     {
21966
21967 #ifdef DEBUG
21968         if (verbose)
21969         {
21970             printf("\nArguments setup:\n");
21971         }
21972 #endif // DEBUG
21973
21974         for (unsigned argNum = 0; argNum < inlineInfo->argCnt; argNum++)
21975         {
21976             if (inlArgInfo[argNum].argHasTmp)
21977             {
21978                 noway_assert(inlArgInfo[argNum].argIsUsed);
21979
21980                 /* argBashTmpNode is non-NULL iff the argument's value was
21981                    referenced exactly once by the original IL. This offers an
21982                    oppportunity to avoid an intermediate temp and just insert
21983                    the original argument tree.
21984
21985                    However, if the temp node has been cloned somewhere while
21986                    importing (e.g. when handling isinst or dup), or if the IL
21987                    took the address of the argument, then argBashTmpNode will
21988                    be set (because the value was only explicitly retrieved
21989                    once) but the optimization cannot be applied.
21990                  */
21991
21992                 GenTreePtr argSingleUseNode = inlArgInfo[argNum].argBashTmpNode;
21993
21994                 if (argSingleUseNode &&
21995                     !(argSingleUseNode->gtFlags & GTF_VAR_CLONED) &&
21996                     !inlArgInfo[argNum].argHasLdargaOp &&
21997                     !inlArgInfo[argNum].argHasStargOp)
21998                 {
21999                     // Change the temp in-place to the actual argument.
22000                     // We currently do not support this for struct arguments, so it must not be a GT_OBJ.
22001                     GenTree* argNode = inlArgInfo[argNum].argNode;
22002                     assert(argNode->gtOper != GT_OBJ);
22003                     argSingleUseNode->CopyFrom(argNode, this);
22004                     continue;
22005                 }
22006                 else
22007                 {
22008                     /* Create the temp assignment for this argument */
22009
22010                     CORINFO_CLASS_HANDLE structHnd = DUMMY_INIT(0);
22011
22012                     if (varTypeIsStruct(lclVarInfo[argNum].lclTypeInfo))
22013                     {
22014                         structHnd = gtGetStructHandleIfPresent(inlArgInfo[argNum].argNode);
22015                         noway_assert(structHnd != NO_CLASS_HANDLE);
22016                     }
22017
22018                     // Unsafe value cls check is not needed for argTmpNum here since in-linee compiler instance would have
22019                     // iterated over these and marked them accordingly.
22020                     impAssignTempGen(inlArgInfo[argNum].argTmpNum,
22021                                      inlArgInfo[argNum].argNode,
22022                                      structHnd,
22023                                      (unsigned)CHECK_SPILL_NONE,
22024                                      & afterStmt,
22025                                      callILOffset,
22026                                      block);
22027
22028 #ifdef DEBUG
22029                     if (verbose)
22030                     {
22031                         gtDispTree(afterStmt);
22032                     }
22033 #endif // DEBUG
22034
22035                 }
22036             }
22037             else if (inlArgInfo[argNum].argIsByRefToStructLocal)
22038             {
22039                 // Do nothing.
22040             }
22041             else
22042             {
22043                 /* The argument is either not used or a const or lcl var */
22044
22045                 noway_assert(!inlArgInfo[argNum].argIsUsed  ||
22046                               inlArgInfo[argNum].argIsInvariant ||
22047                               inlArgInfo[argNum].argIsLclVar );
22048
22049                 /* Make sure we didnt change argNode's along the way, or else
22050                    subsequent uses of the arg would have worked with the bashed value */
22051                 if (inlArgInfo[argNum].argIsInvariant)
22052                 {
22053                     assert(inlArgInfo[argNum].argNode->OperIsConst() ||
22054                            inlArgInfo[argNum].argNode->gtOper == GT_ADDR);
22055                 }
22056                 noway_assert((inlArgInfo[argNum].argIsLclVar == 0) ==
22057                              (inlArgInfo[argNum].argNode->gtOper != GT_LCL_VAR || (inlArgInfo[argNum].argNode->gtFlags & GTF_GLOB_REF)));
22058
22059                 /* If the argument has side effects, append it */
22060
22061                 if (inlArgInfo[argNum].argHasSideEff)
22062                 {
22063                     noway_assert(inlArgInfo[argNum].argIsUsed == false);
22064
22065                     if (inlArgInfo[argNum].argNode->gtOper == GT_OBJ ||
22066                         inlArgInfo[argNum].argNode->gtOper == GT_MKREFANY)
22067                     {
22068                         // Don't put GT_OBJ node under a GT_COMMA.
22069                         // Codegen can't deal with it.
22070                         // Just hang the address here in case there are side-effect.
22071                         newStmt = gtNewStmt(gtUnusedValNode(inlArgInfo[argNum].argNode->gtOp.gtOp1), callILOffset);
22072                     }
22073                     else
22074                     {
22075                         newStmt = gtNewStmt(gtUnusedValNode(inlArgInfo[argNum].argNode), callILOffset);
22076                     }
22077                     afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
22078
22079 #ifdef DEBUG
22080                     if (verbose)
22081                     {
22082                         gtDispTree(afterStmt);
22083                     }
22084 #endif // DEBUG
22085
22086                 }
22087             }
22088         }
22089     }
22090
22091     // Add the CCTOR check if asked for.
22092     // Note: We no longer do the optimization that is done before by staticAccessedFirstUsingHelper in the old inliner.
22093     //       Therefore we might prepend redundant call to HELPER.CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
22094     //       before the inlined method body, even if a static field of this type was accessed in the inlinee
22095     //       using a helper before any other observable side-effect.
22096
22097     if (inlineInfo->inlineCandidateInfo->initClassResult & CORINFO_INITCLASS_USE_HELPER)
22098     {
22099         CORINFO_CONTEXT_HANDLE exactContext = inlineInfo->inlineCandidateInfo->exactContextHnd;
22100         CORINFO_CLASS_HANDLE exactClass;
22101
22102         if (((SIZE_T)exactContext & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS)
22103         {
22104             exactClass = CORINFO_CLASS_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK);
22105         }
22106         else
22107         {
22108             exactClass = info.compCompHnd->getMethodClass(CORINFO_METHOD_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK));
22109         }
22110
22111         tree = fgGetSharedCCtor(exactClass);
22112         newStmt = gtNewStmt(tree, callILOffset);
22113         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
22114     }
22115
22116     // Insert the nullcheck statement now.
22117     if (nullcheck)
22118     {
22119         newStmt = gtNewStmt(nullcheck, callILOffset);
22120         afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
22121     }
22122
22123     //
22124     // Now zero-init inlinee locals
22125     //
22126
22127     CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo;
22128
22129     unsigned lclCnt = InlineeMethodInfo->locals.numArgs;
22130
22131     // Does callee contain any zero-init local?
22132     if ((lclCnt != 0) &&
22133         (InlineeMethodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0)
22134     {
22135
22136 #ifdef DEBUG
22137         if (verbose)
22138         {
22139             printf("\nZero init inlinee locals:\n");
22140         }
22141 #endif // DEBUG
22142
22143         for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++)
22144         {
22145             unsigned  tmpNum = inlineInfo->lclTmpNum[lclNum];
22146
22147             // Is the local used at all?
22148             if (tmpNum != BAD_VAR_NUM)
22149             {
22150                 var_types lclTyp = (var_types)lvaTable[tmpNum].lvType;
22151                 noway_assert(lclTyp == lclVarInfo[lclNum + inlineInfo->argCnt].lclTypeInfo);
22152
22153                 if (!varTypeIsStruct(lclTyp))
22154                 {
22155                     // Unsafe value cls check is not needed here since in-linee compiler instance would have
22156                     // iterated over locals and marked accordingly.
22157                     impAssignTempGen(tmpNum,
22158                                      gtNewZeroConNode(genActualType(lclTyp)),
22159                                      NO_CLASS_HANDLE,
22160                                      (unsigned)CHECK_SPILL_NONE,
22161                                      & afterStmt,
22162                                      callILOffset,
22163                                      block);
22164                 }
22165                 else
22166                 {
22167                     CORINFO_CLASS_HANDLE structType = lclVarInfo[lclNum + inlineInfo->argCnt].lclVerTypeInfo.GetClassHandle();
22168
22169                     tree = gtNewOperNode(GT_ADDR, TYP_BYREF,
22170                                          gtNewLclvNode(tmpNum, lclTyp));
22171
22172                     tree = gtNewBlkOpNode(GT_INITBLK,
22173                                           tree,             // Dest
22174                                           gtNewIconNode(0), // Value
22175                                           gtNewIconNode(info.compCompHnd->getClassSize(structType)), // Size
22176                                           false);           // volatil
22177
22178                     newStmt = gtNewStmt(tree, callILOffset);
22179                     afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt);
22180                 }
22181
22182 #ifdef DEBUG
22183                 if (verbose)
22184                 {
22185                     gtDispTree(afterStmt);
22186                 }
22187 #endif // DEBUG
22188             }
22189         }
22190     }
22191
22192     return afterStmt;
22193 }
22194
22195
22196 /*****************************************************************************/
22197 /*static*/
22198 Compiler::fgWalkResult  Compiler::fgChkThrowCB(GenTreePtr* pTree,
22199                                                fgWalkData* data)
22200 {
22201     GenTreePtr tree = *pTree;
22202
22203     // If this tree doesn't have the EXCEPT flag set, then there is no
22204     // way any of the child nodes could throw, so we can stop recursing.
22205     if (!(tree->gtFlags & GTF_EXCEPT))
22206     {
22207         return Compiler::WALK_SKIP_SUBTREES;
22208     }
22209
22210     switch (tree->gtOper)
22211     {
22212     case GT_MUL:
22213     case GT_ADD:
22214     case GT_SUB:
22215     case GT_ASG_ADD:
22216     case GT_ASG_SUB:
22217     case GT_CAST:
22218         if (tree->gtOverflow()) {
22219             return Compiler::WALK_ABORT;
22220 }
22221         break;
22222
22223     case GT_INDEX:
22224         if (tree->gtFlags & GTF_INX_RNGCHK) {
22225             return Compiler::WALK_ABORT;
22226 }
22227         break;
22228
22229     case GT_ARR_BOUNDS_CHECK:
22230         return Compiler::WALK_ABORT;
22231
22232     default:
22233         break;
22234     }
22235
22236     return Compiler::WALK_CONTINUE;
22237 }
22238
22239 /*****************************************************************************/
22240 /*static*/
22241 Compiler::fgWalkResult  Compiler::fgChkLocAllocCB(GenTreePtr* pTree,
22242                                                   fgWalkData* data)
22243 {
22244     GenTreePtr tree = *pTree;
22245
22246     if (tree->gtOper == GT_LCLHEAP) {
22247         return Compiler::WALK_ABORT;
22248 }
22249
22250     return Compiler::WALK_CONTINUE;
22251 }
22252
22253 /*****************************************************************************/
22254 /*static*/
22255 Compiler::fgWalkResult  Compiler::fgChkQmarkCB(GenTreePtr* pTree,
22256                                                fgWalkData* data)
22257 {
22258     GenTreePtr tree = *pTree;
22259
22260     if (tree->gtOper == GT_QMARK) {
22261         return Compiler::WALK_ABORT;
22262 }
22263
22264     return Compiler::WALK_CONTINUE;
22265 }
22266
22267
22268 void Compiler::fgLclFldAssign(unsigned lclNum)
22269 {
22270     assert(varTypeIsStruct(lvaTable[lclNum].lvType));
22271     if (lvaTable[lclNum].lvPromoted && lvaTable[lclNum].lvFieldCnt > 1)
22272     {
22273         lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField));
22274     }
22275 }